Objetivo C Blocks como callbacks assíncronos e ACESSO RUIM

9

Eu tenho uma dúvida séria. Suponha o seguinte cenário:

  1. Você tem uma UIViewController na tela.
  2. O aplicativo inicia, digamos, uma chamada de back-end usando um bloco como retorno de chamada
  3. Você usa um substituto "próprio" para impedir a retenção de ciclos.
  4. O usuário acessa "Voltar" e o UIViewController é desalocado.
  5. Mais cedo ou mais tarde, o bloqueio de retorno é executado > > %código%

Antes do iOS 4, lidamos com esse tipo de situação definindo como BAD ACCESS a propriedade nil de ... não sei, qualquer que seja a classe que você estava usando.

Mas hoje em dia ... como você cancela um bloco? E se o bloco foi enviado para um método estático, e você não tem como anular essa referência de retorno de chamada?.

Nesse caso, devemos evitar usar o substituto do "eu"?

BTW, por "eu" substituto, eu quero dizer:

__block typeof(self) bself = self;

Obrigado !!

    
por Jorge Leandro Perez 30.07.2011 в 21:27
fonte

2 respostas

5

Bem, primeiro fora: Se (e somente se) sua razão para evitar o uso de self ou acesso direto de ivars dentro de um bloco realmente for reter-ciclos, então você deve estar em uma situação como

client => objectA => blockWithWeakBackReference

(onde => significa 'tem uma forte referência a').

Nesse caso, blockWithWeakBackReference só deve ser invocado por objectA , portanto, não há perigo de um ACESSO RUIM.

Se eu entendi sua pergunta corretamente, o que você realmente quer dizer é um cenário diferente:

  • objectA deseja que algum serviço de todo o aplicativo execute um bloco em seu nome , se alguma pré-condição for atendida.
  • Você evita usar self dentro do bloco porque deseja dispor de objectA antes de executar o bloqueio.

Um exemplo para isso pode ser uma fila de rede compartilhada que executa um bloco quando a solicitação termina de ser carregada por um motivo ou outro.

Nesse caso, sugiro que você copie simplesmente o design de NSNotificationCenter ' addObserverForName:object:queue:usingBlock: e faça seu serviço implementar um par de métodos como -(SomeTokenObjectType)addWorkerBlock:(void(^)(whatever-signature-makes-sense-for-you)) e -(void)cancelWorkerBlockWithToken:(SomeTokenObjectType) para enfileirar e cancelar seu retorno de chamada. blocos.

Em seguida, todos os objetos que usam esse serviço podem simplesmente ter um ivar do tipo NSMutableSet para armazenar o token para cada bloco enfileirado e - em seus dealloc - enumerar os tokens restantes, cancelando-os com o serviço.

    
por danyowdee 01.08.2011 / 18:39
fonte
0

"para evitar ciclos de retenção".

Mas você realmente tem um ciclo de retenção para evitar? Pense sobre isso. O bloco retém self (seu controlador de visualização). A chamada de back-end mantém o bloqueio. Mas onde self retém o bloco?

    
por newacct 23.10.2012 / 20:52
fonte