iOS崩溃日志栈追踪解析:App Store版内购页面崩溃排查
问题:App Store版本加载内购页面崩溃,测试/TestFlight环境正常
应用在测试环境(包括TestFlight)中加载内购页面一切正常,但从App Store下载的版本却会崩溃。已获取崩溃日志,但无法区分代码相关部分与底层系统行为。
崩溃栈追踪信息
Thread 4 Crashed: 0 My app 0x00000001001b7908 Swift runtime failure: Index out of range + 0 (<compiler-generated>:0) 1 My app 0x00000001001b7908 subscript.get + 20 (<compiler-generated>:0) 2 My app 0x00000001001b7908 specialized Store.productsRequest(_:didReceive:) + 1376 3 My app 0x00000001001b75e8 list.get + 28 (Store.swift:0) 4 My app 0x00000001001b75e8 specialized Store.productsRequest(_:didReceive:) + 576 5 My app 0x00000001001b5d8c productsRequest + 12 (<compiler-generated>:0) 6 My app 0x00000001001b5d8c @objc Store.productsRequest(_:didReceive:) + 76 7 StoreKit 0x00000001ab0f8070 __27-[SKProductsRequest _start]_block_invoke_2 + 136 (SKProductsRequest.m:104) 8 libdispatch.dylib 0x000000018f5404b4 _dispatch_call_block_and_release + 32 (init.c:1518) 9 libdispatch.dylib 0x000000018f541fdc _dispatch_client_callout + 20 (object.m:560) 10 libdispatch.dylib 0x000000018f5450c8 _dispatch_queue_override_invoke + 788 (inline_internal.h:2632) 11 libdispatch.dylib 0x000000018f553a6c _dispatch_root_queue_drain + 396 (inline_internal.h:0) 12 libdispatch.dylib 0x000000018f554284 _dispatch_worker_thread2 + 164 (queue.c:7052) 13 libsystem_pthread.dylib 0x00000001d49e4dbc _pthread_wqthread + 228 (pthread.c:2631) 14 libsystem_pthread.dylib 0x00000001d49e4b98 start_wqthread + 8
相关函数代码
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { let myProduct = response.products for product in myProduct { list.append(product) } // Update labels localTitle = list[0].localizedTitle localDescription = list[0].localizedDescription // Format the price and display let formatter = NumberFormatter() formatter.locale = Locale.current formatter.numberStyle = .currency if let formattedPrice = formatter.string(from: list[0].price){ localPrice = ("Upgrade: \(formattedPrice)") delegate?.storeUpdateReceived(store: self) } }
疑问
- 能否定位到函数内具体的崩溃点?还是崩溃发生在进入函数代码之前?
- Index out of range错误是否由引用
list[0](可能list为空)导致,还是其他索引问题?
回答
崩溃定位
从栈追踪可以明确,崩溃发生在Store.productsRequest(_:didReceive:)函数内部,并非进入函数之前。栈帧2、4都指向该函数,结合栈帧0的Index out of range提示和栈帧1的subscript.get,可以确定是访问数组下标时越界触发的错误。
错误原因
就是因为直接访问list[0]导致的。测试/TestFlight环境中response.products有数据,但生产环境可能出现以下情况:
- 内购商品ID配置错误(比如生产环境未上架对应商品,或代码中ID与后台配置不一致)
- 用户所在地区受区域限制,无法获取该商品
- StoreKit返回的
response.products为空数组
此时list在循环后仍为空,直接访问list[0]就会触发下标越界崩溃。
修复方案
在访问list的元素前必须先判断数组是否为空,修改后的代码如下:
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { list.removeAll() // 先清空旧数据,避免重复添加 let myProduct = response.products for product in myProduct { list.append(product) } // 先判断list是否有有效数据 guard let firstProduct = list.first else { // 处理无商品的情况,比如通知代理加载失败 delegate?.storeUpdateFailed(error: .noProductsAvailable) return } // Update labels localTitle = firstProduct.localizedTitle localDescription = firstProduct.localizedDescription // Format the price and display let formatter = NumberFormatter() formatter.locale = Locale.current formatter.numberStyle = .currency if let formattedPrice = formatter.string(from: firstProduct.price){ localPrice = ("Upgrade: \(formattedPrice)") delegate?.storeUpdateReceived(store: self) } // 排查无效商品ID,帮助定位配置问题 if !response.invalidProductIdentifiers.isEmpty { print("无效商品ID: \(response.invalidProductIdentifiers)") // 可将该信息上报到日志系统 } }
内容的提问来源于stack exchange,提问作者laurie
相关产品推荐
相关产品推荐

