iAd冻结了Sprite Kit应用程序
我发现点击iAds可以冻结任何Sprite Kit游戏的屏幕。 这不只是我的具体项目,因为股票的Sprite Kit示例项目也冻结与iAd。 尽pipe这在模拟器中不会发生! 我不能决定是否是因为模拟器运行iOS 8,而我的实际testing设备是7.1,或者是因为模拟器只是一个模拟器,所以它做的事情不同。
所以,如果你点击iAd,然后点击iAd中的链接去Safari浏览器(或者手动切换到任何应用程序),然后切换回Sprite Kit应用程序,应用程序被冻结。 iAd横幅广告仍处于运行状态,它会根据广告的预期方式加载广告。 但其他应用程序被冻结。 或者具体来说,它仍然接受触摸和东西(我可以从NSLog
看到),但节点的渲染被冻结。 如果你点击它再次打开iAd,并closuresiAd,那么应用程序会以某种方式恢复,并且再次正常工作。
如果您好奇,这里是我对股票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横幅即可。 所以这个问题不在我的代码中。 这肯定是苹果框架中的一个错误。
有谁知道一个解决方法? 我在网上find了几个关于这方面的话题,但没有人能提出一个可行的解决scheme。
编辑:
我发现我的设备上的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
是解决这个问题的方法。
这完全解决了我的问题,现在应用程序恢复到正常状态。
编辑:
不,它没有解决我的问题。 🙁
现在打开广告时切换到另一个应用程序,并不会冻结该应用程序。 好。 但是,现在只需打开和closures广告,就能以同样的方式冻结广告。 这没有意义…
所以如果我没有在我的视图控制器中设置canDisplayBannerAds
,那么离开应用程序并返回时,应用程序冻结的情况下。 但是只要打开和closures一个广告就行得通。 但是,如果我确实设置了canDisplayBannerAds
,那么这是另一canDisplayBannerAds
。
这真的没有意义。 我现在很困惑
编辑2(实际解决scheme):
最后我解决了它! 但是这不是件容易的事,所以问题出在视图层次上。 如果我将ADBannerView
作为主视图的子视图添加,则会冻结该应用程序。 这很奇怪,因为这是向屏幕添加横幅的build议方法。 如果我不手动添加横幅作为子视图,但它仍然出现在屏幕上! 我想iAd是以一种初始化的方式实现的,无论如何它都会在屏幕上显示自己。 这看起来有点不同。 如果它不是任何视图的子视图,那么它会从底部以“向上滑动”animation进行显示,将所有视图的大小调整为小于它的较小框。 这是一个iAd横幅的默认行为,我猜。 所以这样它不冻结屏幕,它工作得很好! 但是因为我想要更多地控制横幅(就像我自己animation一样,而不是把它留给横幅本身),我做了以下工作:
在我的视图控制器中,我创build了一个SKView
的实例(不像通常那样将SKView
视为SKView
,而是一个全新的实例)。 然后我将其添加为self.view
的子视图。 之后,我初始化ADBannerView
,并将其作为ADBannerView
的子视图添加。 请注意, self.view
并不直接显示任何东西,我用它作为“容器”来容纳另外两个。 视图层次结构如下所示:
self.view / \ SKView ADBannerView
这样ADBannerView
不是我的SKView的直接子视图或超级视图(这是我的游戏使用的主视图),所以它不能把它搞砸,因为它没有这个视图的概念,因为它们都是同一视图的子视图。 在这一点上,我不知道你是否需要在你的视图控制器中设置canDisplayBannerAds
。 我已经设定好了,而且还行得通。 我没有试着离开。
简而言之,我完全控制了横幅视图以及我的游戏视图,并且由于它们不处于子视图/超视图关系中,所以它们不能彼此混淆。
这很难弄清楚,但是在这里你走了。 如果你也有iAd和Sprite Kit的问题,就像这样整理你的视图。