【问题标题】:Interstitial iAds in SpriteKit?SpriteKit 中的插页式 iAd?
【发布时间】:2015-11-17 20:09:12
【问题描述】:

我正在为我的 iOS 应用程序使用 SpriteKit,并且需要一些全屏(或有时称为“插页式”iAds 以不时弹出。我可以找出何时发生的代码,但我需要知道如何添加 iAd 而无需更改视图控制器。

我尝试了 Techotopia 在 Interstitial iAds 上的 [tutorial][1],但要做到这一点,我需要在实际的视图控制器之间进行转换。好吧,我试过了,但是每当从 iAd 视图控制器转换回 GameViewController 时,它就搞砸了。 GameViewController.m 中的代码表明它最初设置为我的游戏(SKScene)的主菜单。因此,当我尝试从 iAd 转换回来时,不是保持相同的 SKScene,而是直接进入我的主菜单场景。

我需要这些答案:

  1. 除了使用两个视图控制器来显示插页式 iAd 之外,还有其他方法吗?
  2. 如果没有,我该如何解决这个问题?
  3. 如果我将“Interstitial iAds”更改为“Pre-roll Video iAds”,也会出现此问题吗?

-

编辑!编辑!编辑!编辑!编辑!编辑!编辑!编辑!编辑!编辑!编辑!编辑!编辑!编辑!

-

我最终决定使用 crashoverride777 的答案,并创建一个 Objective-C 桥接头将他的 Swift 代码转换为 Objective-C。但是当引用Ads.swift 的变量presentingViewController 时,它最终为零。这是我在GameViewController.m 中的代码:

// Set up interstitial iAds.
Ads *adsClass = [[Ads alloc] init];
Ads *adsInstance = [Ads sharedInstance];
adsInstance.presentingViewController = self;

然而,这并没有做任何事情。函数showInterAd 被我的GameScene.m 调用,就像它应该的那样,但没有广告出现。在我的Ads.swift 中,我添加了一个日志来查看presentingViewController 是否确实为nil。

print("iAd inter showing")
if (self.presentingViewController != nil) {
    print("presentingViewController != nil")
    iAdInterAdView.frame = presentingViewController.view.bounds
    presentingViewController.view.addSubview(iAdInterAdView)
    iAdInterAd!.presentInView(iAdInterAdView)
    UIViewController.prepareInterstitialAds()
    iAdInterAdView.addSubview(iAdInterAdCloseButton)
} else {
    print("presentingViewController == nil")
}

日志每次都这样输出:"presentingViewController == nil"。我不确定这里出了什么问题。

【问题讨论】:

  • 翻译:iAdInterAdCloseButton = [UIButton buttonWithType:UIButtonTypeSystem]if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
  • 为什么会给您带来麻烦?第一个按钮代码是 swift 2.0 中的新内容,因为它在 swift 之前略有不同。在对象 C 它应该看起来像这样我认为 UIButton *iAdInterAdCloseButton = [UIButton buttonWithType:UIButtonTypeSystem];
  • 关于设备代码。你的应用是通用的吗?否则,据我所知,它不会被调用?您可以阅读本文并尝试检查设备是否为 iPad stackoverflow.com/questions/10167221/… 的可能方法
  • 我可以尽我所能帮助你,因为我对 obj c 的了解有限。我相信大部分代码都很简单,所以我认为它不应该那么难。不确定 obj c 是否有扩展之类的东西,这是我用于代表的东西。
  • 我也在想,为什么不在那个 obj c 项目中使用 swift 文件并使用桥接头。对于较旧的应用程序来说,这可能是一个好主意developer.apple.com/library/ios/documentation/Swift/Conceptual/…

标签: ios sprite-kit iad viewcontroller interstitial


【解决方案1】:

您可以使用我在 github 上发布的助手。它是专门为 spritekit 制作的,您可以从任何地方调用广告,而无需代理等或更改视图控制器。

https://github.com/crashoverride777/Swift-2-iAds-and-AdMob-Helper

我认为看看那个助手应该会让你很好地了解从哪里开始。这是一个简化的示例,说明它如何仅适用于 iAds 国际广告。

这很快,所以我不确定它是否对你仍然有帮助。

import iAd

class Ads: NSObject {

// MARK: - Static Properties

/// Shared instance
static let sharedInstance = Ads()

// MARK: - Properties

/// Presenting view controller
var presentingViewController: UIViewController!

/// iAd inter ad
private var iAdInterAd: ADInterstitialAd?

/// iAd inter ad view
private var iAdInterAdView = UIView()

/// iAd inter ad close button
private var iAdInterAdCloseButton = UIButton(type: UIButtonType.System)

// MARK: - Init
private override init() {
    super.init()
    print("Ads helper init")

   iAdInterAd = iAdLoadInterAd()
}

// MARK: - User Methods

/// Show inter ad
func showInterAd() {
    iAdShowInterAd()
}

/// Show inter ad randomly (33% chance)
func showInterAdRandomly() {
    let randomInterAd = Int(arc4random() % 3)
    print("randomInterAd = \(randomInterAd)")
    if randomInterAd == 1 {
        iAdShowInterAd()
    }
}

/// Remove all ads
func removeAllAds() {
    print("Removed all ads")

    if iAdInterAd != nil {
        iAdInterAd!.delegate = nil
        iAdInterAdCloseButton.removeFromSuperview()
        iAdInterAdView.removeFromSuperview()
    }
}

// MARK: - Internal Methods

/// iAd load inter ad
private func iAdLoadInterAd() -> ADInterstitialAd {
    print("iAd inter ad loading...")
    let iAdInterAd = ADInterstitialAd()
    iAdInterAd.delegate = self

    if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
        iAdInterAdCloseButton.frame = CGRectMake(18, 18, 27, 27)
    } else {
        iAdInterAdCloseButton.frame = CGRectMake(13, 13, 22, 22)
    }

    iAdInterAdCloseButton.layer.cornerRadius = 11
    iAdInterAdCloseButton.setTitle("X", forState: .Normal)
    iAdInterAdCloseButton.setTitleColor(UIColor.grayColor(), forState: .Normal)
    iAdInterAdCloseButton.backgroundColor = UIColor.whiteColor()
    iAdInterAdCloseButton.layer.borderColor = UIColor.grayColor().CGColor
    iAdInterAdCloseButton.layer.borderWidth = 2
    iAdInterAdCloseButton.addTarget(self, action: "iAdPressedInterAdCloseButton:", forControlEvents: UIControlEvents.TouchDown)

    return iAdInterAd
}

/// iAd show inter ad
private func iAdShowInterAd() {
    guard iAdInterAd != nil else {
        print("iAd inter is nil, reloading")
        iAdInterAd = iAdLoadInterAd()
        return
    }

    if iAdInterAd!.loaded {
        print("iAd inter showing")
        iAdInterAdView.frame = presentingViewController.view.bounds
        presentingViewController.view.addSubview(iAdInterAdView)
        iAdInterAd!.presentInView(iAdInterAdView)
        UIViewController.prepareInterstitialAds()
        iAdInterAdView.addSubview(iAdInterAdCloseButton)

        //pauseTasks() // not really needed for inter as you tend to show them when not playing.
    } else {
        print("iAd inter not ready, reloading again...")
        iAdInterAd = iAdLoadInterAd()

    }
}

/// iAd inter ad pressed close button
func iAdPressedInterAdCloseButton(sender: UIButton) { // dont make private as its called with a selector
    print("iAd inter closed")
    iAdInterAd!.delegate = nil
    iAdInterAdCloseButton.removeFromSuperview()
    iAdInterAdView.removeFromSuperview()
    iAdInterAd = iAdLoadInterAd()

    //resumeTasks() // not really needed for inter as you tend to not show them during gameplay
}

/// Pause tasks in the app/game
private func pauseTasks() {
    // Pause app/game, music etc here.
    // you could use NSNotifactionCenter or Delegates to call methods in other SKScenes / ViewControllers
}

/// Resume tasks in the app/game
private func resumeTasks() {
    // Resume app/game, music etc here.
    // you could use NSNotifactionCenter or Delegates to call methods in other SKScenes / ViewControllers
     }
}

// MARK: - Delegates iAd Inter
extension Ads: ADInterstitialAdDelegate {

func interstitialAdDidLoad(interstitialAd: ADInterstitialAd!) {
    print("iAd inter did load")
}

func interstitialAdDidUnload(interstitialAd: ADInterstitialAd!) {
    print("iAd inter did unload")
}

func interstitialAd(interstitialAd: ADInterstitialAd!, didFailWithError error: NSError!) {
    print("iAd inter error \(error)")
    iAdInterAd!.delegate = nil
    iAdInterAdCloseButton.removeFromSuperview()
    iAdInterAdView.removeFromSuperview()
   }
}

现在你只需调用

Ads.sharedInstance.presentingViewController = self 

在您的 GameViewController 中执行任何其他操作之前。这将初始化助手并预加载第一个广告。

您可以在任何您希望展示广告间的地方调用它们

GameData.sharedInstance.showInterAd()

GameData.sharedInstance.showInterAdRandomly() // 33% chance for ad

【讨论】:

  • 这对我来说似乎是一个很好的答案。谢谢你。但是,它似乎不起作用。我一直在拼凑所有的碎片,但它不起作用。我收到日志说“iAd inter ad loading...”和“iAd inter did load”等等。但是广告没有出现在屏幕上。我不确定出了什么问题。你想让我发布我的代码吗?我很确定它与必要的代码相同。
  • 嘿,不客气。我刚刚制作了一个新的xCode游戏项目并复制了上面的代码,它没有问题。您是在调用 Ads.sharedInstance.showInterAd() 还是 Ads.sharedInstance.showInterAdRandomly()?随机的只有 33% 的机会出现。此外,有时模拟器在测试时很麻烦,您需要等待几个小时。
  • 您需要在 viewDidLoad 中的游戏视图控制器中调用 Ads.sharedInstance.presentingViewController = self,最好在加载第一个场景之前。比在您的场景中,您需要调用 ...showInterAd 方法并且广告应该显示。告诉我进展如何
  • 呃,我使用您的代码创建了一个新项目并再次尝试。显然,您发送给我的那个 github 链接在 my 的情况下令人困惑甚至毫无用处。好吧,我现在一切都好。谢谢。
  • 是的,github 是一个完整的助手,即来自苹果和谷歌的横幅广告和内部广告。 Google 广告需要大量框架和其他设置。
【解决方案2】:

在 sprite kit 中显示插页式广告几乎与在应用的其他部分中相同。唯一的区别是您通过使用“self.view”调用所有 iAd 方法来呈现添加。这将获得 SKScene 所在的视图并在其上显示 iAd

这也可用于在不切换视图控制器的情况下呈现插页式广告

currentView.requestInterstitialAdPresentation()

从场景中请求:

self.view?.requestInterstitialAdPresentation()

注意在函数调用中它是如何表示请求的。这就是为什么它有时只出现。当您“请求”广告时,设备会向苹果发送请求广告的请求。如果您在合理的时间内得到回复,那么广告就会出现。如果您没有在合理的时间内得到回复(很可能是由于互联网状况不佳),那么广告将不会展示,因为没有什么可展示的。但是,如果您请求一次但它没有出现,那么下次您请求时它肯定会出现,因为您已经从上次请求时加载了一个广告,但它从未出现过。

【讨论】:

  • 效果很好!所以现在我有两个问题。 1. 如何从 SKScene 而不是从 GameViewController 调用该函数?会是[[[GameViewController.m alloc] init] requestInterstitialAdPresentation];吗? 2. 为什么 iAd 有时只出现?我必须等待一段时间才能工作。
  • 原来我的代码 sn-p 并没有实际工作。还有其他想法吗?
  • 应该可以,你能在你的场景中显示代码
  • 显示更多代码,不仅仅是那个狙击手,显示它的内容
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多