我理解错误是什么,但在这种情况下不是导致它的原因。在一般情况下,它可能发生在1%的时间(可能更少),但我发现了一种极端的方式来引起它,我将在下面描述。首先,我使用的是Ray Wenderlich网站上的应用内购买流程。以下是具体的问题:
·H:
typedef void (^RequestProductsCompletionHandler)(BOOL success, NSArray * products);
@interface IAPHelper : NSObject
- (void)requestProductsWithCompletionHandler:RequestProductsCompletionHandler)completionHandler;
@end
的.m
@implementation IAPHelper
{
SKProductsRequest * _productsRequest;
RequestProductsCompletionHandler _completionHandler;
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSLog(@"Loaded list of products...");
_productsRequest = nil;
NSArray * skProducts = response.products;
for (SKProduct * skProduct in skProducts) {
NSLog(@"Found product: %@ %@ %0.2f",
skProduct.productIdentifier,
skProduct.localizedTitle,
skProduct.price.floatValue);
}
_completionHandler(YES, skProducts); // here is where bad access occurs
_completionHandler = nil;
}
再次,99%以上的时间这个工作正常。鉴于常规使用中不良访问的频率很低,并且难以诊断。但是,我找到了导致这个问题的极端方法。设置为“Tab 1”是表视图控制器,“Tab 2”是使用上面代码的表视图控制器。如果我在两个标签之间快速来回切换,我通常会导致问题发生在从几秒到20-30秒的任何地方。在这种情况下,每次都不会发生但绝大多数情况都会发生。如上所示,以下行获取了错误的访问错误,其中Parent为Null。
_completionHandler(YES,skProducts);
要解决此问题,我可以执行以下操作:
if (_completionHandler)
{
_completionHandler(YES, skProducts);
_completionHandler = nil;
}
虽然该修复工作确实有效并且确实解决了问题,但我仍然为此感到困扰。有关于这个原因的任何想法吗?
更新
向所有人道歉,因为我忘记在上面粘贴的内容中包含以下内容。
- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
// 1
_completionHandler = [completionHandler copy];
// 2
_productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers];
_productsRequest.delegate = self;
[_productsRequest start];
}
答案 0 :(得分:0)
存储时,您需要将完成块视为任何其他对象。因此,如果要将块存储为变量,然后在与分配块的范围不同的范围内使用它,则需要通过复制或保留它来增加引用计数。简单的解决方案是创建一个strong
属性来存储块。
答案 1 :(得分:0)
根据看不见的代码位,可能无法正确分配完成处理程序块。如果您打算在创建它的范围之外使用它,则需要复制块。
在您的界面中,将完成处理程序的存储属性声明为“copy”。
@property (nonatomic, readwrite, copy) void (^completionHandler)(BOOL, NSArray *);
如果要控制局部变量,可以在实现中手动合成属性:
@synthesize completionHandler = _completionHandler;