我在应用程序中设置了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 回答
为了找到调用TimeInterval的位置,我将为Bool添加一个公共扩展,这样你就可以为它添加一个断点并进行相应的修改 .
像这样的东西:
我已经 temporarily 通过在运行更新之前返回到pod版本来修复此问题 .
Here are the exact steps I took:
在Podfile中,我注释掉了3个pod,已保存并已关闭 .
然后我运行了
pod install
来删除3个pod .然后我跑了
pod deintegrate
.然后我从项目目录中手动删除
Podfile.lock
和Workspace
.我重新打开了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时才会出现此问题 .