0

iOS アプリケーションに問題があります。

Web API にリクエストを送信していますが、バックグラウンド スレッドで実行しています。このメソッドを持つ Service というクラスがあります。

- (void)searchForRoutesFrom:(NSNumber *)startStationId
                         to:(NSNumber *)endStationId
                   delegate:(id<WAMSServiceDelegate>)delegateOrNil
{
    RouteSearchRequest *request = [[RouteSearchRequest alloc] init];
    ...request populate ...
    [NSThread detachNewThreadSelector:@selector(searchForRoutesInTheBackground:) 
                             toTarget:self withObject:request];
}

- (void)searchForRoutesInTheBackground:(RouteSearchRequest *)request
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    ...make the request and call back...
}

これはうまく機能していますが、ユーザーが (このサービスを使用して) ビューを離れることにした場合、スレッドが開始される直前に、サービス オブジェクトの割り当てが解除されます。スレッドが開始されると、searchForRoutesInTheBackground メソッドの呼び出しが試行され、アプリケーションがクラッシュします。

このスレッドを実行し、解放された呼び出しオブジェクトを処理するために、他にどのようなアプローチを使用できますか?

4

3 に答える 3

0

ただし、ユーザーが (このサービスを使用して) ビューを離れることを決定した場合、スレッドが開始される直前に、サービス オブジェクトの割り当てが解除されます。スレッドが開始されると、searchForRoutesInTheBackground メソッドの呼び出しが試行され、アプリケーションがクラッシュします。

これは不可能です。+detachNewThreadSelector:toTarget:withObject:のドキュメントを参照してください。それは言う

オブジェクト aTarget および anArgument は、切り離されたスレッドの実行中に保持され、その後解放されます。

つまり、呼び出し時に保持されますdetachNewThreadSelector:toTarget:withObject:。したがって、オブジェクトがその時点で有効であった場合、新しいスレッドの実行が終了するまで有効になります。

何か問題が発生している場合は、どこかで間違ったメモリ管理を行っているに違いありません。例: 1) オブジェクトが呼び出されるまでに既に割り当て解除されているdetachNewThreadSelector:toTarget:withObject:、または 2) 想定されていない別の場所でオブジェクトを過剰に解放している。

于 2012-07-13T23:53:38.427 に答える
0

retainスレッドを開始する前にオブジェクトを呼び出し、処理の最後 (戻る直前) にオブジェクトを解放することができます。

 - (void)searchForRoutesFrom:(NSNumber *)startStationId
                     to:(NSNumber *)endStationId
               delegate:(id<WAMSServiceDelegate>)delegateOrNil
{
RouteSearchRequest *request = [[RouteSearchRequest alloc] init];
...request populate ...

[self retain];
[NSThread detachNewThreadSelector:@selector(searchForRoutesInTheBackground:) 
                         toTarget:self withObject:request];
}

- (void)searchForRoutesInTheBackground:(RouteSearchRequest *)request
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
...make the request and call back...

[self release];
}

ブロックを使用した場合、それは自動的に行われますが、この場合の保持/解放は非常に簡単です。

于 2012-06-15T08:09:46.903 に答える
0

ロジックに関する情報が不十分なため、状況に応じて正しく答えることができるかどうかはわかりませんが、それらのシナリオは別の方法で処理します。私がしていることは、リクエストを開始してコールバックを処理するメソッドを使用して Web サービスと通信するための別のクラス (MVC のモデル) を作成することです。コールバックが実行されるとき、さまざまなシナリオがあります (CoreData を使用して結果を保持し、UI がこのイベントをキャッチして更新する (表示されている場合)、またはブロックがリクエストを行うメソッドに引数として渡され、コールバックで呼び出されます)。ブロックが実行され、通常、ブロックは次のように始まりますif(!self.view.window) return;つまり、現在のビューが表示されていない場合は何も起こりません)。しかし、どちらの状況でも、リクエストとコールバックは UI から完全に独立しているため、あなたのような問題は発生しません。

于 2012-06-15T08:12:37.950 に答える