在App Purchase / View Controller Crash中:消息发送到解除分配的实例

时间:2012-08-15 11:48:02

标签: iphone objective-c ios

我的视图控制器上有一个按钮,用于显示我的In App Purchases商店。

storeSinglePlayer *ssp = [[storeSinglePlayer alloc] initWithNibName:@"storeSinglePlayer" bundle:nil];

//Animation Code

CATransition* transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; 
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition forKey:nil];

[self.navigationController pushViewController:ssp animated:NO];

导航控制器成功将此商店推送到屏幕上。商店有一个后退按钮,执行以下代码:

[self.request cancel];
self.request.delegate = nil;
self.request = nil;
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

CATransition* transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromBottom; 
[self.navigationController.view.layer addAnimation:transition forKey:nil];


[self.navigationController popViewControllerAnimated:NO];

这也成功执行。但是,如果我现在单击按钮再次显示商店视图控制器,我会收到消息:

-[storeSinglePlayer respondsToSelector:]: message sent to deallocated instance 0xd642df0

这确实是一个非常着名的问题。正如您在上面的代码中所注意到的,我已经在stackoverflow中包含了我遇到的各种帖子的建议。已实施以下代码:

[self.request cancel];
self.request.delegate = nil;
self.request = nil;
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

此外,我的属性和相应的合成设置为:

@property (nonatomic, strong) SKProductsRequest *request;
@synthesize request = _request;

我不知道为什么会崩溃!

P.S:该项目已启用ARC。

3 个答案:

答案 0 :(得分:2)

在ARC发布后,有些东西正在调用你的ssp。您发布的代码并未明确说明发生的位置。

最有可能解决问题的一件事是在类声明中保留带有成员变量+属性的引用到ssp,而不是每次单击按钮时创建一个新引用。当你的第一个viewcontroller加载并重新使用它时,只需初始化它。

如果您想进一步调查,可以尝试注释掉设置过渡的块,看看它是否仍然崩溃。也许导航控制器在ssp释放后进行一些调用。

答案 1 :(得分:0)

当消息发送到解除分配的实例时,会从内存中释放一个对象,并且您尝试再次使用它。 ARC必须释放对象,因为它会自动检测到您不再需要它。尝试将以下其中一项添加到头文件中。

@property (nonatomic, strong) storeSinglePlayer *ssp;

storeSinglePlayer *__strong ssp;

上面重要的一句话是强大。它告诉ARC你想保留这个对象供以后使用。

答案 2 :(得分:0)

我到了搞砸的地方。我正在使用以下代码处理多个旋转:

[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"storeSinglePlayerLandscape"] owner:self options:nil];

[self viewDidLoad];

我现在意识到,这不是最好的做法,因为它多次调用viewDidLoad。不过,这不是问题的真正原因。当商店只显示几次并返回到前一个视图控制器时,它工作正常。但是在10-15次之后说,有太多的请求将返回产品,因此发送错误,“消息发送到解除分配的实例”。

我注释掉了代码,现在工作正常。

我知道,这是一个非常典型的问题,大多数用户可能不会面对。但为了以防万一,你使用了像我这样的实现了一些不好的代码,可能这个信息有效!