4

我在应用购买中使用的应用和我的参考资料

当我通过一个块从服务器加载产品时,同时我切换到 UITabBarController 内的其他选项卡,并且在加载产品时应用程序崩溃

这是我的代码

//Load products from server
[[LAInAppHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
    if (success) {
        // even i do nothing in here app till crashed
    }
}];

如果我删除此行,我可以在任何选项卡之间切换。崩溃时应用程序不会抛出任何东西,即使我启用了 Zombie 对象。只是不好的访问

4

1 回答 1

3

LAInAppHelper您链接的教程中的实现存在问题:帮助程序将您的应用程序视为非并发。

这是正在发生的事情:共享实例LAInAppHelper有一个sharedInstance,它拥有_completionHandler(除其他外)。

requestProductsWithCompletionHandler:方法分配_completionHandler已传入块的副本。这对于第一个请求是可以的,但如果另一个请求“正在运行”,则由于此重新分配,ARC 将释放另一个请求的完成块。如果您切换到的选项卡启动并发请求,则初始请求将返回到已释放的块,从而导致未定义的行为,并可能导致崩溃。

要解决此问题,您需要将类拆分为两部分 - 一部分包含所有请求共有的项目(即_productIdentifiers_purchasedProductIdentifiers)和特定于请求的项目(_productsRequest_completionHandler)。

第一个类的实例(我们称它为LAInAppHelper)保持共享;第二个类的实例(我们称之为它LAInAppHelperRequest)是在方法内按请求创建的requestProductsWithCompletionHandler:

-(id)initWithHelper:(LAInAppHelper*)helper
    andCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
    if (self = [super init]) {
        _completionHandler = [completionHandler copy];
        _productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:helper.productIdentifiers]; // You will need to make productIdentifiers a property
        _productsRequest.delegate = self;
        [_productsRequest start];
    }
    return self;
}

您还需要创建一个包装 的块_completionHandler,如下所示:

- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
    __block LAInAppHelperRequest *req = [[LAInAppHelperRequest alloc] initWithHelper:self andCompletionHandler:^(BOOL success, NSArray *products) {
         completionHandler(success, products);
         req = nil;
    }];
}
于 2013-07-23T17:43:09.110 回答