苹果内购内存错误调试
苹果规定,虚拟商品必须采用内购形式购买。
在接入内购过程中,遇到一个内存泄漏问题。如下图,
具体操作方式:点击获取商品列表页面,在商品列表没有加载完毕时,返回上一级页面,此时闪退。报错如上图。
解决方式:
分析:在此引入僵尸对象概念,所谓僵尸对象,是用于捕捉内存错误的调试功能。
通常情况下,当引用计数降为0时对象会立即被释放,但这使调试变得困难。如果开启了僵尸对象,那么对象就不会立即释放内存,而是被标记为僵尸。任何试图对其进行访问的行为都会被日志记录,因而你可以在对象的生命周期中跟踪对象在代码中被使用的位置。
NSZombieEnabled是一个环境变量,可以控制Core Foundation的运行时是否将使用僵尸对象。不应长期保留NSZombieEnabled,因为默认情况下是不会有对象被真正析构,这会导致应用使用大量的内存。特别说明:在发布的构建包中一定要禁用NSZombieEnabled。
设置NSZombieEnabled环境变量,需要进入Product->Scheme->Edit Scheme。选择左侧的Run,然后再右侧选取Diagnostics标签页。选中Enable Zombie Objects 选项。
设置完成后,报错如下:
通过日志可以清晰地确认是哪个类发生了内存泄漏。于是,追踪到这个类,发现注册的通知,在最后dealloc中已经移除了。同时根据断点,发现在返回上一级后,代理的方法,还在执行。故而想到试着把代理置为nil。
因而最终解决方式是:
SKProductsRequest *request;
- (void)dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
request.delegate = nil;
}
注:在进行必要清理时一定要移除观察者(具体来说,移除对通知的注册),解除回调(具体来说,将强引用的委托设置为nil)。