iAd冻结Sprite Kit应用程序 [英] iAd freezes Sprite Kit app

查看:81
本文介绍了iAd冻结Sprite Kit应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现点击iAd可以冻结任何Sprite Kit游戏的屏幕.这不仅是我的特定项目,因为库存Sprite Kit示例项目也随iAd冻结.但是,这不会在模拟器中发生!我无法确定是因为模拟器运行iOS 8且我的实际测试设备位于7.1上,还是因为模拟器仅仅是一个模拟器,所以它做的事情有所不同.

I find that tapping on iAds can freeze the screen on any Sprite Kit game. It's not just my specific project, since the stock Sprite Kit example project also freezes with iAd. This does not happen in the simulator though! I cannot decide whether if it's because the simulator runs iOS 8 and my actual testing device is on 7.1, or because of the fact that the simulator is just a simulator so it does things differently.

因此,如果您点击iAd,然后单击iAd中的链接以进行野生动物园(或此时手动切换到任何应用),然后再切换回Sprite Kit应用,则该应用将被冻结. iAd标语仍然有效,并且按预期加载广告.但是该应用程序的其余部分已冻结.更具体地说,它仍然接收触摸和填充(我可以从NSLog中看到),但是节点的渲染被冻结了.如果您通过点击再次打开iAd,然后关闭iAd,则该应用会以某种方式恢复运行,并且可以正常运行.

So if you tap on the iAd then click on the link in the iAd to go to safari (or manually switch over to any app at this point), then switch back to the Sprite Kit app, the app is frozen. The iAd banner is still live, and it loads ads just how it's supposed to. But the rest of the app is frozen. Or to be specific, It still receives touches and stuff (I can see from NSLogs) but the rendering of the nodes is frozen. If you open up iAd again by tapping on it, and close the iAd, then the app resumes somehow and it works again just fine.

如果您感到好奇,这是我对Sprite Kit示例项目所做的唯一修改:

If you're curious, here are the ONLY modifications that I did to the stock Sprite Kit example project:

// 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框架).

Plus I set the deployment target to 7.1 (and obviously include the iAd framework in the project).

如您所见,我没有对可能导致此崩溃的应用程序执行任何操作.我只需添加iAd横幅即可.因此,问题不在我的代码中.这一定是Apple框架中的错误.

As you can see, I'm not doing anything to the app that could cause this crash. I simply add the iAd banner and that's it. So the problem is not in my code. This must be a bug in Apple's frameworks.

有人知道解决方法吗?我在互联网上找到了几个与此相关的主题,但是没有人可以提出可行的解决方案.

Does anyone know a workaround? I have found several topics on this on the internet, but nobody could suggest a working solution.

我发现我的设备上的iOS 7.1在返回应用程序时会调用bannerViewActionDidFinish: .但是,模拟器中的iOS 8在离开应用程序之前会调用该方法(确切地说,确切地说,当您离开应用程序时).这不会直接影响上面发布的代码,因为它没有实现此方法.但这确实表明iAd实施iOS 7.1和iOS 8的功能有所不同.

I found out that iOS 7.1 on my device calls bannerViewActionDidFinish: when returning to the app. iOS 8 in the simulator however, calls that method before leaving the app (exactly when you leave the app to be exact). That doesn't directly affect the code posted above, since it doesn't implement this method. But it does indicate that the iAd implementations iOS 7.1 and iOS 8 do things differently.

推荐答案

--- 编辑2中的最终答案 ---

好吧,我之前确实读过这篇文章,并且确实尝试过,但是当我较早尝试过时似乎失败了.我再次尝试过,现在可以使用了.

Well I did read about this before, and I did try it, but seems like I failed when I tried it earlier. I tried it again and it works now.

因此,您要做的是将视图控制器的canDisplayBannerAds属性设置为YES,然后使用originalContentView属性而不是普通的view属性来设置您的SKView.或者,如果您想从场景内部访问视图,则为:self.view.window.rootViewController.originalContentView.因此,基本上,任何时候您都需要对视图进行特定于SKView的操作(例如过渡到场景),而常规UIView无法完成的操作则使用scene.view.window.rootViewController.originalContentView而不是仅scene.view.原因是当在视图控制器中设置canDisplayBannerAds属性时,iAd会以某种方式显式将视图转换为UIView,因此您将无法再在视图上使用SKView方法. originalContentView是解决此问题的方法.

So what you want to do is set the canDisplayBannerAds property of your view controller to YES, then use the originalContentView property instead of the normal view one to set up your SKView. Or if you want to access your view from inside a scene, that would be: self.view.window.rootViewController.originalContentView. So basically any time you need to do something with your view that is specific to SKView (like transition to a scene) and what cannot be done with a regular UIView then use scene.view.window.rootViewController.originalContentView instead of just scene.view. The reason for this is that iAd somehow explicitly casts your view as UIView when you set the canDisplayBannerAds property in your view controller, so you cannot use the SKView methods on your view anymore. The originalContentView is a workaround for this.

这完全解决了我的问题,该应用现在恢复到正常状态.

This totally solved my problem, the app returns to its normal state now.

不,它不能解决我的问题. :(

Nope, it didn't solve my problem. :(

现在打开广告时切换到另一个应用程序并不会冻结该应用程序.好的.但是,现在只需打开和关闭广告即可以相同的方式冻结它.这是没有道理的...

Switching to another app and back while an ad is open now doesn't freeze the app. Good. But simply opening and closing an ad now freezes it the same way. This makes no sense...

因此,如果我未在视图控制器中设置canDisplayBannerAds,则在应用程序冻结时会离开应用程序并返回.但是只是打开和关闭广告就可以了.但是,如果我确实设置了canDisplayBannerAds,那么反之亦然.

So if I don't set canDisplayBannerAds in my view controller, then leaving the app and coming back is the case when the app freezes. But just opening and closing an ad works fine. But if I do set canDisplayBannerAds, then it's the other way around.

这真的没有道理.我现在很困惑...

This really makes no sense. I'm very confused now...

最后我解决了!但这真不容易,该死的... 因此,问题出在视图层次结构中.如果将ADBannerView添加为主视图的子视图,则它将冻结该应用程序.这很奇怪,因为这是将标语添加到屏幕的建议方法. 如果我没有将横幅手动添加为子视图,则它仍会出现在屏幕上!我猜iAd的实现方式是一旦初始化,无论如何它都会在屏幕上显示自己.看起来却有些不同.如果它不是任何视图的子视图,则它以向上滑动"的形式从底部进入.动画,将所有内容调整为上方的小方框.我猜这是iAd标语的默认行为.因此,这种方式不会冻结屏幕,效果很好!但是由于我想要对横幅进行更多控制(例如自己制作动画,而不是将其留给横幅本身),所以我执行了以下操作:

Finally I solved it! But it wasn't easy god damn it... So the problem was in the view hierarchy. If I add the ADBannerView as a subview of my main view, then it freezes the app. This is strange, since that's the suggested method to add a banner to the screen. If I don't add the banner as as subview manually, it sill appears on the screen though! I guess iAd is implemented in a way that once initialized, it will display itself on the screen no matter what. It appears a bit differently though. If it's not a subview of any view, then it comes in from the bottom with a "slide up" animation, resizing everything to a smaller box that's above it. This is a default behavior of an iAd banner I guess. So this way it doesn't freeze the screen, it works just fine! But since I wanted a bit more control over the banner (like animating it myself, instead of leaving that to the banner itself) I did the following:

在我的视图控制器中,创建了SKView的实例(不要像往常一样通过将self.view强制转换为SKView来创建,而是一个全新的实例).然后,我将其添加为self.view的子视图.之后,我初始化ADBannerView,并将其也添加为self.view的子视图.注意,self.view没有直接显示任何内容,我将其用作容器".容纳另外两个.然后,视图层次结构将如下所示:

In my view controller, I created an instance of SKView (NOT by casting self.view as SKView as usual, but a completely new instance). Then I added that as a subview of self.view. After that, I initialize the ADBannerView, and add it as a subview of self.view as well. Note that self.view is not directly displaying anything, I use it as a "container" to hold the other two. The view hierarchy then looks something like this:

        self.view
        /        \
    SKView    ADBannerView

这样,ADBannerView并不是我的SKView的直接子视图或超级视图(这是我的游戏使用的主视图),因此它无法搞砸,因为它没有该视图的概念,因为它们都是同一视图的子视图.在这一点上,我不知道是否需要在视图控制器中设置canDisplayBannerAds.我已经设置好了,并且可以正常工作.我没有尝试过把它排除在外.

This way the ADBannerView is not the direct subview or superview of my SKView (which is the main view my game uses) so it cannot screw it up because it doesn't have a concept of that view since they are both subviews of the same view. At this point I have no idea whether you need to set canDisplayBannerAds in your view controller or not. I have it set, and it works. I didn't try leaving that out.

简而言之,我可以完全控制横幅视图和游戏视图,而且由于它们不在子视图/超级视图关系中,所以它们不会彼此混乱.

In a nutshell, I have full control of the banner view as well as my game view, and they can't mess with each other since they are not in a subview/superview relationship.

这很难弄清楚,但是您就可以了.如果您在iAd和Sprite Kit方面也遇到了问题,只需像这样整理视图即可.

This was very tough to figure out, but here you go. If you also have problems with iAd and Sprite Kit, just organize your views like this.

这篇关于iAd冻结Sprite Kit应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆