Comportamento ARC dentro de um bloco recursivo

Eu fiz estas duas funções do utilitário:

+ (void)dispatch:(void (^)())f afterDelay:(float)delay {
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay*NSEC_PER_SEC)),
                    dispatch_get_main_queue(),
                    f);
  }

+ (void)dispatch:(void (^)())f withInterval:(float)delay {
    void (^_f)() = nil; // <-- A
    _f = ^{
        f();
        [self dispatch:_f afterDelay:delay]; // <-- B
    };
    [self dispatch:_f afterDelay:delay];
}

A ideia é que você seria capaz de ligar:

[auto despacho:quadra afterDelay:demora]; - para obter um bloco executado após um tempo específico

e

[auto despacho:quadra withInterval:demora]; - para obter um bloco executado periodicamente

Ok, agora, se eu ligarexpedição: withInterval:, como é, ele criará um erro em tempo de execução porque quando o programa tenta executar a linha emB o valor de_f seránada; e isso, por sua vez, acontece porque_f contém uma referência ao valor de_f aA.

Isso poderia ser corrigido se eu mudarA para:

__block void (^_f)() = nil;

e com isso eu estou fazendo uma forte referência a_f, então quando o código chegarB o valor de_f é o valor final que foi atribuído a ele. O problema com isso é que estou incorrendo em um ciclo de retenção.

Finalmente, posso mudarA ser estar:

__block void (^_f)() __weak = nil;

e essadevemos cuidar de ambos os problemas, no entanto, descobri que quando o código atingeB o valor de_f está de novonada porque, no momento em que é avaliado,_f já foi desalocado.

Eu tenho algumas perguntas:

No último cenário, por que_f ser desalocado? Como eu digo ao ARC para reter o bloco pelo menos até a próxima chamada de envio?Qual seria a melhor maneira (e compatível com ARC) de escrever essas funções?

Obrigado pelo seu tempo.

questionAnswers(2)

yourAnswerToTheQuestion