Como funciona o -performSelector: withObject: afterDelay: work?

Eu estou trabalhando atualmente sob o pressuposto de que -performSelector:withObject:afterDelay: não utiliza segmentação, mas agenda um evento para triggersr em uma data posterior no segmento atual. Isso está correto?

Mais especificamente:

 - (void) methodCalledByButtonClick { for (id obj in array) { [self doSomethingWithObj:obj]; } } static BOOL isBad = NO; - (void) doSomethingWithObj:(id)obj { if (isBad) { return; } if ([obj isBad]) { isBad = YES; [self performSelector:@selector(resetIsBad) withObject:nil afterDelay:0.1]; return; } //Do something with obj } - (void) resetIsBad { isBad = NO; } 

É garantido que -resetIsBad não será chamado até depois que -methodCalledByButtonClick retorne, assumindo que estamos rodando no thread principal, mesmo que -methodCalledByButtonClick leve um tempo arbitrariamente longo para completar?

Dos docs :

Invoca um método do receptor no encadeamento atual usando o modo padrão após um atraso.

A discussão vai além:

Esse método configura um cronômetro para executar a mensagem aSelector no loop de execução do segmento atual. O timer é configurado para ser executado no modo padrão (NSDefaultRunLoopMode). Quando o timer é triggersdo, o thread tenta desenfileirar a mensagem do loop de execução e executar o seletor. É bem-sucedido se o loop de execução estiver em execução e no modo padrão; caso contrário, o timer aguarda até que o ciclo de execução esteja no modo padrão.

A partir disso, podemos responder sua segunda pergunta. Sim, é garantido , mesmo com um atraso menor, já que o segmento atual está ocupado executando quando performSelector é chamado. Quando o encadeamento retornar ao loop de execução e desenfileirar o seletor, você terá retornado de seu methodCalledByButtonClick .

performSelector:withObject:afterDelay: agenda um cronômetro no mesmo segmento para chamar o seletor após o atraso passado. Se você se inscrever para o modo de execução padrão (ou seja, não use performSelector:withObject:afterDelay:inModes: , acredito que seja garantido que espere até a próxima passagem pelo loop de execução, para que tudo na pilha seja concluído primeiro.

Mesmo se você ligar com um atraso de 0, ele esperará até o próximo loop e se comportará como quiser aqui. Para mais informações, consulte os documentos .