不良访问父节点为空-这是怎么回事?



我理解错误是什么,但在这种情况下不知道是什么导致它。一般情况下,这种情况只会出现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(是的,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];
}

在存储完成块时,需要像对待任何其他对象一样对待它。因此,如果您将块存储为变量,然后在与分配它的地方不同的范围内使用它,则需要通过复制或保留它来增加引用计数。简单的解决方案是创建一个strong属性来存储您的块。

取决于不可见的代码位,您的完成处理程序块可能没有被正确分配。如果您打算在创建块的作用域之外使用它,则需要复制它。

在你的接口中,声明你的完成处理程序的存储属性为"copy"。

@property (nonatomic, readwrite, copy) void (^completionHandler)(BOOL, NSArray *);

如果你想控制这个局部变量,你可以在你的实现中手动合成这个属性:

@synthesize completionHandler = _completionHandler;

相关内容

最新更新