Цель-C: Как правильно использовать управление памятью для асинхронных методов - PullRequest
8 голосов
/ 23 апреля 2010

Мне нужно вызвать метод, который запускает некоторый асинхронный код

MyClass* myClass = [[MyClass alloc] init];
[myClass startAsynchronousCode];

Теперь я не могу просто выпустить его, так как это приведет к ошибке, так как код все еще выполняется:

[myClass release];  // causes an error

Как лучше всего обращаться с памятью?

Ответы [ 4 ]

4 голосов
/ 23 апреля 2010

Вы можете иметь - [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];
}
3 голосов
/ 23 апреля 2010

Как вы вызываете асинхронный код? Если вы используете 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];
1 голос
/ 23 апреля 2010

Вы должны сохранить свой объект myClass внутренне в методе startAsynchronousCode. И отпустите его изнутри после того, как он закончится.

Это поведение используется в NSURLConnection, UIAlertView и других асинхронных объектах.

0 голосов
/ 23 апреля 2010

Я всегда поддерживал переменную экземпляра, которая указывает на асинхронный объект.

- (id)init {
    myClass = [[MyClass alloc] init];
    [myClass startAsynchronousCode];
}

- (void)myClassDidFinish:(MyClass *)myClass {
    [myClass release];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...