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的问题,就像这样整理你的视图。