#iphone #objective-c
#iPhone #objective-c
Вопрос:
Я использую эту ветку AudioStreamer для потоковой передачи аудио.
В контроллере представления у меня есть AudioStreamer в качестве свойства: @property (nonatomic, retain) AudioStreamer *streamer
Когда загружается контроллер представления, я запускаю поток, подобный этому:
self.streamer = [[AudioStreamer alloc] initWithURL:[NSURL URLWithString:preset.url]];
И чтобы остановить поток, освободить его и запустить новый поток, я делаю это:
[streamer stop];
[streamer release];
self.streamer = nil;
self.streamer = [[AudioStreamer alloc] initWithURL:[NSURL URLWithString:preset.url]];
Это не работает, потому что в initWithURL: методе есть проверка для просмотра if (self != nil)
и эта проверка завершается неудачей.
Кто-нибудь сможет пояснить, почему это не работает?
Спасибо.
РЕДАКТИРОВАТЬ: на самом деле некоторые проблемы с моим проектом вызывали странные проблемы. Тем не менее, я пометил ответ как правильный, потому что в нем было несколько полезных советов по памяти, которые также помогли.
Комментарии:
1. можете ли вы показать нам код метода initWithURL?
2. Какие симптомы заставляют вас полагать, что проблема связана с
initWithURL:
вызовом? В этом методе нет ничего необычного, иAudioStreamer
он суперNSObject
, так что маловероятно, что[super init]
произойдет сбой.3. Я бегло взглянул на класс AudioStreamer, если инициализатор в вашем fork тот же, то я на самом деле не знаю, почему он терпит неудачу, класс просто наследуется от NSObject, а initWithURL вообще ничего особенного не делает.
Ответ №1:
Вы переопределяете экземпляр streamer, задавая для него синтаксис dot и используя alloc.
Синтезированный установщик сохранит его один раз и выделит во второй раз, вам следует добавить автоматическое освобождение:
self.streamer = [[[AudioStreamer alloc] initWithURL:[NSURL URLWithString:preset.url]] autorelease];
Эта строка:
self.streamer = [[AudioStreamer alloc] initWithURL:[NSURL URLWithString:preset.url]];
Автоматически освободит для вас ранее назначенный экземпляр. Таким образом, вам не нужно вызывать
[streamer release];
self.streamer = nil;
перед этим.
Однако вы должны сделать
[streamer release];
в вашем методе освобождения.
Комментарии:
1. 1, хороший улов. Не заметил, что он чрезмерно сохранял (в дополнение к неправильному освобождению).
Ответ №2:
Прежде всего, вы дважды освобождаете streamer
, не намереваясь этого делать.
[streamer release]; // Releases the ivar, but doesn't set it to nil.
self.streamer = nil; // This is a property access, which releases the old
// value (again) before setting to nil.
И ваше назначение в последней строке приводит к утечке ссылки (вы выделяете, а затем присваиваете retain
свойству).
Вы как бы смешиваете метафоры доступа. Если у вас есть свойство, то используйте его исключительно:
[self.streamer stop];
self.streamer = [[[AudioStreamer alloc] initWithURL:[NSURL URLWithString:preset.url]] autorelease];
Все сказанное, неудачная self != nil
проверка не обязательно объясняется этим, но это может быть, в зависимости от того, что AudioStreamer делает для своего внутреннего управления объектами.