[英]iAd freezes Sprite Kit app
我發現點擊iAd可以凍結任何Sprite Kit游戲的屏幕。 這不僅是我的特定項目,因為庫存Sprite Kit示例項目也隨iAd凍結。 但是,這不會在模擬器中發生! 我無法確定是因為模擬器運行iOS 8且我的實際測試設備位於7.1上,還是因為模擬器僅僅是一個模擬器,所以它所做的事情有所不同。
因此,如果您點擊iAd,然后單擊iAd中的鏈接以進行野生動物園(或此時手動切換到任何應用),然后再切換回Sprite Kit應用,則該應用將被凍結。 iAd標語仍然有效,並且按預期加載廣告。 但是該應用程序的其余部分已凍結。 更具體地說,它仍然可以接收觸摸和填充(我可以從NSLog
看到),但是節點的呈現被凍結了。 如果您通過點擊再次打開iAd,然后關閉iAd,則該應用會以某種方式恢復運行,並且可以正常運行。
如果您好奇,這是我對Sprite Kit示例項目所做的唯一修改:
// in GameViewController.h
#import <iAd/iAd.h>
@interface GameViewController : UIViewController <ADBannerViewDelegate>
@end
// in GameViewController.m
@interface GameViewController() {
ADBannerView* iAdBanner;
NSLayoutConstraint* centerAd;
}
@end
@implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure iAd
iAdBanner = [[ADBannerView alloc] initWithFrame:CGRectZero];
iAdBanner.alpha = 0.0;
iAdBanner.delegate = self;
centerAd = [NSLayoutConstraint constraintWithItem:iAdBanner
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0];
[self.view addSubview:iAdBanner];
[self.view addConstraint:centerAd];
// The rest of viewDidLoad is the stock code. I'm not pasting that in...
}
// iAd delegate methods
-(void) bannerViewDidLoadAd:(ADBannerView *)banner {
// fade in iAd banner
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[banner setAlpha:1.0];
[UIView commitAnimations];
}
-(void) bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
NSLog(@"iAd error: %@", error.localizedDescription);
banner.alpha = 0.0;
}
另外,我將部署目標設置為7.1(並且顯然在項目中包括了iAd框架)。
如您所見,我沒有對可能導致此崩潰的應用程序執行任何操作。 我只需添加iAd橫幅即可。 因此,問題不在我的代碼中。 這一定是Apple框架中的錯誤。
有誰知道解決方法? 我在互聯網上找到了一些與此相關的主題,但是沒有人可以提出可行的解決方案。
編輯:
我發現我的設備上的iOS 7.1在返回應用程序時調用bannerViewActionDidFinish:
但是,模擬器中的iOS 8會在離開應用程序之前調用該方法(確切地說,確切地說是在離開應用程序時)。 這不會直接影響上面發布的代碼,因為它沒有實現此方法。 但這確實表明iAd實現iOS 7.1和iOS 8的功能有所不同。
- 編輯2的最終答案 -
好吧,我之前確實讀過關於此的內容,並且確實嘗試過,但是當我較早嘗試時似乎失敗了。 我再次嘗試過,現在可以使用了。
因此,您要做的是將視圖控制器的canDisplayBannerAds
屬性設置為YES
,然后使用originalContentView
屬性而不是普通view
設置SKView
。 或者,如果您想從場景內部訪問視圖,則為: self.view.window.rootViewController.originalContentView
。 因此,基本上,任何時候您都需要對視圖進行特定於SKView
(例如過渡到場景),而常規UIView
無法完成的操作則使用scene.view.window.rootViewController.originalContentView
而不是僅僅scene.view
。 原因是當在視圖控制器中設置canDisplayBannerAds
屬性時,iAd會以某種方式將視圖明確轉換為UIView
,因此您將無法再在視圖上使用SKView
方法。 originalContentView
是解決此問題的方法。
這完全解決了我的問題,該應用現在恢復到正常狀態。
不,這沒有解決我的問題。 :(
現在,在打開廣告的同時切換到另一個應用程序並不會凍結該應用程序。 好。 但是,現在只需打開和關閉廣告就可以凍結廣告。 這沒有道理...
因此,如果我未在視圖控制器中設置canDisplayBannerAds
,則在應用程序凍結時會離開應用程序並返回。 但是只是打開和關閉廣告就可以了。 但是,如果我確實設置了canDisplayBannerAds
,那么canDisplayBannerAds
。
這真的沒有道理。 我現在很困惑
終於我解決了! 但是,天哪,這不是一件容易的事……所以問題出在視圖層次結構中。 如果我將ADBannerView
添加為主視圖的子視圖,則它將凍結該應用程序。 這很奇怪,因為這是將標語添加到屏幕的建議方法。 如果我沒有將橫幅手動添加為子視圖,則它仍會出現在屏幕上! 我猜iAd的實現方式是一旦初始化,無論如何它都會在屏幕上顯示自己。 看起來卻有些不同。 如果它不是任何視圖的子視圖,那么它將從底部以“向上滑動”動畫出現,將所有內容調整為上方的一個較小的框。 我猜這是iAd標語的默認行為。 因此,這種方式不會凍結屏幕,效果很好! 但是由於我想要對橫幅進行更多控制(例如自己制作動畫,而不是將其留給橫幅本身),所以我執行了以下操作:
在我的視圖控制器,我創建的實例SKView
(沒有因鑄造self.view
作為SKView
像往常一樣,但一個完全新的實例)。 然后我將其添加為self.view
的子視圖。 在那之后,我初始化ADBannerView
,並將其添加為一個子視圖self.view
為好。 注意self.view
不會直接顯示任何內容,我將其用作容納其他兩個的“容器”。 然后,視圖層次結構如下所示:
self.view
/ \
SKView ADBannerView
這樣, ADBannerView
並不是我的SKView的直接子視圖或超級視圖(這是我的游戲使用的主視圖),因此它無法搞砸,因為它沒有該視圖的概念,因為它們都是同一個視圖的子視圖。 目前,我不知道是否需要在視圖控制器中設置canDisplayBannerAds
。 我已經設置好了,而且有效。 我沒有嘗試過把它排除在外。
簡而言之,我可以完全控制橫幅視圖和游戲視圖,並且由於它們不在子視圖/超級視圖關系中,因此它們不會彼此混亂。
這很難弄清楚,但是到這里開始。 如果您在iAd和Sprite Kit方面也遇到問題,只需像這樣整理視圖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.