Store Swift v3中的产品延迟负载

时间:2016-12-19 03:03:35

标签: swift store ipv6 product storekit

目前正致力于向Apple提交我的申请,我遇到了一个奇怪的问题,即我的产品标识符没有立即加载。有时,如果您加载商店足够快,价格不会加载,您无法进行购买。 Apple报告称他们无法在他们的ipv6网络上进行购买,但我也在ipv4上看到了这个问题。

您是否看到任何可能导致此问题和/或ipv6非友好代码的逻辑问题?谢谢。

代码遵循:

IAPManager:

import Foundation
import StoreKit
import RealmSwift
import AVFoundation

class IAPManager: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver
{
static let sharedInstance = IAPManager()

private let realm = try! Realm()

// SKRequest
var request:SKProductsRequest!
// Array of SKProducts
var products:[SKProduct] = []

// Audio
var audioPlayer: AVAudioPlayer!

// Received Response From Store
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {

    // Check for Response
    self.products = response.products
}

// Creates String Array of Product Identifiers
func getStoreProductIdentifiers() -> [String]
{
    var identifiers: [String] = []

    let hintsPackXS = "net.identitywithheld.HintsPackXS"

    let hintsPackS = "net.identitywithheld.HintsPackS"

    let hintsPackM = "net.identitywithheld.HintsPackM"

    let hintsPackL = "net.identitywithheld.HintsPackL"

    let hintsPackXL = "net.identitywithheld.HintsPackXL"

    let removeAds = "net.identitywithheld.RemoveAds"

    identifiers.append(hintsPackXS)
    identifiers.append(hintsPackS)
    identifiers.append(hintsPackM)
    identifiers.append(hintsPackL)
    identifiers.append(hintsPackXL)
    identifiers.append(removeAds)

    return identifiers
}

// Perform Request with Identifiers
func performProductRequestForIdentifiers(identifiers:[String]){

    // Create Set Out of String Array and Type Cast as Set<String>
    // Note that sets are not in any paritcular order.
    let products = NSSet(array: identifiers) as! Set<String>

    // Set request to call based on products identifier
    self.request = SKProductsRequest(productIdentifiers: products)

    // Set Delegate to self (this class)
    self.request.delegate = self

    // Start Request
    self.request.start()
}

// Request Store Products
// Gets Identifiers and Performs Requests (Ties Together)
func requestStoreProducts(){
    self.performProductRequestForIdentifiers(identifiers: self.getStoreProductIdentifiers())
}

// Checks to see if user can make purchases
func setupPurchases() -> Bool
{
    // Check to See if Can Make Payments
    if SKPaymentQueue.canMakePayments(){

        // Sets Self As Observer
        SKPaymentQueue.default().add(self)

        return true
    }
    else
    {
        return false
    }
}

// Requests Payment Request
func createPaymentRequestForProduct(product:SKProduct)
{
    let payment = SKMutablePayment(product: product)
    payment.quantity = 1

    // Starts Payment Process
    SKPaymentQueue.default().add(payment)
}

// Payment Observer - Is Updated Whenever There's An Update
//MARK - Transaction Observer
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {

    // For Each Transaction in Transaction Array [SKPaymentTransaction]
    for transaction in transactions {
        switch transaction.transactionState{
        case .purchasing:
            print("purchasing")
            break
        case .purchased:
            print("purchased")
            complete(transaction: transaction)
            queue.finishTransaction(transaction) // Marks as Finished to Remove from Queue
            break
        case .deferred:
            print("deferred")
            break
        case .failed:
            print("failed")
            fail(transaction: transaction)
            queue.finishTransaction(transaction) // Marks as Finished to Remove from Queue
            break
        case .restored:
            print("restored")
            restore(transaction: transaction)
            queue.finishTransaction(transaction) // Marks as Finished to Remove from Queue
            break
        }
    }
}

// Complete Purchase
private func complete(transaction: SKPaymentTransaction) {
    print("complete...")
    deliverPurchaseNotificationFor(identifier: transaction.payment.productIdentifier)

    // Check Whether Sounds Are On
    let gameDataObj = realm.objects(GameData.self).filter("id == 0").first
    let soundOn = gameDataObj!.sound

    if(soundOn == true)
    {
        let hintSound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "purchaseComplete", ofType: "caf")!)
        try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try? AVAudioSession.sharedInstance().setActive(true)

        try? audioPlayer = AVAudioPlayer(contentsOf: hintSound as URL)
        audioPlayer.volume = 0.5
        audioPlayer!.prepareToPlay()
        audioPlayer!.play()
    }

    // If On, Play Sound
}


// Restore Purchases
private func restore(transaction: SKPaymentTransaction) {
    guard let productIdentifier = transaction.original?.payment.productIdentifier else { return }
    print("restore... \(productIdentifier)")
    deliverPurchaseNotificationFor(identifier: productIdentifier)
    SKPaymentQueue.default().finishTransaction(transaction)
}

private func fail(transaction: SKPaymentTransaction) {
    print("fail...")
    if let transactionError = transaction.error as? NSError {
        if transactionError.code != SKError.paymentCancelled.rawValue {
            print("Transaction Error: \(transaction.error?.localizedDescription)")
        }
    }
    SKPaymentQueue.default().finishTransaction(transaction)
}

private func deliverPurchaseNotificationFor(identifier: String?) {
    guard let identifier = identifier else { return }

    let gameDataObj = realm.objects(GameData.self).filter("id == 0")
    var hints = gameDataObj.first!.hints
    var hintsPurchase = false

    if(identifier == "net.identitywithheld.HintsPackXS")
    {
        print("Extra Small Pack")
        hints = hints + 10
        hintsPurchase = true
    }
    else if(identifier == "net.identitywithheld.HintsPackS")
    {
        print("Small Pack")
        hints = hints + 45
        hintsPurchase = true
    }
    else if(identifier == "net.identitywithheld.HintsPackM")
    {
        print("Medium Pack")
        hints = hints + 125
        hintsPurchase = true
    }
    else if(identifier == "net.identitywithheld.HintsPackL")
    {
        print("Large Pack")
        hints = hints + 200
        hintsPurchase = true
    }
    else if(identifier == "net.identitywithheld.HintsPackXL")
    {
        print("Extra Large Pack")
        hints = hints + 500
        hintsPurchase = true
    }
    else if(identifier == "net.identitywithheld.RemoveAds")
    {
        print("Remove Ads")
        try! realm.write {
            gameDataObj.first!.ads = false
        }
    }

    // If Hint Purchase, Set Hints
    if(hintsPurchase == true)
    {
        try! realm.write {
            gameDataObj.first!.hints = hints
        }
    }
}

func getTextWidth(font: UIFont, text: String) -> CGFloat
{
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 17, height: 17))
    label.text = text
    label.font = font
    label.sizeToFit()

    return label.frame.width
}

func getTextHeight(font: UIFont, text: String, width: CGFloat) -> CGFloat
{
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: 17))
    label.text = text
    label.font = font
    label.numberOfLines = 0
    label.sizeToFit()

    return label.frame.height
}
}

应用代表

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    openRealm()
    // Override point for customization after application launch.
    // Use Firebase library to configure APIs
    FIRApp.configure()
    GADMobileAds.configure(withApplicationID: adMobAppID)

    // Store Call to Get Products if Can Make Purchases

    if (IAPManager.sharedInstance.setupPurchases() == true)
    {
        IAPManager.sharedInstance.requestStoreProducts()

        UserDefaults.standard.set(true, forKey: "IAPCapable")
        UserDefaults.standard.synchronize()
    }
    else
    {
        UserDefaults.standard.set(false, forKey: "IAPCapable")
        UserDefaults.standard.synchronize()
    }

    // Initialize the Chartboost library
    Chartboost.start(withAppId: "identitywithheld", appSignature: "identitywithheld", delegate: nil)

    return true
}

1 个答案:

答案 0 :(得分:0)

经过大力测试后,我意识到我并没有推迟商店的负荷,因此产品没有满载。这不是ipv6问题。

要解决此问题,我添加了一个活动指示器并实施了一个计时器,以便在显示商店之前检查产品是否已加载。