Gerenciamento de memória do Objective C com blocos, ARC e não-ARC

Eu tenho usado blocos há algum tempo, mas sinto que há coisas que sinto falta sobre o gerenciamento de memória em ambientes ARC e não-ARC. Eu sinto que uma compreensão mais profunda me fará esvaziar muitos vazamentos de memória.

AFNetworking é o meu principal uso de Blocos em um aplicativo específico. Na maioria das vezes, dentro de um manipulador de conclusão de uma operação, eu faço algo como "[self.myArray addObject]".

Nos ambientes ARC e não habilitados para ARC, "self" será retido de acordo comeste artigo da Apple.

Isso significa que sempre que um bloco de conclusão de uma operação de rede AFNetworking é chamado, self é retido dentro desse bloco e liberado quando esse bloco sai do escopo. Eu acredito que isso se aplica tanto ao ARC quanto ao não-ARC. Eu corri a ferramenta vazamentos e o analisador estático para que eu possa encontrar qualquer vazamento de memória. Nenhum mostrou nenhum.

No entanto, não foi até recentemente que me deparei com um aviso que eu não conseguia descobrir. Estou usando o ARC neste exemplo específico.

Eu tenho duas variáveis ​​de instância que indicam a conclusão e a falha de uma operação de rede

@property (nonatomic, readwrite, copy) SFCompletionBlock completionBlock;
@property (nonatomic, readwrite, copy) SFFailureBlock failureBlock;
@synthesize failureBlock = _failureBlock;
@synthesize operation = _operation;

Em algum lugar no código, faço isso:

[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id
                                                    responseObject) {
NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@{@"description": @"zero results"}];
            _failureBlock(error);
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"nothing");
        }];

Xcode reclama sobre a linha que chama o failureBlock, com a mensagem "Capturando" auto "fortemente neste bloco é susceptível de resultar em um ciclo de retenção. Acredito que o Xcode está certo: o bloco de falha mantém-se, e possui sua própria cópia o bloco, então nenhum dos dois será desalocado.

No entanto, tenho as seguintes questões / observações.

1) Se eu alterar _failureBlock (erro) para "self.failureBlock (error)" (sem aspas), o compilador para de reclamar. Por que é que? Isso é um vazamento de memória que o compilador erra?

2) Em geral, qual é a melhor prática para trabalhar com blocos em ambientes habilitados para ARC e não-ARC ao usarblocos que são variáveis ​​de instância? Parece que no caso de blocos de completação e falha no AFNetworking, esses dois blocos sãonão variáveis ​​de instância, então eles provavelmente não se enquadram na categoria de reter ciclos que descrevi acima. Mas ao usar blocos de progresso no AFNetworking, o que pode ser feito para evitar reter ciclos como o acima?

Eu adoraria ouvir os pensamentos de outras pessoas sobre ARC e não-ARC com blocos e problemas / soluções com gerenciamento de memória. Eu acho essas situações propensas a erros e eu sinto que algumas discussões sobre isso são necessárias para esclarecer as coisas.

Eu não sei se isso importa, mas eu uso o Xcode 4.4 com o último LLVM.

questionAnswers(2)

yourAnswerToTheQuestion