NSThread с ошибкой _NSAutoreleaseNoPool

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

Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
15 770
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Внутри потока вам необходимо создать новый пул автозапуска, прежде чем делать что-либо еще, иначе при сетевых операциях, как вы видели, возникнут проблемы.

В основном вам нужно создать пул автозапуска для потока. Попробуйте изменить метод сохранения следующим образом:

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

Jehiah 30.06.2009 07:02

Я не вижу смысла использовать для этого потоки. Простое выполнение этого асинхронно в цикле выполнения должно работать без блокировки пользовательского интерфейса.

Доверьтесь циклу выполнения. всегда проще, чем потоки, и предназначен для обеспечения того же результата (никогда не блокируемый пользовательский интерфейс).

Другие вопросы по теме