2008-10-30 7 views
12

Mam metodę, która zapisuje pliki w Internecie, działa, ale działa wolno. Następnie chciałbym uczynić interfejs użytkownika bardziej płynnym, więc tworzę NSThread do obsługi powolnego zadania.NSThread z błędem _NSAutoreleaseNoPool

widzę listę błędów, takich jak:

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

Bez NSThread wzywam metody jak:

[self save:self.savedImg]; 

I stosuje się następującą używać NSThread wywołać metodę:

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

Dzięki.

Odpowiedz

15

No przede wszystkim, są zarówno tworzenia nowego wątku dla kodu oszczędzania, a następnie za pomocą NSURLConnection asynchronicznie. NSUrlConnection we własnej implementacji będzie również spin-off inny wątek i oddzwoni do nowo utworzonego wątku, który w większości nie jest czymś, co próbujesz zrobić. Zakładam, że próbujesz się upewnić, że twój interfejs nie blokuje się podczas zapisywania ...

NSUrlConnection ma również wersję synchroniczną, która będzie blokować twój wątek i byłoby lepiej użyć tego, jeśli chcesz uruchomić własny wątek do robienia rzeczy. Podpis to

+ sendSynchronousRequest:returningResponse:error: 

Gdy otrzymasz odpowiedź, możesz oddzwonić do wątku interfejsu użytkownika. Powinno zadziałać coś jak poniżej:

- (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

obudowa i podpis są zbliżone do wywołania synchronizacji powinno być NSURLConnection * conn = [NSURLConnection sendSyncronousRequest: postRequest returnurningResponse: & response error: & error]; – Jehiah

0

Wewnątrz wątku należy utworzyć nową pulę autorelease, zanim zrobi się cokolwiek innego, w przeciwnym razie operacje sieciowe będą miały problemy, jak pan widział.

6

Musisz przede wszystkim utworzyć pulę autorelease dla wątku. Spróbuj zmienić metodę zapisywania się być tak:

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

    //Existing code 

    [pool drain]; 
} 

Użytkownik nie będzie, że powyższe nie wywołać zwolnić na NSAutoreleasePool. Jest to szczególny przypadek. Odpływ NSAutoreleasePool jest równoważny wydaniu przy pracy bez GC i zamienia na wskazówkę dla kolekcjonera, że ​​może być dobry punkt do uruchomienia kolekcji.

2

Może być konieczne utworzenie pętli uruchamiania. Dodam do rozwiązania Louisa:

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

Nie widzę powodu, aby używać wątków do tego. Po prostu wykonanie tego asynchronicznie w pętli uruchamiania powinno działać bez blokowania interfejsu użytkownika.

Zaufanie w pętli uruchamiania. Jest to zawsze łatwiejsze niż wątkowanie i ma na celu zapewnienie tego samego rezultatu (niezmiennie zablokowanego interfejsu użytkownika).