Como posso evitar esse aviso no xcode. Aqui está o trecho de código:
[player(AVPlayer object) addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
queue:nil usingBlock:^(CMTime time) {
current+=1;
if(current==60)
{
min+=(current/60);
current = 0;
}
[timerDisp(UILabel) setText:[NSString stringWithFormat:@"%02d:%02d",min,current]];///warning occurs in this line
}];
objective-c
cocoa-touch
automatic-ref-counting
avplayer
retain
user1845209
fonte
fonte
timerDisp
uma propriedade na classe?player(AVPlayer object)
etimerDisp(UILabel)
?Respostas:
A captura
self
aqui está chegando com seu acesso implícito à propriedadeself.timerDisp
- você não pode consultarself
ou propriedades aself
partir de dentro de um bloco que será fortemente retido porself
.Você pode contornar isso criando uma referência fraca para
self
antes de acessartimerDisp
dentro do seu bloco:fonte
__unsafe_unretained
lugar.self
, é retido pela fila de expedição principal. Estou errado?E uma coisa muito importante a lembrar: não use variáveis de instância diretamente no bloco, use-as como propriedades de um objeto fraco, exemplo:
e não se esqueça de fazer:
outro problema pode aparecer se você passar uma cópia fraca de não retida por ninguém:
se
vcToGo
será desalocado e, em seguida, este bloco disparado, acredito que você irá travar com o seletor não reconhecido em uma lixeira que contémvcToGo_
variável agora. Tente controlá-lo.fonte
Versão melhorada
Então, a coisa toda seria assim:
Eu li este artigo várias vezes. Este é um excelente artigo de Erica Sadun sobre Como evitar problemas ao usar blocos e o NSNotificationCenter
Atualização rápida:
Por exemplo, rapidamente, um método simples com bloco de sucesso seria:
Quando chamamos esse método e precisamos usar
self
no bloco de sucesso. Usaremos os recursos[weak self]
eguard let
.Essa dança dita forte-fraca é usada pelo projeto popular de código aberto
Alamofire
.Para mais informações, consulte o guia de estilo rápido
fonte
typeof(self) strongSelf = self;
fora do bloco (em vez de __ fraco) estrongSelf = nil;
depois disse após o uso? Não vejo como o seu exemplo garante que o fracoSelf não seja nulo no momento em que o bloco é executado.Em outra resposta, Tim disse:
Isso não é bem verdade. Não há problema em você fazer isso desde que interrompa o ciclo em algum momento. Por exemplo, digamos que você tenha um timer que é acionado com um bloco que se retém e também mantém uma referência forte ao timer. Isso é perfeitamente correto se você sempre souber que destruirá o cronômetro em algum momento e interromperá o ciclo.
No meu caso, agora, eu tinha esse aviso de código que fazia:
Agora eu sei que o clang só produzirá esse aviso se detectar o método iniciado com "set" (e outro caso especial que não vou mencionar aqui). Para mim, eu sei que não há perigo de haver um loop de retenção, então mudei o nome do método para "useY:" É claro que isso pode não ser apropriado em todos os casos e geralmente você deseja usar uma referência fraca, mas Achei interessante notar minha solução, caso ajude outras pessoas.
fonte
Muitas vezes, esse não é realmente um ciclo de retenção .
Se você sabe que não é, não precisa trazer-se fracos infrutíferos ao mundo.
A Apple até obriga esses avisos com a API
UIPageViewController
, incluindo um método definido (que aciona esses avisos - como mencionado em outro lugar - pensando que você está definindo um valor para um ivar que é um bloco) e um bloco manipulador de conclusão (no qual você sem dúvida se referirá a si mesmo).Aqui estão algumas diretrizes do compilador para remover o aviso dessa linha de código:
fonte
Adicionando dois centavos em melhorar a precisão e o estilo. Na maioria dos casos, você usará apenas um ou alguns membros
self
deste bloco, provavelmente apenas para atualizar um controle deslizante. Fundiçãoself
é um exagero. Em vez disso, é melhor ser explícito e converter apenas os objetos que você realmente precisa dentro do bloco. Por exemplo, se for uma instância deUISlider*
, digamos,_timeSlider
faça o seguinte antes da declaração do bloco:Depois é só usar
slider
dentro do bloco. Tecnicamente, isso é mais preciso, pois restringe o ciclo de retenção potencial apenas ao objeto que você precisa, e não a todos os objetos internosself
.Exemplo completo:
Além disso, provavelmente o objeto que está sendo convertido em um ponteiro fraco já é um ponteiro fraco por dentro
self
, além de minimizar ou eliminar completamente a probabilidade de um ciclo de retenção. No exemplo acima,_timeSlider
é realmente uma propriedade armazenada como uma referência fraca, por exemplo:Em termos de estilo de codificação, como em C e C ++, as declarações de variáveis são melhor lidas da direita para a esquerda. Declarando
SomeType* __weak variable
nesta ordem lê mais naturalmente da direita para a esquerda, como:variable is a weak pointer to SomeType
.fonte
Encontrei este aviso recentemente e queria entendê-lo um pouco melhor. Após algumas tentativas e erros, descobri que ele se origina do início de um método com "add" ou "save". O objetivo C trata os nomes dos métodos que começam com "novo", "alocar" etc. como retornando um objeto retido, mas não menciona (que eu posso encontrar) nada sobre "adicionar" ou "salvar". No entanto, se eu usar um nome de método dessa maneira:
Vou ver o aviso na linha [self done]. No entanto, isso não irá:
Vou seguir em frente e usar a maneira "__weak __typeof (self) weakSelf = self" para fazer referência ao meu objeto, mas realmente não gosto de fazê-lo, pois isso confundirá um futuro eu e / ou outro desenvolvedor. Obviamente, eu também não poderia usar "adicionar" (ou "salvar"), mas isso é pior, pois tira o significado do método.
fonte