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

iPhone-SKProductsRequest和;已发送到解除分配实例的消息“;,iphone,Iphone,我在执行非应用程序购买时遇到麻烦。我的购买实现是在模态视图控制器(AppUpgradeViewController)中实现的,我从另一个模态视图中演示了它。我是这样做的: AppUpgradeViewController * appUpgradeViewController = [[AppUpgradeViewController alloc] init]; appUpgradeViewController.modalTransitionStyle = UIModalTransitionStyl

我在执行非应用程序购买时遇到麻烦。我的购买实现是在模态视图控制器(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 release]; 
太早了

试着在任何类的dealloc方法中实现它。
当然,前提是您不会多次分配它。这还需要您将声明移动到类标题中。

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

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

[self.productsRequest release];
您需要执行以下操作:

self.productsRequest = nil; // Property will do the release for you.
[self.productsRequest release];
self.productsRequest = nil; // Or else some might access this pointer,
                            // which now might point to nirvana.
如果它有
assign
选项,则需要执行以下操作:

self.productsRequest = nil; // Property will do the release for you.
[self.productsRequest release];
self.productsRequest = nil; // Or else some might access this pointer,
                            // which now might point to nirvana.

您可能忘记在
AppUpgradeViewController
dealloc
中取消请求委托:

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

我也有同样的问题。不是使用模式视图,而是使用导航控制器堆栈上的推送视图。当我在通过
SKProductsRequest
加载产品信息之前快速导航回时,它还会向我抛出一条
消息,该消息发送到解除分配的实例
异常。我通过调用SKProductsRequest对象上的
cancel
方法(请参阅)解决了这个问题

除此之外,我还将委托设置为
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
中删除了观察者,如中所述


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
    }

它的定义如下:@property(非原子,retain)SKProductsRequest*productsRequest;在这种情况下,您所需要做的就是
self.productsRequest=nil。不要做
[self.productsRequest release],这将导致内存错误。它的定义如下:@property(非原子,retain)SKProductsRequest*productsRequest;但我只在“-(void)productsRequest:(SKProductsRequest*)request-didReceiverResponse:(SKProductsResponse*)response”方法中释放它,所以在控制器收到响应之前不会释放它。若我在控制器收到响应之前立即关闭modal,则不会发生这种情况。但我尝试在我的dealloc方法中执行“[self.productsRequest release]”,错误为“***-[SKProductsRequest release]:消息已发送到解除分配的实例0x20c010”。我曾在dealloc中尝试过这种方法:“self.productsRequest.delegate=nil;”,但错误是:“***-[SKProductsRequest setDelegate:]:消息已发送到deallocated实例0x2f3090”。当我在dealloc中只执行“productsRequest=nil;”时,我会遇到与前面相同的错误:***-[AppUpgradeViewController respondsToSelector:]:消息发送到解除分配的实例0x2f9590”最终解决!我认为dealloc方法中正确的指令集是:self.productsRequest.delegate=nil;[self.productsRequest取消];self.productsRequest=nil;[[SKPaymentQueue defaultQueue]removeTransactionObserver:self];我不认为我做得太早。很可能有什么东西在调用控制器的方法,但它肯定不能。我有同样的问题,但下面的解决方案都不适合我。我已经启用了ARC。有什么建议吗?这花了很长时间才弄明白。Enable Zombie objects捕获到这条消息,该消息将我抛出
-[IAPurchaseViewController retain]:发送到解除分配实例的消息
。非常感谢。我不明白为什么你(和我)在取消时必须
nil
代表。它必须在所有引用都消失后立即消失,但某些东西使它与要回调的委托引用一起保持活动状态。。。