2011-01-24 48 views
5

我遇到了实施InAppPurchase的麻烦。我的购买实现是在模态视图控制器(AppUpgradeViewController)中,我从另一个模态视图呈现。我不喜欢这样写道:iPhone - SKProductsRequest和“发送到释放实例的消息”

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 

我想,这件事情与该产品的要求,但我不知道如何调试或修复它。似乎请求的答案是在它被解散(和释放)之后才发送给这个控制器,但我不知道如何阻止它在dismiss/dealloc之后接收消息。 感谢您的帮助!

+0

我有同样的问题,但以下解决方案都不适用于我。我启用了ARC。有什么建议么? – mvb 2012-08-11 07:10:56

回答

0

是不是因为你这样做:太早

[appUpgradeViewController release]; 

尝试在您分配给它的任何类的dealloc方法中执行此操作。 提供您当然不会多次分配它。这也需要你将你的声明移到类头中。

+0

我不认为我做得太早。这很可能是某种叫做控制器的方法,当它绝对不能。 – Marcin 2011-01-24 16:26:40

2

我想这是因为你已经发布了你的产品请求,但是你似乎没有设置指向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. 
+0

它的定义如下: @property(nonatomic,retain)SKProductsRequest * productsRequest; – Marcin 2011-01-24 16:07:58

+0

在这种情况下,您只需要`self.productsRequest = nil;`。做**不**做`[self.productsRequest释放];`,这会导致内存错误。 – DarkDust 2011-01-24 16:21:22

+0

它的定义如下: @property(nonatomic,retain)SKProductsRequest * productsRequest;我只在“ - (void)productsRequest:(SKProductsRequest *)请求didReceiveResponse:(SKProductsResponse *)响应”方法中释放它,所以直到控制器接收到响应才会释放它。如果我在控制器收到响应之前立即解除模态,则不会发生这种情况。 – Marcin 2011-01-24 16:21:26

4

您可能忘了清零AppUpgradeViewControllerdealloc

- (void)dealloc { 
    ... 
    productsRequest.delegate = nil; 
    [productsRequest release], productsRequest = nil; 
    ... 
    [super dealloc]; 
} 
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; 

我还除去从SKPaymentQueue观察者像this answer for another question说明。

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; 
0

斯威夫特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 
    } 
相关问题