【问题标题】:Hide/Show iAds in Spritekit在 Spritekit 中隐藏/显示 iAd
【发布时间】:2014-02-09 20:03:41
【问题描述】:

我一直试图弄清楚如何在我的 Spritekit 场景中隐藏和显示 iAd。目前我有这样的设置:

ViewController.h

#import <UIKit/UIKit.h>
#import <SpriteKit/SpriteKit.h>
#import <iAd/iAD.h>


@interface ViewController : UIViewController <ADBannerViewDelegate> {

    ADBannerView *adView;

}

-(void)showsBanner;
-(void)hidesBanner;



@end

ViewController.m

#import "ViewController.h"
#import <UIKit/UIKit.h>
#import <iAd/iAD.h>
#import "MyScene.h"

#import <SpriteKit/SpriteKit.h>


@implementation ViewController

- (void)viewDidLoad
{

    [super viewDidLoad];

    // Configure the view.
    SKView * skView = (SKView *)self.view;
    skView.showsFPS = NO;
    skView.showsNodeCount = NO;

    // Create and configure the scene.
    SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    // Present the scene.
    [skView presentScene:scene];
    self.canDisplayBannerAds = YES;

    adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
    adView.frame = CGRectOffset(adView.frame, 0, 0.0f);
    adView.delegate=self;
    [self.view addSubview:adView];

    self.bannerIsVisible=NO;

}

-(void)bannerViewDidLoadAd:(ADBannerView *)banner {
    if (!self.bannerIsVisible) {
        [UIView beginAnimations:@"animatedAdBannerOn" context:NULL];
        banner.frame = CGRectOffset(banner.frame, 0.0, 0.0);
        [UIView commitAnimations];
        self.bannerIsVisible = YES;
    }}

-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
    if (!self.bannerIsVisible) {
        [UIView beginAnimations:@"animatedAdBannerOff" context:NULL];
        banner.frame = CGRectOffset(banner.frame, 0.0, 0.0);
       [adView setAlpha:0];
        [UIView commitAnimations];
        self.bannerIsVisible = NO;
    }
}

-(void)hidesBanner {

    NSLog(@"HIDING BANNER");
    [adView setAlpha:0];
    self.bannerIsVisible = NO;
}


-(void)showsBanner {

    NSLog(@"SHOWING BANNER");
    [adView setAlpha:1];
    self.bannerIsVisible = YES;

}


etc...


@end

然后在我的场景中,我用指针抓住我的视图控制器:

ViewController *controller;


controller = [[ViewController alloc] init];
[controller hidesBanner];

我的 nslog 在控制台中运行,所以我知道它正在运行。但横幅不会隐藏。有什么想法吗?我对 Objective c 很陌生,所以我觉得我只是在做一些愚蠢的事情。

【问题讨论】:

  • 为什么使用 alpha 而不是 ADBannerView 的 hidden 属性(继承自 UIView)?
  • 因为我在这里找到了答案:stackoverflow.com/questions/20577465/… 使用隐藏属性似乎无法解决我的问题。

标签: ios objective-c iad viewcontroller sprite-kit


【解决方案1】:

就像 Huygamer 所说,您正在创建视图控制器的新实例,因此当您调用方法 [controller hidesBanner]; 时,您指的是另一个对象。

这里最好的方法是使用NSNotificationCenter:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html

并在您想要隐藏或显示广告时向您的视图控制器发送消息:

ViewController.m

 - (void)viewDidLoad
 {

        [super viewDidLoad];

         //Add view controller as observer
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"hideAd" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"showAd" object:nil];

        // Configure the view.
        SKView * skView = (SKView *)self.view;
        skView.showsFPS = NO;
        skView.showsNodeCount = NO;

        // Create and configure the scene.
        SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
        scene.scaleMode = SKSceneScaleModeAspectFill;

        // Present the scene.
        [skView presentScene:scene];
        self.canDisplayBannerAds = YES;

        adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
        adView.frame = CGRectOffset(adView.frame, 0, 0.0f);
        adView.delegate=self;
        [self.view addSubview:adView];

        self.bannerIsVisible=NO;  
 }

    //Handle Notification
 - (void)handleNotification:(NSNotification *)notification
 { 
    if ([notification.name isEqualToString:@"hideAd"]) {
        [self hidesBanner];
    }else if ([notification.name isEqualToString:@"showAd"]) {
        [self showBanner];
    }
 }

在你的场景中:

 [[NSNotificationCenter defaultCenter] postNotificationName:@"showAd" object:nil]; //Sends message to viewcontroller to show ad.

 [[NSNotificationCenter defaultCenter] postNotificationName:@"hideAd" object:nil]; //Sends message to viewcontroller to hide ad.

【讨论】:

    【解决方案2】:

    当然,有 2 个对象,为什么你认为它可以做到?

    如果您想访问 skscene 的父级,只需执行此操作

    UIViewController *vc = self.view.window.rootViewController;

    您可以访问此 skscene 的父级,并且可以在此场景的父级处执行 hideBanner。简单吗?

    【讨论】:

    • 这破坏了 MVC 架构,应该避免。
    【解决方案3】:

    这是我为使其与 SpriteKit 场景(iPhone 6 上的 Xcode 6.1 和 iOS 8.1)一起使用所做的工作:

    步骤 1- 在 MyScene.h 头文件中添加#import

    第 2 步 - 确保在 MyScene.h 头文件中声明您的 MyScene 类以实现协议。

    第 3 步 - 在 MyScene.m 文件中添加以下代码行 -(Void)didMoveToView:(SKView *)view 函数。

    ADBannerView* banner=[[ADBannerView alloc]initWithFrame:CGRectZero];
    CGRect bannerFrame =CGRectMake(0, 667, self.view.frame.size.width, 0);
    banner.frame=bannerFrame;
    [self.view addSubview:banner];
    banner.delegate=self;
    

    步骤 4- 实现 iAd 的两种方法

    -(void)bannerViewDidLoadAd:(ADBannerView *)banner
     {
       CGRect bannerFrame =CGRectMake(0, 667-50, self.view.frame.size.width, 0);
       [UIView beginAnimations:nil context:nil];
       [UIView setAnimationDuration:1];
       banner.frame=bannerFrame;
       [UIView commitAnimations];
    
      }
    
     -(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
     {
       CGRect bannerFrame =CGRectMake(0, 667, self.view.frame.size.width, 0);
       [UIView beginAnimations:nil context:nil];
       [UIView setAnimationDuration:1];
       banner.frame=bannerFrame;
       [UIView commitAnimations];
     }
    

    上面的代码会在有广告时将广告框架移动到场景中,如果没有广告,则会通过动画移动来移除框架。请注意,框架矩形中的最后一个数字是 0。无论您放什么,横幅高度都是固定的,不会改变(50 pt)。

    第 5 步 - 通过此代码响应广告操作:

      -(void)bannerViewActionDidFinish:(ADBannerView *)banner
       {
        [self startTimer];
    
       }
    
       -(BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
         {
    
           [gameTimer invalidate];
    
           return YES;
          }
    

    此代码将在用户单击横幅时停止游戏计时器,并在用户返回游戏后恢复游戏计时器。您可以在此处添加自己的代码来保存和检索游戏数据。

    希望这会有所帮助。

    【讨论】:

    • 谢谢!为我工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多