【问题标题】:Remove Ads - In App Purchase移除广告 - 应用内购买
【发布时间】:2016-05-31 17:05:32
【问题描述】:

在我的游戏中,我希望通过应用内购买来移除广告。我使用 Admob,我的代码很适合广告。我遇到的问题是我的广告代码在 GameViewController.swift 中。但我的应用内购买位于我的 PurchaseScene.swift 中。

我没有找到在我的 PurchaseScene.swift 中创建删除功能的方法。所以我在 GameViewController.swift 中的代码:

class GameViewController: UIViewController, GADBannerViewDelegate, GADInterstitialDelegate {

    @IBOutlet weak var banner: GADBannerView!

    var interstital: GADInterstitial!

    override func viewDidLoad() {
        super.viewDidLoad()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ShowAd(_:)), name: "ShowInterAdKey", object: nil)

        if let scene = GameScene(fileNamed:"GameScene") {
            // Configure the view.
            let skView = self.view as! SKView
            skView.showsFPS = false
            skView.showsNodeCount = false

            /* Sprite Kit applies additional optimizations to improve rendering performance */
            skView.ignoresSiblingOrder = true

            /* Set the scale mode to scale to fit the window */
            scene.scaleMode = .AspectFill
            scene.size = self.view.bounds.size

            skView.presentScene(scene)
        }

        self.banner.adUnitID = "myUnitID"
        self.banner.rootViewController = self

        var request: GADRequest = GADRequest()

        self.banner.loadRequest(request)

        request.testDevices = [kGADSimulatorID]

        interstital = GADInterstitial(adUnitID: "myUnitID")

        let req = GADRequest()
        interstital.loadRequest(req)
    }

    func adViewDidReceiveAd(bannerView: GADBannerView!) {
        banner.hidden = false
    }

    func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
        banner.hidden = true
    }

    override func shouldAutorotate() -> Bool {
        return true
    }

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return .AllButUpsideDown
        } else {
            return .All
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Release any cached data, images, etc that aren't in use.
    }

    override func prefersStatusBarHidden() -> Bool {
        return true
    }

    func ShowAd(sender: AnyObject) {
        if (interstital.isReady) {
            interstital.presentFromRootViewController(self)
            interstital = CreateAd()
        }

    }

    func CreateAd() -> GADInterstitial {
        let interstital = GADInterstitial(adUnitID: "myUnitID")
        interstital.loadRequest(GADRequest())
        return interstital
    }
}

现在我在 Utilities.swift 中有这段代码。

import Foundation

类实用程序{

// Gets a path to your app's local directory where it has permissions to write
static func getFilePathForFile(fileName:String) -> String {
    let libraryPath = NSSearchPathForDirectoriesInDomains(.LibraryDirectory, .UserDomainMask, true)[0]

    return libraryPath.stringByAppendingString("/").stringByAppendingString(fileName as String)
}

static func writeValueToFile(value:String, fileName:String) {

    do {
        try value.writeToFile(Utility.getFilePathForFile(fileName), atomically: true, encoding: NSUTF8StringEncoding)
    } catch {
        print("\(error)")
    }
}

static func readValueFromFile(fileName:String) -> String? {

    let file = Utility.getFilePathForFile(fileName);

    if let value = try? String(contentsOfFile: file) {
        return value;
    }

    return nil;
}

}

调用函数在 PurchaseScene.swift 中是这样的:

let file = "IAP_Ads"



func removeADS() {

    Utility.writeValueToFile("YES", fileName: file);




if let value = Utility.readValueFromFile(file) {
    print("file exists... value = %@" , Utility.readValueFromFile(file) )

    let adsRemoved = (value == "YES" ? true : false)

    if adsRemoved {
        // Code to remove ads, but i don't know what code
        print("ads removed")


    }
 }
}
 override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch: AnyObject in touches{
        let location = touch.locationInNode(self)
        var node = self.nodeAtPoint(location)
if removeadsBTN.containsPoint(location){
            for product in list {
                let prodID = product.productIdentifier
                if(prodID == "myProductID") {
                    p = product
                    buyProduct()
                    break;
                }
            }
        }

    }


}

第 3 步:购买产品()

func buyProduct() {
    print("buy " + p.productIdentifier)
    let pay = SKPayment(product: p)
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)
    SKPaymentQueue.defaultQueue().addPayment(pay as SKPayment)
    Utility.writeValueToFile("YES", fileName: "IAP_Ads") //new code
}

【问题讨论】:

  • 我假设您的购买屏幕与您的 GameViewController 是分开的?如果是这样,并且您必须更改屏幕(例如,通过导航控制器推送/弹出),那么您需要做的就是在调用 viewWillAppear 函数时检查 GameViewController 中“购买”的状态。如果它是通过覆盖,并且您的 GameViewController 的生命周期方法不会被调用,那么您需要使用观察者/通知模型。
  • @thephatp 是的,我有一个单独的购买屏幕。如何检查 GameViewController 中“购买”的状态?你有代码示例吗?非常感谢
  • 跟踪状态还不错,但由于这是一次购买,我假设您希望能够在用户更换设备时恢复购买。请记住这一点以备后用。现在,只是进入“寻找状态”,让我为您获取一些代码。您是否使用核心数据? (这将帮助我在不给你太多工作的情况下为你提供正确的代码。)
  • @thephatp 好吧,那太好了。不,这是一个精灵套件游戏。我认为在这我不能使用核心数据。谢谢! :)
  • 所以你添加了 Utility 文件,并且你添加了提供给你的 PurchaseScene.swift 的方法。 步骤 1 完成。 第 2 步,在 PurchaseScene 中,添加以下行:if let value = Utility.readValueFromFile(file),将 print("ads removed") 替换为代码以删除任何可能可见的广告。 步骤 3buyProduct() 方法中,调用Utility.writeValueToFile("YES", "IAP_Ads")第 4 步,更新 GameViewController 并调用 Utility.readValueFromFile("IAP_Ads"),如果应删除广告,则不要显示展示广告的视图。

标签: ios swift sprite-kit in-app-purchase


【解决方案1】:

首先,我对 Swift 并不精通,但如果你不了解 Objective-C,我可以尝试为你转换它,这将花费我更多的时间。

现在,这可能不是理想的解决方案,但它应该能让您快速启动并运行。一旦您了解发生了什么,您就可以修改代码以满足您的需求。例如,您可以选择将多个值存储在一个文件中。如果你这样做,你可以使用 JSON 格式,或者你只是制作一个格式,如 : 并用换行符分隔值等。

// Gets a path to your app's local directory where it has permissions to write
+ (NSString *)getFilePathForFile:(NSString *)fileName
{
    NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    return [libraryPath stringByAppendingPathComponent:fileName];
}

// Writes a value to a file. Cast your value to a string before passing it in.
+ (void)writeValue:(NSString *)value toFile:(NSString *)file
{
    [value writeToFile:[self getFilePathForFile:file] atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}

// Reads a value from a file. Once you have this value, cast it back to the type you need.
+ (NSString *)readValueFromFile:(NSString *)file
{
    NSString *filePath = [self getFilePathForFile:file];

    if(![[NSFileManager defaultManager] fileExistsAtPath:filePath])
        return nil;

    return [NSString stringWithContentsOfFile:filePath
                                     encoding:NSUTF8StringEncoding
                                        error:NULL];
}

将这些方法复制并粘贴到某个文件中。如果您使用实用程序/帮助文件,请将其放在那里,因为这些可以是静态方法(“+”号),因此它们可以存在于任何地方。将这些方法中的self 替换为您放置它们的类。

接下来,如下所示调用它。

写:

// User purchased to remove adds, so let's save that now. (IAP stands for In-App Purchase
[self writeValue:@"YES" toFile:@"IAP_RemoveAds"];

阅读:

// Loading my new view, so need to check to see if the removal of ads was purchased...
NSString * sPurchased = [self readValueFromFile:@"IAP_RemoveAds"];
BOOL removeAds = [sPurchased boolValue];

希望这会有所帮助。

Swift 代码:

把它放在一个文件中,说叫它Utilities.swift

import Foundation

class Utility {

    // Gets a path to your app's local directory where it has permissions to write
    static func getFilePathForFile(fileName:String) -> String {
        let libraryPath = NSSearchPathForDirectoriesInDomains(.LibraryDirectory, .UserDomainMask, true)[0]

        return libraryPath.stringByAppendingString("/").stringByAppendingString(fileName as String)
    }

    static func writeValueToFile(value:String, fileName:String) {

        do {
            try value.writeToFile(Utility.getFilePathForFile(fileName), atomically: true, encoding: NSUTF8StringEncoding)
        } catch {
            print("\(error)")
        }
    }

    static func readValueFromFile(fileName:String) -> String? {

        let file = Utility.getFilePathForFile(fileName);

        if let value = try? String(contentsOfFile: file) {
            return value;
        }

        return nil;
    }
}

这样称呼它:

let file = "IAP_Ads"

// Writing to the file
Utility.writeValueToFile("YES", fileName: file);


// Reading from the file
if let value = Utility.readValueFromFile(file) {
    print("file exists... value = %@" , Utility.readValueFromFile(file) )

    let adsRemoved = (value == "YES" ? true : false)

    if adsRemoved {
        print("ads removed")

        // Remove the ads here
    }
}

因为我不能继续在推荐中描述代码,所以我在下面放置了您的 GameViewController 类的 viewDidLoad 方法的修改版本,该方法包含了当视图加载到未来:

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ShowAd(_:)), name: "ShowInterAdKey", object: nil)

    if let scene = GameScene(fileNamed:"GameScene") {
        // Configure the view.
        let skView = self.view as! SKView
        skView.showsFPS = false
        skView.showsNodeCount = false

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .AspectFill
        scene.size = self.view.bounds.size

        skView.presentScene(scene)
    }

    if let value = Utility.readValueFromFile(file) {

        let adsRemoved = (value == "YES" ? true : false)

        if !adsRemoved {
            // Ads have not been purchased yet, so show the ads

            self.banner.adUnitID = "myUnitID"
            self.banner.rootViewController = self

            var request: GADRequest = GADRequest()

            self.banner.loadRequest(request)

            request.testDevices = [kGADSimulatorID]

            interstital = GADInterstitial(adUnitID: "myUnitID")

            let req = GADRequest()
            interstital.loadRequest(req)
        }
    }
}

【讨论】:

  • 很遗憾我从来没有使用过 Objective-C,所以我可以t translate this. What do you mean with "paste the methods into a file somewhere"? Shouldnt 我将这段代码粘贴到 GameViewController 中?
  • @Claudio13 更新了答案。让我知道这是否适合您或您是否有任何其他问题。确认购买后,将Utility.writeValueToFile(...) 电话放入您的PurchaseScene.swift 文件中。将读取文件的逻辑放入您的 GameViewController 中的 viewDidLoad 中并删除广告。
  • 对不起,我的吸收速度有点慢,但我是初学者。该代码目前不起作用,但我认为那是因为我没有把它放在正确的地方或做错了什么。我创建了一个新文件 Utilities.swift 并将代码放在那里。但是第二个代码不起作用。非常感谢您的帮助和您的耐心!
  • @Claudio13 你能解释一下“第二个代码”是什么吗?出于测试目的,您可能会在您的两个文件中已经存在的静态方法(实用程序类的大括号之间的所有内容)。但是在测试之后(假设它有效),您会希望将其合并到一个地方以保持其清洁。在多个位置使用文字 "IAP_RemoveAds",因为如果您更改名称,则必须确保在任何地方都更改它。
  • @Claudio13 将let file = "IAP_Ads" 添加到答案的“这样称呼它:”部分。
猜你喜欢
  • 1970-01-01
  • 2020-08-05
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多