首页 文章

在IAP之后,应用程序崩溃 - 仅在更新podfiles之后

提问于
浏览
1

我在应用程序中设置了IAP,还有一些Cocoapods:

- Firebase/AdMob (4.8.0):
    - Firebase/Core
    - Google-Mobile-Ads-SDK (= 7.27.0)
  - Firebase/Core (4.8.0):
    - FirebaseAnalytics (= 4.0.5)
    - FirebaseCore (= 4.0.13)
  - Firebase/Crash (4.8.0):
    - Firebase/Core
    - FirebaseCrash (= 2.0.2)
  - FirebaseAnalytics (4.0.5):
    - FirebaseCore (~> 4.0)
    - FirebaseInstanceID (~> 2.0)
    - GoogleToolboxForMac/NSData+zlib (~> 2.1)
    - nanopb (~> 0.3)
  - FirebaseCore (4.0.13):
    - GoogleToolboxForMac/NSData+zlib (~> 2.1)
  - FirebaseCrash (2.0.2):
    - FirebaseAnalytics (~> 4.0)
    - FirebaseInstanceID (~> 2.0)
    - GoogleToolboxForMac/Logger (~> 2.1)
    - GoogleToolboxForMac/NSData+zlib (~> 2.1)
    - Protobuf (~> 3.1)

IAP和所有上述框架都非常完美!没问题 .

Once I do a pod update, things start to go south.

pod更新后,以下是更新版本:

PODS:

- Firebase/AdMob (4.10.1):
    - Firebase/Core
    - Google-Mobile-Ads-SDK (= 7.29.0)
  - Firebase/Core (4.10.1):
    - FirebaseAnalytics (= 4.1.0)
    - FirebaseCore (= 4.0.17)
  - Firebase/Crash (4.10.1):
    - Firebase/Core
    - FirebaseCrash (= 2.0.2)
  - FirebaseAnalytics (4.1.0):
    - FirebaseCore (~> 4.0)
    - FirebaseInstanceID (~> 2.0)
    - GoogleToolboxForMac/NSData+zlib (~> 2.1)
    - nanopb (~> 0.3)
  - FirebaseCore (4.0.17):
    - GoogleToolboxForMac/NSData+zlib (~> 2.1)
  - FirebaseCrash (2.0.2):
    - FirebaseAnalytics (~> 4.0)
    - FirebaseInstanceID (~> 2.0)
    - GoogleToolboxForMac/Logger (~> 2.1)
    - GoogleToolboxForMac/NSData+zlib (~> 2.1)
    - Protobuf (~> 3.1)

在此pod更新后 - 我的IAP在100%的成功购买时崩溃 . 代码中没有任何改变 . 只是对上面列出的最新框架的pod更新 .

IAP完成后,我将收到以下崩溃(并且“你已全部设置!”成功警告弹出):

libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

    libsystem_kernel.dylib`__pthread_kill:
    0x1859bc2e0 <+0>:  mov    x16, #0x148
    0x1859bc2e4 <+4>:  svc    #0x80
->  0x1859bc2e8 <+8>:  b.lo   0x1859bc300               ; <+32>
    0x1859bc2ec <+12>: stp    x29, x30, [sp, #-0x10]!
    0x1859bc2f0 <+16>: mov    x29, sp
    0x1859bc2f4 <+20>: bl     0x18599cbdc               ; cerror_nocancel
    0x1859bc2f8 <+24>: mov    sp, x29
    0x1859bc2fc <+28>: ldp    x29, x30, [sp], #0x10
    0x1859bc300 <+32>: ret

以下是调试面板的屏幕截图:https://i.stack.imgur.com/exmsO.png

[![Debug panel][1]][1]

以下是Firebase崩溃报告记录的内容:

-[__NSCFBoolean timeIntervalSince1970]: unrecognized selector sent to instance 0x1b6f8a878

Some items to note:

  • 代码中没有任何改变 .

  • Cocoapods在终端更新 . 步骤:1 . CD到目录,2 . $ pod更新

  • 我在更新Cocoapods之前测试了IAP - 一切都完美无缺;该应用程序没有崩溃 .

  • 在Cocoapod更新后测试IAP之前我做了一个项目清理 .

  • 在多个设备上崩溃 - (iOS 11.2.6和11.2.1) .

What is causing this crash since I only updated pods?

Bounty update:

我已经在这个问题上添加了Bounty,因为我现在正在其他项目中遇到它 . 我有一个旧项目,我想更新Pods(Firebase / Firebase崩溃/谷歌广告) . 以下是我采取的确切步骤:

  • CD到项目目录 .

  • Pod更新 . Cocoapods根本没有给我任何错误 .

在Xcode中,我运行了我更新了Podfile的项目...我通过购买IAP并在它完成后立即崩溃 . 同样,在pod文件更新之前不会发生这种情况! IAP工作正常,直到我运行pod更新 .

在新冒犯的项目中,我删除了Podfile,Podfile.lock和Pods目录 . 我从旧项目中拖动了相同的文件和目录 . 工作完美,没有任何崩溃 .

此问题仅在pod更新后持续存在 . 我迷路了..

IAP帮助文件

import StoreKit
import Firebase

public typealias MYProductIdentifier = String
public typealias MYProductRequestCompletionHandler = (_ success: Bool, _ products: [SKProduct]?) -> ()

// MARK: - Class

public class IAPHelper: NSObject {

    // Define properties!
    fileprivate let myProductIdentifiers: Set<MYProductIdentifier>
    fileprivate var myPurchasedProductIdentifiers = Set<MYProductIdentifier>()

    // Optional properties
    fileprivate var myProductsRequest: SKProductsRequest?
    fileprivate var myProductsRequestCompletionHandler: MYProductRequestCompletionHandler?


    // NOTIFICATION
    static let IAPTransactionInProgress = "IAPTransactionInProgress"
    static let IAPTransactionFailed = "IAPTransactionFailed"
    static let myIAPHelperPurchaseNotification = "IAPHelperPurchaseNotification" // Whenever a purchase takes place!
    static let myRestorePurchaseNotification = "myRestorePurchaseNotification" // Whenever a restore takes place!
    static let myPurchaseMadeThankYou = "myPurchaseMadeThankYou" // Whenever a first purchase takes place!


    // init!
    public init(productIDs: Set<MYProductIdentifier>) {
        myProductIdentifiers = productIDs

        // CHECK IF USER ALREADY BOUGHT! (to set the correct Defaults)
        for productIdentifier in productIDs {
            let purchased = MYConstants.nsDefaults.bool(forKey: productIdentifier)
            if purchased {
                myPurchasedProductIdentifiers.insert(productIdentifier)
                print("Already purchased! \(productIdentifier)")
            }
            else {
                print("Not yet purchased! \(productIdentifier)")
            }
        }

        super.init()

        SKPaymentQueue.default().add(self)

    }


    public func requestProducts(completionHandler: @escaping MYProductRequestCompletionHandler) {
        myProductsRequest?.cancel()
        myProductsRequestCompletionHandler = completionHandler

        myProductsRequest = SKProductsRequest(productIdentifiers: myProductIdentifiers)
        myProductsRequest?.delegate = self
        myProductsRequest?.start()
    }

    public func buyProduct(product: SKProduct) {
        let payment = SKPayment(product: product)
        SKPaymentQueue.default().add(payment)
    }

    public func isProductPurchased(productIdentifier: MYProductIdentifier) -> Bool {
        return myPurchasedProductIdentifiers.contains(productIdentifier)
    }

    public class func canMakePayment() -> Bool {
        return SKPaymentQueue.canMakePayments()
    }

    public func restorePurchases() {
        SKPaymentQueue.default().restoreCompletedTransactions()
    }

}

// MARK: - SKProductRequestsDelegate

extension IAPHelper: SKProductsRequestDelegate {

    public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let products = response.products
        myProductsRequestCompletionHandler?(true, products)
        reset()
    }

    public func request(_ request: SKRequest, didFailWithError error: Error) {
        // Called wheneever there is an ERROR or NO PRODUCTS!
        myProductsRequestCompletionHandler?(false, nil)
        reset()
        print("ERROR \(error.localizedDescription)")
    }

    private func reset() {
        myProductsRequest = nil
        myProductsRequestCompletionHandler = nil
    }

}

// MARK: - SKPaymentTransactionObserver

extension IAPHelper: SKPaymentTransactionObserver {

    // Tells us if the payment from the user was successful. Then react accordingly!

    public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        // Check outstanding transactions and react to them.
        for transaction in transactions {
            // check what kind of transaction is happening!
            switch transaction.transactionState {
            case .purchased :
                completeTransaction(transaction: transaction)
            case .failed :
                failedTransaction(transaction: transaction)
            case .restored :
                restoreTransaction(transaction: transaction)
            case .deferred :
                showTransactionAsInProgress(deferred: true)
            case .purchasing :
                showTransactionAsInProgress(deferred: false)
            }
        }

    }

    //MARK: Payment transaction related methods
    private func showTransactionAsInProgress(deferred: Bool) {
        NotificationCenter.default.post(name: Notification.Name(IAPHelper.IAPTransactionInProgress), object: deferred)
    }


    private func completeTransaction(transaction: SKPaymentTransaction) {
        postPurchaseNotificationForIdentifier(identifier: transaction.payment.productIdentifier)
        NotificationCenter.default.post(name: NSNotification.Name(IAPHelper.myPurchaseMadeThankYou), object: nil)
        SKPaymentQueue.default().finishTransaction(transaction)
    }

    private func failedTransaction(transaction: SKPaymentTransaction) {
        // User aborts payment!!
        if transaction.error!._code != SKError.Code.paymentCancelled.rawValue {
            print("Error: \(transaction.error!.localizedDescription)")
        }

        NotificationCenter.default.post(name: Notification.Name(IAPHelper.IAPTransactionFailed), object: transaction.error)

        SKPaymentQueue.default().finishTransaction(transaction)
    }

    private func restoreTransaction(transaction: SKPaymentTransaction) {
        guard let productIdentifier = transaction.original?.payment.productIdentifier else {
            return
        }

        postRestoreNotificationForIdentifier(identifier: productIdentifier)


        SKPaymentQueue.default().finishTransaction(transaction)
    }





    private func postPurchaseNotificationForIdentifier(identifier: String?) {
        // TELL VC THAT PURCHASE WAS OR WAS NOT success.
        guard let identifier = identifier else {
            return
        }

        Analytics.logEvent("IAP_Purchase_Made", parameters: nil)


        // I believe it crashes right here.

        // NEW ==================================
        myPurchasedProductIdentifiers.insert(identifier)
        MYConstants.nsDefaults.set(true, forKey: identifier)
        MYConstants.unlockLogic(restoring: false)
        NotificationCenter.default.post(name: Notification.Name(IAPHelper.myIAPHelperPurchaseNotification), object: identifier)
        // END NEW ==============================

    }



    private func postRestoreNotificationForIdentifier(identifier: String?) {
        // TELL VC THAT PURCHASE WAS OR WAS NOT success.
        guard let identifier = identifier else {
            return
        }

        Analytics.logEvent("IAP_Restore_Made", parameters: nil)

        // NEW ==================================
        myPurchasedProductIdentifiers.insert(identifier)
        MYConstants.nsDefaults.set(true, forKey: identifier)
        print("NEW RESTORE Identifier: \(identifier)")
        MYConstants.unlockLogic(restoring: true)
        NotificationCenter.default.post(name: NSNotification.Name(IAPHelper.myRestorePurchaseNotification), object: nil)
        // END NEW ==============================

    }



}

2 回答

  • 0

    为了找到调用TimeInterval的位置,我将为Bool添加一个公共扩展,这样你就可以为它添加一个断点并进行相应的修改 .

    像这样的东西:

    public extension Bool {
        public var timeIntervalSince1970:TimeInterval {
            get {
                // Add breakpoint here
                return 0
            }
        }
    }
    
  • 4

    我已经 temporarily 通过在运行更新之前返回到pod版本来修复此问题 .

    Here are the exact steps I took:

    • 在Podfile中,我注释掉了3个pod,已保存并已关闭 .

    • 然后我运行了 pod install 来删除3个pod .

    • 然后我跑了 pod deintegrate .

    • 然后我从项目目录中手动删除 Podfile.lockWorkspace .

    • 我重新打开了Podfile,取消注释了3个pod,然后明确指定了我在pod更新之前使用的依赖版本导致崩溃 . 见下文:

    pod'Firebase / Core','4.8.0'

    pod'Google-Mobile-Ads-SDK','7.27.0'

    pod'Firebase / Crash','4.8.0'

    该项目现在按计划运作 . 该应用程序完成IAP,没有例外 .

    Why is this occurring? 我被认为这不是代码问题,因为只有当我更新我的pod时才会出现此问题 .

相关问题