Я должен назвать метод, который запускает некоторый асинхронный код
MyClass* myClass = [[MyClass alloc] init];
[myClass startAsynchronousCode];
Теперь я не могу просто выпустить его, поскольку это вызвало бы ошибку, так как код все еще работает:
[myClass release]; // causes an error
Что лучший способ состоит в том, чтобы иметь дело с памятью?
Вы можете - [MyClass startAsynchronousCode] вызвать обратный вызов:
typedef void(*DoneCallback)(void *);
-(void) startAsynchronousCode {
// Lots of stuff
if (finishedCallback) {
finishedCallback(self);
}
}
и затем создать экземпляр MyClass может выглядеть так:
MyClass *myClass = [[MyClass alloc] initWith: myCallback];
myCallback может выглядеть так:
void myCallback(void *userInfo) {
MyClass *thing = (MyClass *)userInfo;
// Do stuff
[thing release];
}
Вы должны сохранить свой объект myClass внутри метода startAsynchronousCode. И отпустите его внутри тоже после того, как он закончится.
Это поведение используется в NSURLConnection, UIAlertView и других асинхронных объектах.
Я всегда поддерживал переменную экземпляра, указывающую на асинхронный объект.
- (id)init {
myClass = [[MyClass alloc] init];
[myClass startAsynchronousCode];
}
- (void)myClassDidFinish:(MyClass *)myClass {
[myClass release];
}
Как дела? вызывая асинхронный код? Если вы используете NSThread + detachNewThreadSelector: toTarget: withObject: , вы обнаружите, что целевой объект сохраняется в потоке до его завершения, а затем освобождается. Таким образом, вы можете освободить объект сразу после асинхронного сообщения.
например.
@implementation MyClass
-(void) startAsynchronousCode
{
[NSThread detachNewThreadSelector: @selector(threadMain:) toTarget: self withObject: nil];
}
-(void) threadMain: (id) anObject
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// do stuff
[pool drain];
}
@end
С приведенным выше кодом совершенно безопасен следующий код:
MyClass* myClass = [[MyClass alloc] init];
[myClass startAsynchronousCode];
[myClass release];