iPhone - SKProductsRequest和“发送到解除分配的实例的消息”

时间:2011-01-24 12:55:11

标签: iphone

我在实施InAppPurchase方面遇到了麻烦。我的购买实现是在模态视图控制器(AppUpgradeViewController)中,我从另一个模态视图中呈现。我是这样做的:

AppUpgradeViewController * appUpgradeViewController = [[AppUpgradeViewController alloc] init];
appUpgradeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
appUpgradeViewController.delegate = self;
[self presentModalViewController:appUpgradeViewController animated:YES];
[appUpgradeViewController release];

然后,在我的升级视图中,我执行以下操作:

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
NSSet *productIdentifiers = [NSSet setWithObject:kInAppPurchaseProUpgradeProductId];
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
self.productsRequest.delegate = self;
[productsRequest start];

然后我实施了

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response

我在哪里:

[self.productsRequest release];

然后我还有其他必需的方法。

问题是当我显示模态时,并迅速解除它然后几秒后我在控制台上得到以下内容(我打开了NSZombieEnabled):

*** -[AppUpgradeViewController respondsToSelector:]: message sent to deallocated instance 0x2e91f0

我想这是产品请求的内容,但我不知道如何调试或修复它。似乎请求的答案是在它被解除(并且已经解除分配)之后才到达该控制器,但我不知道如何阻止它在解除/ dealloc之后接收消息。 谢谢你的帮助!

5 个答案:

答案 0 :(得分:9)

我遇到了同样的问题。不是模态视图,而是导航控制器堆栈上的推入视图。当我在通过SKProductsRequest加载产品信息之前快速导航回来时,它也会引发message sent to deallocated instance异常。我通过在SKProductsRequest对象上调用cancel方法(请参阅reference)解决了这个问题。

除此之外,我还将委托设置为nil

这是我的产品要求:

NSSet *productIdentifiers = [NSSet setWithObject:@"MY_IDENTIFIER"];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];

这就是我在dealloc方法中用来取消它的方法。

productsRequest.delegate = nil;
[productsRequest cancel];
productsRequest = nil;

我还从this answer for another question中描述的SKPaymentQueue移除了观察者。

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

答案 1 :(得分:4)

您可能忘记在AppUpgradeViewController的{​​{1}} dealloc中忘记您的请求代理人了:

- (void)dealloc {
   ...
   productsRequest.delegate = nil;
   [productsRequest release], productsRequest = nil;
   ...
   [super dealloc];
}

答案 2 :(得分:2)

我想那是因为你已经发布了你的productsRequest,但似乎你没有将指针设置为nil,这意味着它仍然指向现在无效的内存位置。

如何定义productsRequest属性?如果它具有retain选项,则代替:

[self.productsRequest release];

你需要这样做:

self.productsRequest = nil; // Property will do the release for you.

如果它有assign选项,则需要执行以下操作:

[self.productsRequest release];
self.productsRequest = nil; // Or else some might access this pointer,
                            // which now might point to nirvana.

答案 3 :(得分:0)

是因为你这样做了吗?

[appUpgradeViewController release]; 

太早了?

尝试在你分配它的任何类的dealloc方法中执行它。 当然,假设你没有多次分配它。这还需要您将声明移动到类标题中。

答案 4 :(得分:0)

Swift 3

如果您启动它,请关闭该请求。这是在Swift中执行此操作的安全方法。

    // strong reference at top of class
    var productRequest: SKProductsRequest!

    // at some point you will fetch products

    // on deallocating the window
    if productRequest != nil {
        productRequest.cancel()
        productRequest.delegate = nil
    }