1

ビューコントローラに、アプリ内購入ストアを表示するボタンがあります。

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;

手がかりがない、なぜクラッシュするのか!

PS:プロジェクトはARC対応です。

4

3 に答える 3

2

ARC によってリリースされた後、何かがあなたの ssp を呼び出しています。あなたが投稿したコードは、それがどこで起こっているのかを明確にしません。

問題を解決する可能性が最も高いことの 1 つは、ボタンをクリックするたびに新しいものを作成するのではなく、クラス宣言でメンバー変数 + プロパティを使用して ssp への参照を保持することです。最初のビューコントローラーがロードされたときに一度だけ初期化して、代わりに再利用してください。

さらに調査したい場合は、トランジションを設定しているブロックをコメントアウトして、それでもクラッシュするかどうかを確認してください。ssp が解放された後に、ナビゲーション コントローラが何らかの呼び出しを行う可能性があります。

于 2012-08-15T12:01:56.553 に答える
0

ごちゃごちゃしているところに着きました。次のコードを使用して、複数のローテーションを処理していました。

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

[self viewDidLoad];

viewDidLoad を複数回呼び出すため、これはベスト プラクティスではないことに気付きました。それでも、それは実際には問題の原因ではありません。ストアが数回しか表示されず、以前のView Controllerに戻った場合、正常に機能します。しかし、10 ~ 15 回の後に、製品と共に返される要求が多すぎて、「割り当て解除されたインスタンスにメッセージが送信されました」というエラーが送信されるとします。

コードをコメントアウトしたところ、問題なく動作するようになりました。

これは非常に典型的な問題であり、ほとんどのユーザーが直面することはないかもしれません。しかし、念のため、私のような悪いコードを実装した場合、この情報が機能する可能性があります!

于 2012-08-16T18:26:44.577 に答える
0

メッセージが割り当て解除されたインスタンスに送信されると、オブジェクトがメモリから解放され、再度使用しようとしています。ARC は、オブジェクトが不要になったことを自動的に検出するため、オブジェクトを解放している必要があります。次のいずれかをヘッダー ファイルに追加してみてください。

@property (nonatomic, strong) storeSinglePlayer *ssp;

また

storeSinglePlayer *__strong ssp;

上記の重要な単語は強いです。これは、後で使用するためにこのオブジェクトを保持することを ARC に伝えます。

于 2012-08-15T12:01:18.423 に答える