如何使用 SpriteKit 和 Swift 2 中的 Xcode 7 beta 从应用程序中删除 iAd?
How to remove iAd from application, using SpriteKit and Xcode 7 beta in Swift 2?
我使用 Xcode 7 beta 和 Swift 2 中的 SpriteKit 制作了一个具有 iAd 插页式广告的游戏,我尝试使用一个函数来删除它们,但它不起作用。我正在使用两个不同的文件,GameScene.swift 和 GameViewController.swift.
我在文件中使用的代码,GameScene.swift:
func gameOver() {
isGameOver = true
print("Game Over")
loadAd()
}
//iAd
func close(sender: UIButton) {
closeButton.removeFromSuperview()
interAdView.removeFromSuperview()
}
func loadAd() {
print("load ad")
interAd = ADInterstitialAd()
interAd.delegate = self
closeButton.frame = CGRectMake(15, 15, 22, 22)
closeButton.layer.cornerRadius = 11
closeButton.setTitle("x", forState: .Normal)
closeButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
closeButton.backgroundColor = UIColor.whiteColor()
closeButton.layer.borderColor = UIColor.blackColor().CGColor
closeButton.layer.borderWidth = 1
closeButton.addTarget(self, action: "close:", forControlEvents: UIControlEvents.TouchDown)
}
func interstitialAdDidLoad(interstitialAd: ADInterstitialAd!) {
print("ad did load")
interAdView = UIView()
interAdView.frame = self.view!.bounds
view!.addSubview(interAdView)
interAd.presentInView(interAdView)
UIViewController.prepareInterstitialAds()
interAdView.addSubview(closeButton)
}
func interstitialAdDidUnload(interstitialAd: ADInterstitialAd!) {
}
func interstitialAd(interstitialAd: ADInterstitialAd!, didFailWithError error: NSError!) {
print("failed to receive")
print(error.localizedDescription)
closeButton.removeFromSuperview()
interAdView.removeFromSuperview()
}
在GameViewController.swift是In-App Purchase去除广告(购买专业版):
@IBAction func removeAds(sender: UIButton) {
print("Remove Ads Button pressed")
for product in list {
let prodID = product.productIdentifier
if(prodID == "Squares.RemoveAds") {
p = product
buyProduct()
break;
}
}
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
func removeAds() {
}
override func prefersStatusBarHidden() -> Bool {
return true
}
//Remove Ads Payment
var list = [SKProduct]()
var p = SKProduct()
//Squares.regular.removeAds
//Squares.6Plus.removeAds
func buyProduct() {
print("Buy" + p.productIdentifier)
let pay = SKPayment(product: p)
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
print("Product Request")
let myProduct = response.products
for product in myProduct {
print("Product Added")
print(product.productIdentifier)
print(product.localizedTitle)
print(product.localizedDescription)
print(product.price)
list.append(product as SKProduct)
}
removeAdsButton.enabled = true
removeAdsIPhone6Plus.enabled = true
}
func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
print("Transactions Restored")
var purchasedItemIDS = []
for transaction in queue.transactions {
let t: SKPaymentTransaction = transaction as SKPaymentTransaction
let prodID = t.payment.productIdentifier as String
switch prodID {
case "Squares.RemoveAds":
print("Remove Ads")
removeAds()
case "Squares.RemoveAds":
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not setup")
}
}
}
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print("Add Payment")
for transaction:AnyObject in transactions {
let trans = transaction as! SKPaymentTransaction
print(trans.error)
switch trans.transactionState {
case .Purchased:
print("Buy, Ok unlock Squares here")
print(p.productIdentifier)
let prodID = p.productIdentifier as String
switch prodID {
case "Squares.RemoveAds":
print("Remove Ads")
removeAds()
case "Squares.RemoveAds":
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not Setup")
}
queue.finishTransaction(trans)
break;
case .Failed:
print("Buy Error")
queue.finishTransaction(trans)
break;
default:
print("Default")
break;
}
}
}
func finishTransaction(trans:SKPaymentTransaction){
print("Finish Transaction")
}
func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
print("Remove Transaction")
}
如果您阅读文件 GameViewController.swift 中的代码,函数 removeAds()
是空的并且在同一文件中的某些代码中被调用,因此它将删除广告永远,我需要做的是在函数 removeAds()
中放置一个代码,它将永久删除广告,问题是我不知道如何调用它以及以何种方式删除它们,因为函数是在不同的文件中,我尝试了很多方法但没有用。
你能详细告诉我怎么做吗?
您可以使用 NSNotifcationCenter。
所以在您的 viewController 中,您会说
NSNotificationCenter.defaultCenter().addObserver(self, selector: "removeAds", name: "RemoveAdsKey", object: nil)
比任何时候你想调用这个函数你都会说
NSNotificationCenter.defaultCenter().postNotificationName("RemoveAdsKey", object: nil)
关于函数 removeAds() 本身。你需要写这样的东西。
closeButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
您应该尽快添加 SKpayment 交易观察器,并且只添加一次,而不是每次购买。
仅当您的游戏关闭时才移除观察者。很多教程向您展示了 Apple 不推荐的方式。
https://developer.apple.com/library/ios/technotes/tn2387/_index.html
为了让您的生活更轻松,为什么不查看我在 gitHub 上发布的 iAds 和 Admob 助手,它主要是为 SpriteKit 制作的。
https://github.com/crashoverride777/Swift-iAds-and-AdMob-Helper
即使您不想使用它,也应该让您了解如何使用委托等。那里没有什么复杂的,只是使用广告的基本方法。它还向您展示了如何预加载 interAds,以便它们显示得更快。
我用 link 更新了我的第一个答案给 apple。这并不是说你的方法是错误的,而是 Apple 专门给出了一个很好和不好的实施示例,不幸的是,大多数教程都是以错误的方式进行的。
在您的具体情况下,您可以执行以下操作。
将 2 个 NSNotification 中心观察者添加到您的 viewController
NSNotificationCenter.defaultCenter().addObserver(self, selector: "addTransactionObserver", name: "AddObserverKey", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "removeTransactionObserver", name: "RemoveObserverKey", object: nil)
在您的 viewController.
中创建 2 个函数
func addTransactionObserver() {
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
// you could put this in view Did Load but I prefer apples way
}
func removeTransactionObserver() {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
比在你的 appDelegate 方法 didFinishLaunching...中使用
NSNotificationCenter.defaultCenter().postNotificationName("AddObserverKey", object: nil)
比在 appWillTerminate 的 appDelegate 中...使用
NSNotificationCenter.defaultCenter().postNotificationName("RemoveObserverKey", object: nil)
您真的应该考虑将您的购买代码放入帮助程序文件中,以使事情变得容易得多。例如,这是一个好的开始。
https://github.com/Vitaa/IAPurchaseManager/blob/master/IAPManager.swift
有了广告,只要看看我的助手,它就会让你知道哪里错了。
您的游戏视图控制器可能看起来像这样
class gameViewController: .....
struct ProductID {
static let removeAds = "squares.RemoveAds"
static let removeAds6Plus = "squares.RemoveAds6Plus" // really needed?
}
struct NSNotificationKey {
static let addObserver = "AddObserver"
static let removeObserver = "RemoveObserver"
}
func ViewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "addTransactionObserver", name: NSNotificationKey.addObserver, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "removeTransactionObserver", name: NSNotificationKey.removeObserver, object: nil)
....
}
func addTransactionObserver() {
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
// you could put this in view Did Load but I prefer apples way
}
func removeTransactionObserver() {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
@IBAction func removeAds(sender: UIButton) {
print("Remove Ads Button pressed")
for product in list {
let prodID = product.productIdentifier
if(prodID == ProductID.removeAds) {
p = product
buyProduct()
break
}
}
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
func removeAds() {
interAd.delegate = nil
closeButton.removeFromSuperView()
interAdView.removeFromSuperView()
}
override func prefersStatusBarHidden() -> Bool {
return true
}
//Remove Ads Payment
var list = [SKProduct]()
var p = SKProduct()
//Squares.regular.removeAds
//Squares.6Plus.removeAds
func buyProduct() {
print("Buy" + p.productIdentifier)
let pay = SKPayment(product: p)
SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
print("Product Request")
let myProduct = response.products
for product in myProduct {
print("Product Added")
print(product.productIdentifier)
print(product.localizedTitle)
print(product.localizedDescription)
print(product.price)
list.append(product as SKProduct)
}
removeAdsButton.enabled = true
removeAdsIPhone6Plus.enabled = true
}
func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
print("Transactions Restored")
var purchasedItemIDS = []
for transaction in queue.transactions {
let t: SKPaymentTransaction = transaction as SKPaymentTransaction
let prodID = t.payment.productIdentifier as String
switch prodID {
case ProductID.removeAds:
print("Remove Ads")
removeAds()
case ProductID.removeAds6Plus:
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not setup")
}
}
}
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print("Add Payment")
for transaction:AnyObject in transactions {
let trans = transaction as! SKPaymentTransaction
print(trans.error)
switch trans.transactionState {
case .Purchased:
print("Buy, Ok unlock Squares here")
print(p.productIdentifier)
let prodID = p.productIdentifier as String
switch prodID {
case ProductID.removeAds:
print("Remove Ads")
removeAds()
case ProductID.removeAds6Plus: // really needed?
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not Setup")
}
queue.finishTransaction(trans)
break;
case .Failed:
print("Buy Error")
queue.finishTransaction(trans)
break;
default:
print("Default")
break;
}
}
}
func finishTransaction(trans:SKPaymentTransaction){
print("Finish Transaction")
}
func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
print("Remove Transaction")
}
比你在 didFinishLaunchingWithOptions 中的 appDelegate.swift 你说的
NSNotificationCenter.defaultCenter().postNotificationName(GameViewController.NSNotificationKey.addObserver, object: nil)
在 appWillTerminate 中你说
NSNotificationCenter.defaultCenter().postNotificationName(GameViewController.NSNotificationKey.removeObserver, object: nil)
如果仍然无法正常工作,您需要检查您的产品 ID。您正在使用 Squares.RemoveAds 作为产品 ID,但您有这些评论
//Squares.regular.removeAds
//正方形.6Plus.removeAds
仔细检查您的 ID。
好的,这基本上是一种具有更好代码的新方法。
首先复制您的项目,以防万一。
其次,请听我的指示并完全按照我的指示去做。
所以我已经用购买代码向您发布了答案。检查你是否完全按照我说的去做了。比删除 GameScene 中有关广告的所有代码。所有这些都像 NSNotifcationCenter、函数、ADInterstitialAdDelegate(在游戏场景的顶部)等。
然后在项目中创建一个新的 swift 文件并输入此代码。
这是我的帮手的精简版,它现在包括内部广告和横幅广告。要设置横幅,请执行以下操作。在你写的 import UIKit 下的应用委托中
import iAd
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
仍在 class 实现下的 appDelegate 中,您必须创建此 属性
var bannerAdView = ADBannerView()
进入 appDelegate 的原因是因为我们正在创建一个共享的 iAdBanner。对于具有 1 个 viewController 的 spritekit 来说并不是真正需要的,但对于具有多个 viewController 的应用程序来说这是正确的方法,因此您不妨使用它。
而不是像以前一样将其复制到您的项目中。
import iAd
class Ads: NSObject {
// MARK: - Properties
static let sharedInstance = Ads()
var presentingViewController: UIViewController!
var interAd = ADInterstitialAd()
var interAdView = UIView()
var interAdCloseButton = UIButton.buttonWithType(UIButtonType.System) as! UIButton
override init() {
super.init()
print("Ads Helper init")
preloadInterAd() // preload first interAd, they will preload automatically afterwards.
}
// MARK: - User Methods
class func showBannerAd() {
Ads.sharedInstance.loadBannerAd()
}
class func showInterAd() {
Ads.sharedInstance.showInterAd()
}
class func removeBannerAds() {
Ads.sharedInstance.removeBannerAds()
}
class func removeAllAds() {
Ads.sharedInstance.removeAllAds()
}
//MARK: - Internal Methods
// loading banner
private func loadBannerAd() {
printDebug("iAd banner loading...")
appDelegate.bannerAdView = ADBannerView(frame: presentingViewController.view.bounds)
appDelegate.bannerAdView.delegate = self
appDelegate.bannerAdView.center = CGPoint(x: CGRectGetMidX(presentingViewController.view.frame), y: CGRectGetMaxY(presentingViewController.view.frame) + (appDelegate.bannerAdView.frame.size.height / 2))
}
// preloading inter
private func preloadInterAd() {
print("iAds Inter preloading")
interAd = ADInterstitialAd()
interAd.delegate = self
interAdCloseButton.frame = CGRectMake(13, 13, 22, 22)
interAdCloseButton.layer.cornerRadius = 12
interAdCloseButton.setTitle("X", forState: .Normal)
interAdCloseButton.setTitleColor(UIColor.grayColor(), forState: .Normal)
interAdCloseButton.backgroundColor = UIColor.whiteColor()
interAdCloseButton.layer.borderColor = UIColor.grayColor().CGColor
interAdCloseButton.layer.borderWidth = 2
interAdCloseButton.addTarget(self, action: "pressedCloseButton:", forControlEvents: UIControlEvents.TouchDown) // function such as this with content in brackets need : for selector. VIP
}
private func showInterAd() {
if interAd.loaded {
print("iAds Inter showing")
presentingViewController.view.addSubview(interAdView)
interAd.presentInView(interAdView)
UIViewController.prepareInterstitialAds()
interAdView.addSubview(interAdCloseButton)
// pause game, music etc here
} else {
print("iAds Inter cannot be shown, reloading")
preloadInterAd()
}
}
// closed inter ad
func pressedCloseButton(sender: UIButton) {
interAdCloseButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
preloadInterAd()
}
// remove banner ads
private func removeBannerAds() {
appDelegate.bannerAdView.delegate = nil
appDelegate.bannerAdView.removeFromSuperview()
}
// remove all ads
private func removeAllAds() {
// banners
appDelegate.bannerAdView.delegate = nil
appDelegate.bannerAdView.removeFromSuperview()
// inter
interAdCloseButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
}
}
// MARK: iAds Banner Delegates
extension Ads: ADBannerViewDelegate {
func bannerViewWillLoadAd(banner: ADBannerView!) {
printDebug("iAds banner will load")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
printDebug("iAds banner did load, showing")
presentingViewController.view.addSubview(appDelegate.bannerAdView)
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.5)
appDelegate.bannerAdView.center = CGPoint(x: CGRectGetMidX(presentingViewController.view.frame), y: CGRectGetMaxY(presentingViewController.view.frame) - (appDelegate.bannerAdView.frame.size.height / 2))
UIView.commitAnimations()
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
printDebug("iAds banner clicked")
// pause game , music etc here
return true
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
printDebug("iAds banner closed")
// resume game, music here
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
printDebug("iAds banner error")
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.5)
appDelegate.bannerAdView.center = CGPoint(x: CGRectGetMidX(presentingViewController.view.frame), y: CGRectGetMaxY(presentingViewController.view.frame) + (appDelegate.bannerAdView.frame.size.height / 2))
appDelegate.bannerAdView.hidden = true
UIView.commitAnimations()
}
}
// MARK: - iAds Inter Delegates
extension Ads: ADInterstitialAdDelegate {
func interstitialAdDidLoad(interstitialAd: ADInterstitialAd!) {
print("iAds Inter did preload")
interAdView = UIView()
interAdView.frame = presentingViewController.view.bounds
}
func interstitialAdDidUnload(interstitialAd: ADInterstitialAd!) {
print("iAds Inter did unload")
}
func interstitialAd(interstitialAd: ADInterstitialAd!, didFailWithError error: NSError!) {
print("iAds Inter error")
print(error.localizedDescription)
interAdCloseButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
preloadInterAd()
}
}
好的。现在你所要做的就是写一行代码来初始化这个Helper并预加载第一个Inter(之后它们会自动预加载。)
在您的 ViewDidLoad 中的 gameViewController 中,您称之为
// this tells the ad helper that this is the GameViewController that shows ads.
// This step also inits the adHelper and preloads the first inter ad.
Ads.sharedInstance.presentingViewController = self
就是这样。在 func gameOver() 的 GameScene 中或任何你想要的地方,你现在只需说
Ads.showInterAd()
Ads.showBannerAd()
您可以随时在控制台中检查广告是否已预加载,因为我为每一步都设置了 prinln。如果广告尚未预加载,则无法显示。这有助于您了解发生了什么。
在你的 gameViewController 中购买代码你现在只需说
Ads.removeAllAds()
并删除所有广告。
如果您只想移除横幅广告,例如在玩游戏期间,只需说
Ads.removeBannerAds()
比你喜欢的时候再次加载它们
Ads.showBannerAd()
要保存购买,请执行此操作。
在函数 removeAllAds() 中,你在最后说得很好
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "your product ID")
在你的代码中任何你会说 Ads.showInterAd() 或 Ads.showBannerAd() 的地方,比如 func gameOver() 你写这个
// You can use your product Id as a key, and you dont actually have to set a var. So its the easiest this way. If it cannot find a bool for your product ID it will automatically set it to false. Very nice.
// A reason I made the structs with the product ID is so its easier to reference it so you dont have to type it out every time.
if NSUserDefaults.standardUserDefaults().boolForKey("your product ID") == false {
Ads.showInterAd()
}
完成
我使用 Xcode 7 beta 和 Swift 2 中的 SpriteKit 制作了一个具有 iAd 插页式广告的游戏,我尝试使用一个函数来删除它们,但它不起作用。我正在使用两个不同的文件,GameScene.swift 和 GameViewController.swift.
我在文件中使用的代码,GameScene.swift:
func gameOver() {
isGameOver = true
print("Game Over")
loadAd()
}
//iAd
func close(sender: UIButton) {
closeButton.removeFromSuperview()
interAdView.removeFromSuperview()
}
func loadAd() {
print("load ad")
interAd = ADInterstitialAd()
interAd.delegate = self
closeButton.frame = CGRectMake(15, 15, 22, 22)
closeButton.layer.cornerRadius = 11
closeButton.setTitle("x", forState: .Normal)
closeButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
closeButton.backgroundColor = UIColor.whiteColor()
closeButton.layer.borderColor = UIColor.blackColor().CGColor
closeButton.layer.borderWidth = 1
closeButton.addTarget(self, action: "close:", forControlEvents: UIControlEvents.TouchDown)
}
func interstitialAdDidLoad(interstitialAd: ADInterstitialAd!) {
print("ad did load")
interAdView = UIView()
interAdView.frame = self.view!.bounds
view!.addSubview(interAdView)
interAd.presentInView(interAdView)
UIViewController.prepareInterstitialAds()
interAdView.addSubview(closeButton)
}
func interstitialAdDidUnload(interstitialAd: ADInterstitialAd!) {
}
func interstitialAd(interstitialAd: ADInterstitialAd!, didFailWithError error: NSError!) {
print("failed to receive")
print(error.localizedDescription)
closeButton.removeFromSuperview()
interAdView.removeFromSuperview()
}
在GameViewController.swift是In-App Purchase去除广告(购买专业版):
@IBAction func removeAds(sender: UIButton) {
print("Remove Ads Button pressed")
for product in list {
let prodID = product.productIdentifier
if(prodID == "Squares.RemoveAds") {
p = product
buyProduct()
break;
}
}
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
func removeAds() {
}
override func prefersStatusBarHidden() -> Bool {
return true
}
//Remove Ads Payment
var list = [SKProduct]()
var p = SKProduct()
//Squares.regular.removeAds
//Squares.6Plus.removeAds
func buyProduct() {
print("Buy" + p.productIdentifier)
let pay = SKPayment(product: p)
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
print("Product Request")
let myProduct = response.products
for product in myProduct {
print("Product Added")
print(product.productIdentifier)
print(product.localizedTitle)
print(product.localizedDescription)
print(product.price)
list.append(product as SKProduct)
}
removeAdsButton.enabled = true
removeAdsIPhone6Plus.enabled = true
}
func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
print("Transactions Restored")
var purchasedItemIDS = []
for transaction in queue.transactions {
let t: SKPaymentTransaction = transaction as SKPaymentTransaction
let prodID = t.payment.productIdentifier as String
switch prodID {
case "Squares.RemoveAds":
print("Remove Ads")
removeAds()
case "Squares.RemoveAds":
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not setup")
}
}
}
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print("Add Payment")
for transaction:AnyObject in transactions {
let trans = transaction as! SKPaymentTransaction
print(trans.error)
switch trans.transactionState {
case .Purchased:
print("Buy, Ok unlock Squares here")
print(p.productIdentifier)
let prodID = p.productIdentifier as String
switch prodID {
case "Squares.RemoveAds":
print("Remove Ads")
removeAds()
case "Squares.RemoveAds":
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not Setup")
}
queue.finishTransaction(trans)
break;
case .Failed:
print("Buy Error")
queue.finishTransaction(trans)
break;
default:
print("Default")
break;
}
}
}
func finishTransaction(trans:SKPaymentTransaction){
print("Finish Transaction")
}
func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
print("Remove Transaction")
}
如果您阅读文件 GameViewController.swift 中的代码,函数 removeAds()
是空的并且在同一文件中的某些代码中被调用,因此它将删除广告永远,我需要做的是在函数 removeAds()
中放置一个代码,它将永久删除广告,问题是我不知道如何调用它以及以何种方式删除它们,因为函数是在不同的文件中,我尝试了很多方法但没有用。
你能详细告诉我怎么做吗?
您可以使用 NSNotifcationCenter。
所以在您的 viewController 中,您会说
NSNotificationCenter.defaultCenter().addObserver(self, selector: "removeAds", name: "RemoveAdsKey", object: nil)
比任何时候你想调用这个函数你都会说
NSNotificationCenter.defaultCenter().postNotificationName("RemoveAdsKey", object: nil)
关于函数 removeAds() 本身。你需要写这样的东西。
closeButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
您应该尽快添加 SKpayment 交易观察器,并且只添加一次,而不是每次购买。 仅当您的游戏关闭时才移除观察者。很多教程向您展示了 Apple 不推荐的方式。 https://developer.apple.com/library/ios/technotes/tn2387/_index.html
为了让您的生活更轻松,为什么不查看我在 gitHub 上发布的 iAds 和 Admob 助手,它主要是为 SpriteKit 制作的。 https://github.com/crashoverride777/Swift-iAds-and-AdMob-Helper
即使您不想使用它,也应该让您了解如何使用委托等。那里没有什么复杂的,只是使用广告的基本方法。它还向您展示了如何预加载 interAds,以便它们显示得更快。
我用 link 更新了我的第一个答案给 apple。这并不是说你的方法是错误的,而是 Apple 专门给出了一个很好和不好的实施示例,不幸的是,大多数教程都是以错误的方式进行的。 在您的具体情况下,您可以执行以下操作。
将 2 个 NSNotification 中心观察者添加到您的 viewController
NSNotificationCenter.defaultCenter().addObserver(self, selector: "addTransactionObserver", name: "AddObserverKey", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "removeTransactionObserver", name: "RemoveObserverKey", object: nil)
在您的 viewController.
中创建 2 个函数func addTransactionObserver() {
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
// you could put this in view Did Load but I prefer apples way
}
func removeTransactionObserver() {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
比在你的 appDelegate 方法 didFinishLaunching...中使用
NSNotificationCenter.defaultCenter().postNotificationName("AddObserverKey", object: nil)
比在 appWillTerminate 的 appDelegate 中...使用
NSNotificationCenter.defaultCenter().postNotificationName("RemoveObserverKey", object: nil)
您真的应该考虑将您的购买代码放入帮助程序文件中,以使事情变得容易得多。例如,这是一个好的开始。
https://github.com/Vitaa/IAPurchaseManager/blob/master/IAPManager.swift
有了广告,只要看看我的助手,它就会让你知道哪里错了。
您的游戏视图控制器可能看起来像这样
class gameViewController: .....
struct ProductID {
static let removeAds = "squares.RemoveAds"
static let removeAds6Plus = "squares.RemoveAds6Plus" // really needed?
}
struct NSNotificationKey {
static let addObserver = "AddObserver"
static let removeObserver = "RemoveObserver"
}
func ViewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "addTransactionObserver", name: NSNotificationKey.addObserver, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "removeTransactionObserver", name: NSNotificationKey.removeObserver, object: nil)
....
}
func addTransactionObserver() {
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
// you could put this in view Did Load but I prefer apples way
}
func removeTransactionObserver() {
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
@IBAction func removeAds(sender: UIButton) {
print("Remove Ads Button pressed")
for product in list {
let prodID = product.productIdentifier
if(prodID == ProductID.removeAds) {
p = product
buyProduct()
break
}
}
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
}
func removeAds() {
interAd.delegate = nil
closeButton.removeFromSuperView()
interAdView.removeFromSuperView()
}
override func prefersStatusBarHidden() -> Bool {
return true
}
//Remove Ads Payment
var list = [SKProduct]()
var p = SKProduct()
//Squares.regular.removeAds
//Squares.6Plus.removeAds
func buyProduct() {
print("Buy" + p.productIdentifier)
let pay = SKPayment(product: p)
SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
}
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
print("Product Request")
let myProduct = response.products
for product in myProduct {
print("Product Added")
print(product.productIdentifier)
print(product.localizedTitle)
print(product.localizedDescription)
print(product.price)
list.append(product as SKProduct)
}
removeAdsButton.enabled = true
removeAdsIPhone6Plus.enabled = true
}
func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
print("Transactions Restored")
var purchasedItemIDS = []
for transaction in queue.transactions {
let t: SKPaymentTransaction = transaction as SKPaymentTransaction
let prodID = t.payment.productIdentifier as String
switch prodID {
case ProductID.removeAds:
print("Remove Ads")
removeAds()
case ProductID.removeAds6Plus:
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not setup")
}
}
}
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print("Add Payment")
for transaction:AnyObject in transactions {
let trans = transaction as! SKPaymentTransaction
print(trans.error)
switch trans.transactionState {
case .Purchased:
print("Buy, Ok unlock Squares here")
print(p.productIdentifier)
let prodID = p.productIdentifier as String
switch prodID {
case ProductID.removeAds:
print("Remove Ads")
removeAds()
case ProductID.removeAds6Plus: // really needed?
print("Remove Ads for iPhone 6 Plus")
removeAds()
default:
print("IAP not Setup")
}
queue.finishTransaction(trans)
break;
case .Failed:
print("Buy Error")
queue.finishTransaction(trans)
break;
default:
print("Default")
break;
}
}
}
func finishTransaction(trans:SKPaymentTransaction){
print("Finish Transaction")
}
func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
print("Remove Transaction")
}
比你在 didFinishLaunchingWithOptions 中的 appDelegate.swift 你说的
NSNotificationCenter.defaultCenter().postNotificationName(GameViewController.NSNotificationKey.addObserver, object: nil)
在 appWillTerminate 中你说
NSNotificationCenter.defaultCenter().postNotificationName(GameViewController.NSNotificationKey.removeObserver, object: nil)
如果仍然无法正常工作,您需要检查您的产品 ID。您正在使用 Squares.RemoveAds 作为产品 ID,但您有这些评论
//Squares.regular.removeAds
//正方形.6Plus.removeAds
仔细检查您的 ID。
好的,这基本上是一种具有更好代码的新方法。 首先复制您的项目,以防万一。 其次,请听我的指示并完全按照我的指示去做。
所以我已经用购买代码向您发布了答案。检查你是否完全按照我说的去做了。比删除 GameScene 中有关广告的所有代码。所有这些都像 NSNotifcationCenter、函数、ADInterstitialAdDelegate(在游戏场景的顶部)等。 然后在项目中创建一个新的 swift 文件并输入此代码。
这是我的帮手的精简版,它现在包括内部广告和横幅广告。要设置横幅,请执行以下操作。在你写的 import UIKit 下的应用委托中
import iAd
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
仍在 class 实现下的 appDelegate 中,您必须创建此 属性
var bannerAdView = ADBannerView()
进入 appDelegate 的原因是因为我们正在创建一个共享的 iAdBanner。对于具有 1 个 viewController 的 spritekit 来说并不是真正需要的,但对于具有多个 viewController 的应用程序来说这是正确的方法,因此您不妨使用它。 而不是像以前一样将其复制到您的项目中。
import iAd
class Ads: NSObject {
// MARK: - Properties
static let sharedInstance = Ads()
var presentingViewController: UIViewController!
var interAd = ADInterstitialAd()
var interAdView = UIView()
var interAdCloseButton = UIButton.buttonWithType(UIButtonType.System) as! UIButton
override init() {
super.init()
print("Ads Helper init")
preloadInterAd() // preload first interAd, they will preload automatically afterwards.
}
// MARK: - User Methods
class func showBannerAd() {
Ads.sharedInstance.loadBannerAd()
}
class func showInterAd() {
Ads.sharedInstance.showInterAd()
}
class func removeBannerAds() {
Ads.sharedInstance.removeBannerAds()
}
class func removeAllAds() {
Ads.sharedInstance.removeAllAds()
}
//MARK: - Internal Methods
// loading banner
private func loadBannerAd() {
printDebug("iAd banner loading...")
appDelegate.bannerAdView = ADBannerView(frame: presentingViewController.view.bounds)
appDelegate.bannerAdView.delegate = self
appDelegate.bannerAdView.center = CGPoint(x: CGRectGetMidX(presentingViewController.view.frame), y: CGRectGetMaxY(presentingViewController.view.frame) + (appDelegate.bannerAdView.frame.size.height / 2))
}
// preloading inter
private func preloadInterAd() {
print("iAds Inter preloading")
interAd = ADInterstitialAd()
interAd.delegate = self
interAdCloseButton.frame = CGRectMake(13, 13, 22, 22)
interAdCloseButton.layer.cornerRadius = 12
interAdCloseButton.setTitle("X", forState: .Normal)
interAdCloseButton.setTitleColor(UIColor.grayColor(), forState: .Normal)
interAdCloseButton.backgroundColor = UIColor.whiteColor()
interAdCloseButton.layer.borderColor = UIColor.grayColor().CGColor
interAdCloseButton.layer.borderWidth = 2
interAdCloseButton.addTarget(self, action: "pressedCloseButton:", forControlEvents: UIControlEvents.TouchDown) // function such as this with content in brackets need : for selector. VIP
}
private func showInterAd() {
if interAd.loaded {
print("iAds Inter showing")
presentingViewController.view.addSubview(interAdView)
interAd.presentInView(interAdView)
UIViewController.prepareInterstitialAds()
interAdView.addSubview(interAdCloseButton)
// pause game, music etc here
} else {
print("iAds Inter cannot be shown, reloading")
preloadInterAd()
}
}
// closed inter ad
func pressedCloseButton(sender: UIButton) {
interAdCloseButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
preloadInterAd()
}
// remove banner ads
private func removeBannerAds() {
appDelegate.bannerAdView.delegate = nil
appDelegate.bannerAdView.removeFromSuperview()
}
// remove all ads
private func removeAllAds() {
// banners
appDelegate.bannerAdView.delegate = nil
appDelegate.bannerAdView.removeFromSuperview()
// inter
interAdCloseButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
}
}
// MARK: iAds Banner Delegates
extension Ads: ADBannerViewDelegate {
func bannerViewWillLoadAd(banner: ADBannerView!) {
printDebug("iAds banner will load")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
printDebug("iAds banner did load, showing")
presentingViewController.view.addSubview(appDelegate.bannerAdView)
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.5)
appDelegate.bannerAdView.center = CGPoint(x: CGRectGetMidX(presentingViewController.view.frame), y: CGRectGetMaxY(presentingViewController.view.frame) - (appDelegate.bannerAdView.frame.size.height / 2))
UIView.commitAnimations()
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
printDebug("iAds banner clicked")
// pause game , music etc here
return true
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
printDebug("iAds banner closed")
// resume game, music here
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
printDebug("iAds banner error")
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.5)
appDelegate.bannerAdView.center = CGPoint(x: CGRectGetMidX(presentingViewController.view.frame), y: CGRectGetMaxY(presentingViewController.view.frame) + (appDelegate.bannerAdView.frame.size.height / 2))
appDelegate.bannerAdView.hidden = true
UIView.commitAnimations()
}
}
// MARK: - iAds Inter Delegates
extension Ads: ADInterstitialAdDelegate {
func interstitialAdDidLoad(interstitialAd: ADInterstitialAd!) {
print("iAds Inter did preload")
interAdView = UIView()
interAdView.frame = presentingViewController.view.bounds
}
func interstitialAdDidUnload(interstitialAd: ADInterstitialAd!) {
print("iAds Inter did unload")
}
func interstitialAd(interstitialAd: ADInterstitialAd!, didFailWithError error: NSError!) {
print("iAds Inter error")
print(error.localizedDescription)
interAdCloseButton.removeFromSuperview()
interAdView.removeFromSuperview()
interAd.delegate = nil
preloadInterAd()
}
}
好的。现在你所要做的就是写一行代码来初始化这个Helper并预加载第一个Inter(之后它们会自动预加载。)
在您的 ViewDidLoad 中的 gameViewController 中,您称之为
// this tells the ad helper that this is the GameViewController that shows ads.
// This step also inits the adHelper and preloads the first inter ad.
Ads.sharedInstance.presentingViewController = self
就是这样。在 func gameOver() 的 GameScene 中或任何你想要的地方,你现在只需说
Ads.showInterAd()
Ads.showBannerAd()
您可以随时在控制台中检查广告是否已预加载,因为我为每一步都设置了 prinln。如果广告尚未预加载,则无法显示。这有助于您了解发生了什么。
在你的 gameViewController 中购买代码你现在只需说
Ads.removeAllAds()
并删除所有广告。
如果您只想移除横幅广告,例如在玩游戏期间,只需说
Ads.removeBannerAds()
比你喜欢的时候再次加载它们 Ads.showBannerAd()
要保存购买,请执行此操作。
在函数 removeAllAds() 中,你在最后说得很好
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "your product ID")
在你的代码中任何你会说 Ads.showInterAd() 或 Ads.showBannerAd() 的地方,比如 func gameOver() 你写这个
// You can use your product Id as a key, and you dont actually have to set a var. So its the easiest this way. If it cannot find a bool for your product ID it will automatically set it to false. Very nice.
// A reason I made the structs with the product ID is so its easier to reference it so you dont have to type it out every time.
if NSUserDefaults.standardUserDefaults().boolForKey("your product ID") == false {
Ads.showInterAd()
}
完成