12

私はインターネットにファイルを保存する方法を持っています、それは機能しますがただ遅いです。次に、ユーザーインターフェイスをよりスムーズにしたいので、遅いタスクを処理するためにNSThreadを作成します。

次のようなエラーのリストが表示されます。

_NSAutoreleaseNoPool(): Object 0x18a140 of class NSCFString autoreleased with no pool in place - just leaking

NSThreadがない場合、次のようなメソッドを呼び出します。

[self save:self.savedImg];

そして、NSThreadを使用してメソッドを呼び出すために以下を使用しました。

NSThread* thread1 = [[NSThread alloc] initWithTarget:self
                                        selector:@selector(save:)
                                              object:self.savedImg];
[thread1 start];

ありがとう。

4

5 に答える 5

15

まず第一に、コードを保存するための新しいスレッドを作成し、NSUrlConnection を非同期的に使用しています。独自の実装の NSUrlConnection は、別のスレッドをスピンオフし、新しく作成したスレッドにコールバックしますが、これはほとんどあなたがしようとしていることではありません。保存中にUIがブロックされないようにしようとしているだけだと思います...

NSUrlConnection には、スレッドでブロックする同期バージョンもあります。何かを行うために独自のスレッドを起動する場合は、それを使用することをお勧めします。サインは

+ sendSynchronousRequest:returningResponse:error:

その後、応答が返ってきたら、UI スレッドにコールバックできます。以下のようなものが動作するはずです:

- (void) beginSaving {
   // This is your UI thread. Call this API from your UI.
   // Below spins of another thread for the selector "save"
   [NSThread detachNewThreadSelector:@selector(save:) toTarget:self withObject:nil];    

}

- (void) save {
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  

   // ... calculate your post request...
   // Initialize your NSUrlResponse and NSError

   NSUrlConnection *conn = [NSUrlConnection sendSyncronousRequest:postRequest:&response error:&error];
   // Above statement blocks until you get the response, but you are in another thread so you 
   // are not blocking UI.   

   // I am assuming you have a delegate with selector saveCommitted to be called back on the
   // UI thread.
   if ( [delegate_ respondsToSelector:@selector(saveCommitted)] ) {
    // Make sure you are calling back your UI on the UI thread as below:
    [delegate_ performSelectorOnMainThread:@selector(saveCommitted) withObject:nil waitUntilDone:NO];
   }

   [pool release];
}
于 2008-10-30T04:12:00.440 に答える
6

主にスレッドの自動解放プールを作成する必要があります。保存方法を次のように変更してみてください。

- (void) save:(id)arg {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    //Existing code

    [pool drain];
}

上記が NSAutoreleasePool で release を呼び出さないことに気付かないでしょう。これは特殊なケースです。NSAutoreleasePool のドレインは、GC なしで実行する場合のリリースと同等であり、コレクションを実行するのに適している可能性があるというコレクターへのヒ​​ントに変換されます。

于 2008-10-30T02:06:20.257 に答える
2

実行ループを作成する必要がある場合があります。Louisのソリューションに追加します。

BOOL done = NO;

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSRunLoop currentRunLoop];

// Start the HTTP connection here. When it's completed,
// you could stop the run loop and then the thread will end.

do {
    SInt32 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
    if ((result == kCFRunLoopRunStopped) || (result == kCFRunLoopRunFinished)) {
        done = YES;
    }
} while (!done);

[pool release];
于 2008-10-30T03:54:40.863 に答える
0

これにスレッドを使用する理由はわかりません。実行ループで非同期に実行するだけで、UI をブロックすることなく機能するはずです。

実行ループを信頼してください。これは常にスレッド化よりも簡単で、同じ結果 (決してブロックされない UI) を提供するように設計されています。

于 2008-10-31T04:58:45.353 に答える
0

スレッド内で、他のことを行う前に新しい自動解放プールを作成する必要があります。そうしないと、ネットワーク操作に問題が発生します。

于 2008-10-30T01:58:58.400 に答える