Вы не понимаете, как работает автоматический выпуск. Вы присваиваете переменной cleanString
автоматически выпущенный объект, а затем начинаете некоторую обработку на фоне, который использует это значение. Но когда метод, который запустил фоновую обработку, возвращает управление в основной цикл выполнения, автоматически освобожденная строка, хранящаяся в cleanString
, освобождается, и фоновый поток запускается в зомби.
Вы можете упростить код, используя Grand Central Dispatch :
- (void) startProcessing {
NSString *source = [NSString stringWithWhatever…];
dispatch_queue_t targetQ =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(targetQ, ^{
sound = flite_text_to_wave…;
dispatch_async(dispatch_get_main_queue(), ^{
[self speechProcessingDone];
});
});
}
Преимущества заключаются в том, что вам не нужно поддерживать собственный пул автоматического выпуска, вам не нужно добавлять дополнительные методы только для того, чтобы одна строка выполнялась в фоновом режиме и блок сохранит вашу строку, чтобы не разбиться.
Но вы, конечно, не должны использовать GCD только для того, чтобы обойти проблему автоматического освобождения, не зная, что происходит. Управление памятью - основа, вы должны быть на 100% уверены в том, что делаете.
Если это у вас над головой, убедитесь, что вы знаете, как работает управление памятью в Какао, например, прочитав это Objective-C учебное пособие Скотта Стивенсона . У вас есть , чтобы сделать это, пути назад нет.
Затем вернитесь к коду и увидите, что изменяемые строки, которые вы храните в cleanString
, автоматически высвобождаются, то есть они будут освобождены вскоре после того, как вы покинете текущую функцию. После запуска селектора в фоновом режиме вы выходите из текущей функции, и строка, хранящаяся в cleanString
, освобождается. Вскоре после этого фоновый поток попадает в следующую строку:
sound = flite_text_to_wave([cleanString UTF8String], voice);
Но так как объект, хранящийся в cleanString
, уже освобожден, вы получите сбой. Решение состоит в том, чтобы просто сохранить объект, пока вы не закончили с ним. Вы можете сохранить его перед запуском фонового потока и освободить после окончания фонового потока.