У меня есть метод сохранения файлов в Интернете, он работает, но работает медленно. Затем я хотел бы сделать пользовательский интерфейс более плавным, поэтому я создаю 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];
Спасибо.





Внутри потока вам необходимо создать новый пул автозапуска, прежде чем делать что-либо еще, иначе при сетевых операциях, как вы видели, возникнут проблемы.
В основном вам нужно создать пул автозапуска для потока. Попробуйте изменить метод сохранения следующим образом:
- (void) save:(id)arg {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Existing code
[pool drain];
}
Вы не будете знать, что вышеупомянутое не вызывает освобождение в NSAutoreleasePool. Это особый случай. Для NSAutoreleasePool слив эквивалентен выпуску при работе без сборщика мусора и преобразуется в подсказку сборщику, что может быть хорошей точкой для запуска коллекции.
Возможно, вам потребуется создать цикл выполнения. Я добавлю к решению Луи:
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];
Прежде всего, вы создаете новый поток для своего кода сохранения, а затем асинхронно используете NSUrlConnection. NSUrlConnection в своей собственной реализации также будет отделять другой поток и вызывать вас обратно в ваш недавно созданный поток, что в большинстве случаев не является тем, что вы пытаетесь сделать. Я предполагаю, что вы просто пытаетесь убедиться, что ваш пользовательский интерфейс не блокируется во время сохранения ...
NSUrlConnection также имеет синхронную версию, которая блокирует ваш поток, и было бы лучше использовать это, если вы хотите запустить свой собственный поток для выполнения каких-либо действий. Подпись
+ sendSynchronousRequest:returningResponse:error:
Затем, когда вы получите ответ, вы можете перезвонить в свой поток пользовательского интерфейса. Что-то вроде ниже должно работать:
- (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];
}
Я не вижу смысла использовать для этого потоки. Простое выполнение этого асинхронно в цикле выполнения должно работать без блокировки пользовательского интерфейса.
Доверьтесь циклу выполнения. всегда проще, чем потоки, и предназначен для обеспечения того же результата (никогда не блокируемый пользовательский интерфейс).
регистр и подпись близки к вызову синхронизации, это должно быть NSURLConnection * conn = [NSURLConnection sendSyncronousRequest: postRequest returnResponse: & response error: & error];