2008-10-30 4 views
12

Ich habe eine Methode, die Dateien im Internet speichern, es funktioniert aber nur langsam. Dann möchte ich die Benutzerschnittstelle glatter machen, also erstelle ich einen NSThread, um die langsame Aufgabe zu behandeln.NSThread mit _NSAutoreleaseNoPool Fehler

Ich sehe eine Liste von Fehlern wie:

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

Ohne NSThread, ich nenne das Verfahren wie:

[self save:self.savedImg]; 

Und ich habe die folgende NSThread verwenden, um die Methode aufzurufen:

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

Danke.

Antwort

15

Nun zunächst einmal, Sie sind beide einen neuen Thread für Ihre Spar Code erstellen und dann asynchron mit NSURLConnection. NSUrlConnection in seiner eigenen Implementierung würde auch einen anderen Thread ausgliedern und Sie in Ihrem neu erstellten Thread zurückrufen, was meistens nicht das ist, was Sie versuchen zu tun. Ich nehme an, dass Sie nur versuchen, sicherzustellen, dass Ihre Benutzeroberfläche nicht blockiert, während Sie speichern ...

NSUrlConnection hat auch synchrone Version, die auf Ihrem Thread blockieren wird und es wäre besser, das zu verwenden, wenn Sie starten möchten dein eigener Thread für Dinge. Die Signatur lautet:

Dann, wenn Sie die Antwort zurück erhalten, können Sie zurück in Ihre UI-Thread aufrufen. So etwas sollte unter arbeiten:

- (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]; 
} 
+0

der Fall und die Signatur schließen sich auf den Synchronisierungsaufruf, es sollte NSURLConnection sein * conn = [NSURLConnection sendSyncronousRequest: postRequest returningResponse: & response error: & error]; – Jehiah

0

Innerhalb des Threads müssen Sie einen neuen Autorelease-Pool erstellen, bevor Sie etwas anderes tun, da sonst die Netzwerkoperationen Probleme haben, wie Sie gesehen haben.

6

Sie müssen hauptsächlich einen Autorelease-Pool für den Thread erstellen. Versuchen Sie, Ihre speichern Methode zu ändern, so sein:

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

    //Existing code 

    [pool drain]; 
} 

Sie werden Sie nicht, dass die oben rufen entbindet nicht auf dem NSAutoreleasePool. Dies ist ein besonderer Fall. Für NSAutoreleasePool ist Drain gleichbedeutend mit release, wenn es ohne GC ausgeführt wird, und konvertiert in einen Hinweis für den Kollektor, dass es sinnvoll wäre, eine Sammlung auszuführen.

2

Möglicherweise müssen Sie eine Ausführungsschleife erstellen. Ich werde Louis-Lösung hinzu:

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]; 
0

ich keinen Grund für Sie Themen für diesen Einsatz. Einfaches asynchrones Ausführen in der Laufschleife sollte funktionieren, ohne die Benutzeroberfläche zu blockieren.

Vertrauen in die Laufschleife. Es ist immer einfacher als Threading und wurde entwickelt, um das gleiche Ergebnis (eine nie blockierte Benutzeroberfläche) zu liefern.

Verwandte Themen