Atributos configuradores de propriedade fracos e fortes em Objective-C

94

Qual é a diferença entre os atributos de setter de propriedades fracos e fortes em Objective-C?

@property(retain, [weak/strong]) __attribute__((NSObject)) CFDictionaryRef myDictionary;

Qual é o impacto e benefício?

Ouvi dizer que o fraco não está disponível no iOS 4 e precisamos usar atribuir.

É fraco semelhante a atribuir?

kkurni
fonte

Respostas:

102

Você pode ativar ou desativar o ARC para um arquivo específico. Se estiver ligado, você não pode usar retain release autoreleaseetc ... Em vez disso, você usa strong weakpara propriedades ou __strong __weak para variáveis ​​(o padrão é__strong ). Forte é o equivalente a reter, mas o ARC administrará a liberação para você.

A única vez em que você desejaria usar o fraco é se quisesse evitar ciclos de retenção (por exemplo, o pai mantém o filho e o filho mantém o pai, então nenhum dos dois nunca é liberado).

A parte 'ligação gratuita' (lançar de NSpara CF) é um pouco complicada. Você ainda precisa gerenciar manualmente CFRelease()e CFRetain()para objetos CF. Ao convertê-los de volta em objetos NS, você deve informar ao compilador sobre a contagem de retenção para que ele saiba o que você fez.

Está tudo aqui .

Robert
fonte
119

Aqui estão as informações que eu sei sobre propriedades variáveis

  1. atômico // padrão
  2. não atômico
  3. forte = reter // padrão
  4. fraco
  5. reter
  6. atribuir // padrão
  7. unsafe_unretained
  8. cópia de
  9. somente leitura
  10. readwrite // default

então, abaixo está o link do artigo detalhado onde você pode encontrar todos os atributos mencionados acima, que certamente irão ajudá-lo. Muito obrigado a todas as pessoas que aqui deram as melhores respostas !!

Atributos de propriedade variável ou modificadores no iOS

01. forte (iOS4 = reter) - diz "manter isso na pilha até que eu não aponte mais para ele" - em outras palavras "Eu sou o dono, você não pode desalocar isso antes de apontar bem com o mesmo que reter “- Você usa forte apenas se precisar reter o objeto. - Por padrão, todas as variáveis ​​de instância e variáveis ​​locais são indicadores fortes. - Geralmente usamos strong para UIViewControllers (pais do item de UI) - strong é usado com ARC e basicamente ajuda você, por não ter que se preocupar em reter a contagem de um objeto. O ARC o libera automaticamente para você quando você terminar de usá-lo. Usar a palavra-chave forte significa que você possui o objeto.

Exemplo:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

02. fraco (iOS4 = inseguro_ não retido) - diz "mantenha isso contanto que outra pessoa aponte para ele com força" - o mesmo que atribuir, não reter ou liberar - Uma referência "fraca" é uma referência que você não retém. - Geralmente usamos fraco para IBOutlets (Childs de UIViewController). Isso funciona porque o objeto filho só precisa existir enquanto o objeto pai existir. - uma referência fraca é uma referência que não protege o objeto referenciado da coleta por um coletor de lixo. - Fraco é essencialmente atribuir, uma propriedade não retida. Exceto quando o objeto é desalocado, o ponteiro fraco é automaticamente definido como nulo

Exemplo:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Explique : Graças a BJ Homer

Imagine que nosso objeto é um cachorro e que ele quer fugir (ser desalocado). Dicas fortes são como uma coleira no cão. Contanto que você tenha a guia presa ao cão, o cão não fugirá. Se cinco pessoas prenderem a coleira em um cão (cinco pontas fortes em um objeto), o cão não fugirá até que todas as cinco coleiras sejam retiradas. Os ponteiros fracos, por outro lado, são como crianças apontando para o cachorro e dizendo "Olha! Um cachorro!" Enquanto o cachorro ainda estiver na coleira, as crianças pequenas ainda podem ver o cachorro e ainda apontam para ele. Assim que todas as coleiras são retiradas, porém, o cachorro foge, não importa quantas crianças apontem para ele. Assim que o último ponteiro forte (leash) não apontar mais para um objeto, o objeto será desalocado e todos os ponteiros fracos serão zerados. Quando usamos fraco? A única vez em que você desejaria usar o fraco é se quisesse evitar ciclos de retenção (por exemplo, o pai mantém o filho e o filho mantém o pai, então nenhum dos dois nunca é liberado).

SwiftBoy
fonte
1
Na lista inicial, não tenho certeza do que você quer dizer com “padrão”. Você tem ambos strong=retaine assignrotulado como padrão, mas não pode ser ambos.
Slipp D. Thompson
27
Gostei do cachorro na comparação da coleira. Explica muito bem.
Jarrett Barnett
1
Boa explicação, embora o iOS não use coleta de lixo. ARC! = Coleta de lixo (!), São tecnologias diferentes.
1
fraco e inseguro_ não retido são diferentes (o primeiro usa zero referências fracas, enquanto o último faz agachamento)
wcochran
1
Estou apenas aprendendo iOS, mas parece que você perdeu o weake strongem seus exemplos. Não faria mais sentido que um pai tivesse strongreferências a seus filhos (como a myButtonpropriedade da UIViewControllerclasse que você mostrou ser weak) e que os filhos mantivessem weakreferências a seus pais (como a viewControllerpropriedade de uma classe filha que você ' em vez disso, defina como strong). Por exemplo, lendo Matt Neuburg, iOS 7 Programming Fundamentalsele mostra que uma classe declarando seu delegado como uma propriedade irá mantê-la `fraca, o que parece justo.
Bogdan Alexandru
2

Para destacar as partes dos documentos mencionados por Robert que respondem explicitamente às suas duas últimas perguntas:

// The following declaration is similar to "@property(assign) MyClass *myObject;"
// except that if the MyClass instance is deallocated,
// the property value is set to nil instead of remaining as a dangling pointer.
@property(weak) MyClass *myObject;

Isso é conhecido como uma referência fraca de zeragem. Você pode criar referências fracas que não estão zerando referências fracas usando __unsafe_unretained, mas como o nome indica, isso geralmente não é recomendado.

Também na documentação:

Weak references are not supported in Mac OS X v10.6 and iOS 4.
Rimsky
fonte
1
Sim, está correto, __unsafe_unretainedé a versão ARC do assign.
Robert
2

O uso claro da propriedade WEAK é o seguinte:

Any control whose properties we need to change(eg:text of a label) is declared weak and as below:

@property(nonatomic,weak) IBOutlet Type *name;
Eg: @property(nonatomic,weak) IBOutlet UILabel *myLabel;
Alen Alexander
fonte
1
Usando fraco em minhas propriedades, recebo um aviso dizendo: "O receptor fraco pode ser imprevisivelmente definido como nulo". Eu vi alguns outros posts que para evitar este aviso, você tem que criar uma referência local forte. E se isso é verdade, de que adianta tornar uma propriedade fraca, se no final tenho que criar uma referência forte?
arh
0

vamos dar um exemplo para elaborar mais (as respostas acima já são ótimas), talvez este exemplo ajude um pouco mais

vamos ter duas classes A e B

//A.h

#import <Foundation/Foundation.h>
#import "B.h"

@interface A : NSObject

@property (nonatomic, strong) B *objB;

@end

@implementation A
//

@end

//B.h

    #import <Foundation/Foundation.h>
    #import "A.h"


    @interface B : NSObject

    @property strong text(nonatomic, strong) A *objA;

    @end

    @implementation B
    //

    @end

    and in main

    #import "B.h"
    #import "A.h"

    {
    A *obja =[[A alloc]init];
    B *objb =[[B alloc]init];
    A.objB=objb;
    B.objA=obja;
   }

o código acima irá gerar um ciclo de retenção porque ambos são do tipo forte a --------> b ---------> a

então, para evitá-lo, você deve usar a propriedade week de um deles para que se refira semanalmente ao objeto e não aumente sua contagem de referência.

Anurag Bhakuni
fonte