влияние на счетчик выполнения executeSelector: withObject: afterDelay: inModes - PullRequest
2 голосов
/ 11 декабря 2010

Простая программа:

-(void)doSomething {

 NSLog(@"self rc=%d", [self retainCount]);

 [self performSelector:@selector(doMe:) withObject:nil afterDelay:0 inModes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];

 NSLog(@"self rc=%d", [self retainCount]);
}

-(void)doMe:(id)object {

 NSLog(@"i'm done");

 NSLog(@"self rc=%d", [self retainCount]);

}

Вывод:

self rc=1

self rc=2

i'm done

self rc=2

Почему счетчик приращений увеличивается и остается на 2?

Ответы [ 2 ]

13 голосов
/ 11 декабря 2010

Из - [NSObject executeSelector: withObject: afterDelay: inModes:] документации :

2013/11/01 Ответ

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

Если используется NSTimer, то объект должен быть кем-то сохранен, иначе не будет гарантии, что селектор может быть выполнен, поскольку никто не может гарантировать, что объект будет еще жив. Если не использовать ARC weak, произойдет сбой. По моему мнению, Apple отредактировала свою документацию, чтобы не упомянуть детали реализации, хотя я думаю, что это довольно очевидно.

Над документом НЕ упоминается слово retain , однако это НЕ означает, что цель не сохраняется.

Вот что я попробовал в отладчике на симуляторе iOS7.0:

(lldb) p (int)[self retainCount]
(int) $1 = 8
(lldb) expr (void)[self performSelector:@selector(description) withObject:nil afterDelay:1.0]
(lldb) p (int)[self retainCount]
(int) $2 = 9
(lldb) expr (void)[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(description) object:nil]
(lldb) p (int)[self retainCount]
(int) $3 = 8

Вывод: объект сохраняется, но это не то, о чем мы должны заботиться. Мистер решил: р

<ч />

Предыдущий ответ: (все еще действует)

Этот метод сохраняет получателя и параметр anArgument до тех пор, пока селектор выполнен.

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

Это та же логика, когда вы устанавливаете и пытаетесь запустить метод, используя NSTimers. Когда таймер фактически срабатывает, если целевой объект больше не существует (выпущен), ваше приложение будет аварийно завершено. Так что performSelector:withObject:afterDelay:... и его друзья здесь, чтобы сделать нашу жизнь немного проще, потому что она гарантирует, что приложение не будет зависать при срабатывании таймера;)

Надеюсь, это поможет

4 голосов
/ 11 декабря 2010

Вы, похоже, ошибочно полагаете, что NSLog в doMe: будет выполняться раньше второго в doSomething:.Это неверно.Методы performSelector:afterDelay:… по-прежнему планируют сообщение с помощью runloop, даже если задержка равна 0, поэтому оно будет выполняться при следующей итерации runloop.

Кроме того, практически нет веских причин для просмотра объекта.сохранить счет - и если вы посмотрите, не верьте тому, что видите.Результат метода retainCount в лучшем случае сбивает с толку, а в худшем - просто обманчив - для одного очевидного и чрезвычайно распространенного примера счет сохранения не отражает авто-выпуски.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...