Objective-C ARC: güçlü - elde tutma ve zayıf - atama


367

ARC tarafından sunulan özellikler için iki yeni bellek yönetimi özelliği vardır strongve weak.

Bunun dışında copy, tamamen farklı bir şey olduğu gibi, vs ve vs arasında herhangi bir fark var mı?strongretainweakassign

Anladığım kadarıyla, buradaki tek fark , işaretçiye weakatayacak nil, ancak assignolmayacak, bu da bırakıldıktan sonra işaretçiye bir mesaj gönderdiğimde programın çökeceği anlamına geliyor. Ama kullanırsam weak, bu asla gerçekleşmeyecek, çünkü mesaj göndermek nilhiçbir şey yapmaz.

Ben arasında herhangi farklar hakkında bilmiyorum strongve retain.

Kullanmalıyım bir sebep var mı assignve retainyeni projelerde veya kaldırılma tür?


12
Orada ARC tarafından tanıtılan özellikleri için üç yeni bellek yönetimi niteliklerdir strong, weakve unsafe_unretained.
Ocak'ta NJones

5
@NJones vardır iki özellik özellikler ( weakve strong) ve 4 değişken süresi kalifiye ( __strong, __weak, __unsafe_unretained, __autoreleasing). Aşağıdaki ARC Notlarına bakın.
Snowcrash

1
@SnowCrash Xcode'un, muhtemelen bir geliştirici önizlemesinin, assignARC ile derlerken kullanmanın bir hata olduğu bir sürümü vardı. Bu konuda silinmiş birçok cevap var. Görünüşe göre bu son sürümden önce değişti. unsafe_unretainederken benimseyenlerin çoğunun tercih ettiği özelliktir. unsafe_unretainedGeçerli bir özellik olduğunu kanıtlamak için Apple'ın "Bazı Sınıflar İçin Güvenli Olmayan Referansları Kullan" alt başlığı altındaki "Verileri Kapsülleme" bölümündeki "Objective-C ile Programlama" konusuna bakın. Şunu söylüyor: "Bir mülk için, bu, güvensiz_güvenilmeyen özellik kullanmak anlamına gelir:"
NJones

Yanıtlar:


230

Gönderen ARC Sürüm Notları Geçiş (mülkiyet niteliklerini bölümünde örnek).

// The following declaration is a synonym for: @property(retain) MyClass *myObject;

@property(strong) MyClass *myObject;

Yani strongaynı olan retainbir özellik bildiriminde.

Ben kullanırım ARC projeleri için strongyerine retainben kullanırım assignC ilkel özellikleri için ve weakObjective-C nesnelere zayıf referanslar için.


11
Aslında, ARC altında assignbir nesne için kullanmak bir derleme hatasıdır . Özelliği korumak istemiyorsanız ya weakda unsafe_unretained(ki bu güvenli değildir) kullanmak zorundasınız.
kobbal

5
assigndağıtım hedefi 4.0 ile ARC projelerinde benim için iyi derler.
Pascal

8
@Pascal: işletim sisteminin 5.0 veya üstü olmadığı dağıtım hedeflerinde zayıf referanslara izin verilmez. Eski projeler için yine de atama kullanabilirsiniz, ancak daha yeni sürümlere geçerseniz zayıf duruma geçmelisiniz
Mattia

1
Görünüşe göre Xcode 4 (ARC ile) vs. kullanarak NSManagedObject alt sınıfları üretir . Sanırım bu çoğunlukla zararsız, ama bunun tutarlılık için olması gerektiğini düşünüyorum ... ya da belki de önemli değil. stackoverflow.com/questions/7796476/…retainstrongstrong
Joe D'Andrea

3
@JeremyP Evet, cevabınız yerinde. @Mattia'ya tepki gösteriyordum. assignBazı durumlarda hala geçerli olduğuna dikkat çekiyordum.
Steven Oxley

606

Değişken özellik özelliklerini kontrol etmek için çok sayıda makale Stackoverflow yayınlarını ve demo uygulamalarını okuduktan sonra, tüm özellik bilgilerini bir araya getirmeye karar verdim:

  1. atomik // varsayılan
  2. nonatomic
  3. strong = koru // varsayılan
  4. güçsüz
  5. tutmak
  6. ata // varsayılan
  7. unsafe_unretained
  8. kopya
  9. Sadece oku
  10. readwrite // varsayılan

Aşağıda, kesinlikle size yardımcı olacak, yukarıda belirtilen tüm özellikleri bulabileceğiniz ayrıntılı makale bağlantısı bulunmaktadır. Burada en iyi cevapları veren herkese çok teşekkürler !!

İOS'ta değişken özellik özellikleri veya Değiştiriciler

1. güçlü (iOS4 = koru)

  • "Artık göstermeyene kadar bunu yığınta tut" diyor
  • diğer bir deyişle "Ben sahibim, bunu korumakla aynı şekilde nişan almadan önce bunu halledemezsiniz"
  • Yalnızca nesneyi tutmanız gerektiğinde güçlü kullanırsınız.
  • Varsayılan olarak tüm örnek değişkenleri ve yerel değişkenler güçlü işaretçilerdir.
  • Genellikle UIViewControllers (UI öğesinin ebeveynleri) için güçlü kullanırız
  • strong, ARC ile kullanılır ve bir nesnenin alıkonma sayısı konusunda endişelenmenize gerek kalmadan size yardımcı olur. ARC, işiniz bittiğinde sizin için otomatik olarak serbest bırakır. Strong anahtar kelimesinin kullanılması, nesneye sahip olduğunuz anlamına gelir.

Misal:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2. zayıf -

  • "başkası güçlü bir şekilde işaret ettiği sürece bunu koru" yazıyor
  • atama ile aynı şey, tutma veya bırakma yok
  • "Zayıf" başvuru, tutmadığınız bir başvurudur.
  • IBOutlets (UIViewController's Childs) için genellikle zayıf kullanırız.
  • zayıf başvuru, başvurulan nesneyi bir çöp toplayıcı tarafından toplanmaya karşı koruyamayan bir başvurudır.
  • Zayıf esas olarak atanmamış bir mülktür. Nesne yeniden yerleştirildiğinde, zayıf işaretçi otomatik olarak sıfır değerine ayarlanır

Misal :

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

@synthesize myButton;

BJ Homer sayesinde güçlü ve zayıf açıklama :

Nesnemizin bir köpek olduğunu ve köpeğin kaçmak istediğini düşünün (yeniden yerleştirilmek).

Güçlü işaretçiler köpek tasması gibidir. Tasma köpeğe takılı olduğu sürece, köpek kaçmayacaktır. Beş kişi tasmalarını bir köpeğe (bir nesneye beş güçlü işaretçi) bağlarsa, o zaman beş tasma da ayrılana kadar köpek kaçmaz.

Zayıf işaretçiler ise köpeğe işaret eden ve “Bak! Bir köpek!” Diyen küçük çocuklar gibidir. Köpek hala tasma üzerinde olduğu sürece, küçük çocuklar hala köpeği görebilir ve yine de işaret ederler. Tüm tasmalar ayrılır ayrılmaz, kaç tane çocuk işaret ettiğine bakılmaksızın köpek kaçar.

Son güçlü işaretçi (tasma) artık bir nesneyi işaret etmez etmez, nesne yeniden yerleştirilir ve tüm zayıf işaretçiler sıfırlanır.

Zayıf kullandığımızda?

Zayıf kullanmak isteyebileceğiniz tek zaman, döngüleri korumaktan kaçınmak istediğiniz zamandır (örneğin, ebeveyn çocuğu korur ve çocuk ebeveynini korur, böylece ikisi de serbest bırakılmaz).

3. koru = güçlü

  • korunur, eski değer serbest bırakılır ve alıkonur atanır yeni değerin gönderilmesi gerektiğini belirtir
  • atama ve gönderilen eski değeri tutmak
  • korumak güçlü ile aynıdır.
  • apple, eğer yazarsanız, otomatik olarak dönüştürülecek / sadece güçlü gibi çalışacağını söylüyor.
  • "tahsis" gibi yöntemler örtük bir "sakla" yı içerir

Misal:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.assign

  • atama varsayılan değerdir ve basitçe değişken atama gerçekleştirir
  • atama, derleyiciye özelliğin ayarlayıcı uygulamasını nasıl sentezleyeceğini bildiren bir özellik özniteliğidir
  • C ilkel özellikleri için atama ve Objective-C nesnelerine zayıf başvurular için zayıf kullanırdım.

Misal:

@property (nonatomic, assign) NSString *address;

@synthesize address;

5
2. "zayıf bir referans, atıfta bulunulan nesneyi bir çöp toplayıcı tarafından toplanmaya karşı korumayan bir referanstır" - objektif c'de çöp toplayıcı diye bir şey yoktur;
bucherland

1
ve bu hiyerarşi iOS tarafından otomatik olarak yönetilir. MVC konsepti hakkında bilgi edinin. Yani, ViewContorller'a iOS sunulduğunda ekran hiyerarşisini ekrana yükler (eksik görünümler oluşturur). Diğer ViewController sunulduğunda, bu ilk görünüm hiyerarşisi yeniden konumlandırılır. Ancak ViewController'da 'güçlü' varsa, bu görünüm ekran dışındayken yeniden konumlandırılamaz. Cihaz hafızası ve uygulamanın yavaşlamasına neden olan bu durum büyük bir etkisi olabilir. (Tabii ki cihaz çok fazla belleğe sahip ve 5-10 ekran uygulamasında kesinlikle iyi olacaksınız, ancak büyük uygulamada sorun
yaşarsınız

1
Zayıf kullandığımızda? 1. UI nesneleri için, 2. delegeler, 3. bloklar (bellek döngülerinden kaçınmak için kendinden ziyade kendini yerine kullanılmalıdır (yukarıda belirtildiği gibi)
bucherland

1
Bu harika cevapta bir hata var - güçlü - "ARC, işiniz bittiğinde sizin için otomatik olarak serbest bırakır", bu doğru değil. ARC, işaretçi olmadığında zayıf nesneleri otomatik olarak serbest bırakır. Güçlü - tutulması eşanlamlıdır, bu nedenle nesne korunur ve nesneyi sıfır yapmak bizim sorumluluğumuzdur
Ashwin G

1
@RDC, Ne anlama defaultgeliyor? Ben kullanırsanız @property (nonatomic) NSString *stringöyle strong? Yoksa assign? Çünkü ikisi de varsayılan.
Iulian Onofrei

40

nonatomic / atomik

  • atomik olmayan atomiktir
  • Atomik için nadir olması gereken çok spesifik bir gereksiniminiz yoksa daima atom olmayan kullanın (atomik iplik güvenliğini garanti etmez - aynı anda başka bir iplik tarafından ayarlandığında özelliğe erişen tezgahlar)

Güçlü / zayıf / atama

  • nesneleri korumak için güçlü kullanın - tutma anahtar kelimesi eşanlamlı olmasına rağmen, bunun yerine güçlü kullanmak en iyisidir
  • nesneyi tutmadan yalnızca bir işaretçi istiyorsanız zayıf kullanın - tutma döngülerinden (örn. temsilciler) kaçınmak için yararlıdır - nesne serbest bırakıldığında işaretçiyi otomatik olarak silecektir
  • ilkeler için atama kullanın - serbest bırakıldığında nesneyi temizlememesi dışında (zayıf olarak)

(İsteğe bağlı)

kopya

  • nesnenin sığ bir kopyasını oluşturmak için kullanın
  • kopyalanacak değişmez özellikleri her zaman ayarlamak için iyi bir uygulama - değişebilir sürümler değişmez özelliklere geçirilebildiğinden, kopyalama her zaman değişmez bir nesneyle uğraşmanızı sağlar
  • değişmez bir nesne içeri aktarılırsa, onu korur - değişebilir bir nesne geçirilirse, onu kopyalar

Sadece oku

  • özellik ayarını devre dışı bırakmak için kullanın (bir ihlal varsa kodun derlenmesini önler)
  • değişkeni doğrudan örnek değişkeni aracılığıyla değiştirerek veya getter yönteminin kendisinde değiştiren tarafından sağlananları değiştirebilirsiniz.

@Sakthimuthiah haklı, cevabını düzeltmelisin.
Adela Toderici

@Sakthimuthiah yanlış (ve bunu söyleyen herkes). Atomic, iş parçacığını güvenli hale getirmez, ancak davranışı nedeniyle kolayca yanlış olabilir. Lütfen okuyun: stackoverflow.com/questions/12347236/…
Chris J

39

Gibi bildiğim kadarıyla, strongve retainyaptıkları nedenle, eş olan tam aynı.

O zaman weakneredeyse gibidir assign, ancak nesnenin işaret ettiği nesnenin otomatik olarak sıfırlanmasından sonra otomatik olarak sıfır değerine ayarlanır.

Bu, onları değiştirebileceğiniz anlamına gelir.

Ancak karşılaştığım özel bir durum var, bunun assignyerine kullanmak zorunda kaldım weak. Diyelim ki iki özelliğimiz var delegateAssignve delegateWeak. Her ikisinde de tek güçlü referansa sahip olan bize ait olan delege saklanır. Delege yer değiştiriyor, bu yüzden -deallocyöntemimiz de çağrılıyor.

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething];
    [delegateAssign doSomething];
}

Delege zaten anlaşma sürecindedir, ancak yine de tam olarak yeniden konumlandırılmamıştır. Sorun şu ki weak, ona yapılan göndermeler zaten iptal edilmiş! Özellik delegateWeaknil içeriyor, ancak delegateAssigngeçerli nesne içeriyor (tüm özellikler önceden yayınlanmış ve iptal edilmiş ancak yine de geçerli).

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething]; // Does nothing, already nil.
    [delegateAssign doSomething]; // Successful call.
}

Oldukça özel bir durum, ancak bu weakdeğişkenlerin nasıl çalıştığını ve ne zaman geçersiz kılındığını bize gösteriyor.



20

Clang'ın Objective-C Automatic Reference Counting (ARC) dokümanı sahiplik niteleyicileri ve değiştiricileri açıkça açıklıyor:

Dört sahiplik niteleyicisi vardır:

  • __ otomatik kiralama
  • __ güçlü
  • __ * unsafe_unretained *
  • __ zayıf

Bir tür, __ otomatik yayınlama , __ güçlü veya __ zayıf olarak nitelendiriliyorsa, sahiplik niteliğinde olmayan niteliktedir .

Sonra beyan edilen mülk için altı sahiplik değiştiricisi vardır:

  • atamak __ * güvensiz_güvenilmemiş * sahiplik anlamına gelir.
  • copy , __ güçlü sahipliğin yanı sıra kopya semantiğinin ayarlayıcıdaki olağan davranışını ifade eder.
  • korumak __ güçlü sahiplik anlamına gelir .
  • Güçlü __ ima güçlü sahipliğini.
  • * güvensiz_güvenilmemiş *, __ * güvensiz_güvenilmemiş * sahiplik anlamına gelir.
  • zayıf demek . zayıf sahiplik.

Zayıf dışında , bu değiştiriciler ARC olmayan modlarda kullanılabilir.

Anlambilim açısından, sahiplik niteleyicileri yönetilen beş işlemde farklı bir anlama sahiptir : Okuma, Atama, Başlatma, İmha ve Taşınma, çoğu zaman sadece Atama işlemindeki farkı önemsiyoruz.

Atama , bir atama işleci değerlendirilirken gerçekleşir. Anlambilim niteliklere göre değişir:

  • __ güçlü nesneler için, yeni pointee önce korunur; ikinci olarak, değer ilkel anlambilim ile yüklenir; üçüncüsü, yeni pointee ilkel anlambilim ile lvalue içine depolanır; ve son olarak, eski sivri serbest bırakıldı. Bu atomik olarak yapılmaz; harici senkronizasyon, bunu eşzamanlı yükler ve depolar karşısında güvenli hale getirmek için kullanılmalıdır.
  • __ zayıf nesneler için, yeni pointee şu anda bölüştürülmekte olan bir nesne değilse, lvalue yeni pointee'yi işaret edecek şekilde güncellenir, bu durumda lvalue bir boş göstergeye güncellenir. Bu, nesneye yapılan diğer atamalara, nesneden okumalara ve yeni pointee'nin son sürümüne göre atomik olarak yürütülmelidir.
  • __ * güvensiz_güvenilmeyen * nesneler için, yeni nokta ilkel anlambilim kullanılarak değer değerine depolanır.
  • __ için autoreleasing nesneler, yeni pointee muhafaza autoreleased ve ilkel sözcüklerle lvalue depolanır.

Okuma, Başlatma, İmha ve Taşınmadaki diğer fark, lütfen belgedeki Bölüm 4.2 Anlambilime bakınız .


6

Güçlü ve Zayıf referansı anlamak için aşağıdaki örneği düşünün, displayLocalVariable adında bir yöntemimiz olduğunu varsayalım.

 -(void)displayLocalVariable
  {
     NSString myName = @"ABC";
     NSLog(@"My name is = %@", myName);
  }

Yukarıdaki yöntemde myName değişkeninin kapsamı displayLocalVariable yöntemiyle sınırlıdır, yöntem bittikten sonra "ABC" dizesini tutan myName değişkeni bellekten çıkarılır.

Şimdi, myName değişken değerini görünüm denetleyicisi yaşam döngümüz boyunca tutmak istersek. Bunun için self.username = myName;, aşağıdaki gibi myName değişkenine ( aşağıdaki koda bakın) güçlü bir referansa sahip olacak kullanıcı adı olarak adlandırılan özelliği oluşturabiliriz ,

@interface LoginViewController ()

@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;

- (void)displayLocalVariable;

@end

@implementation LoginViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

}

-(void)viewWillAppear:(BOOL)animated
{
     [self displayLocalVariable];
}

- (void)displayLocalVariable
{
   NSString myName = @"ABC";
   NSLog(@"My name is = %@", myName);
   self.username = myName;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}


@end

Şimdi yukarıdaki kodda myName'in self.username'a atandığını ve self.username öğesinin myName'e (dolaylı olarak "ABC" dizesine Güçlü referansı var) güçlü bir referansı olduğunu (@property kullanarak arayüzde beyan ettiğimiz gibi) görebilirsiniz. Bu nedenle String myName, self.username hayatta olana kadar bellekten çıkarılmaz.

  • Zayıf referans

Şimdi zayıf bir başvuru olan dummyName'e myName atamayı düşünün, self.dummyName = myName; Güçlü referansın aksine Weak, myName'i yalnızca myName'e Güçlü referans olana kadar tutacaktır. Zayıf referansı anlamak için aşağıdaki koda bakın,

-(void)displayLocalVariable
  {
     NSString myName = @"ABC";
     NSLog(@"My name is = %@", myName);
     self.dummyName = myName;
  }

Yukarıdaki kodda myName'e zayıf başvuru var (yani self.dummyName, myName'e zayıf başvuruya sahip), ancak myName'e Güçlü başvuru yok, bu nedenle self.dummyName myName değerini tutamayacak.

Şimdi tekrar aşağıdaki kodu düşünün,

-(void)displayLocalVariable
      {
         NSString myName = @"ABC";
         NSLog(@"My name is = %@", myName);
         self.username = myName;
         self.dummyName = myName;
      } 

Yukarıdaki kodda self.username, myName için Güçlü bir referansa sahiptir, bu nedenle myName ile ilişkili Strong bir referansa sahip olduğundan, metod bittikten sonra bile self.dummyName artık myName değerine sahip olacaktır.

Şimdi, bir değişkene Güçlü bir referans yaptığımızda, tutma sayısı birer birer artırılır ve değişken serbest bırakılmaz, tutma sayısı 0'a ulaşır.

Bu yardımcı olur umarım.


2

Kuvvetli:

  • Mülkiyet Yok Etmeyecek, ancak mülkü nil olarak ayarladıktan sonra nesne yok edilecek
  • Varsayılan olarak tüm örnek değişkenleri ve yerel değişkenler güçlü işaretçilerdir.
  • Yalnızca nesneyi tutmanız gerektiğinde güçlü kullanırsınız.
  • Genellikle UIViewControllers (UI öğesinin ebeveynleri) için güçlü kullanırız
  • IOS 4 (ARC olmayan) Tutma Anahtar Klavyesini Kullanabiliriz
  • IOS 5 (ARC) Güçlü Anahtar Kelime Kullanabiliriz

Örnek: @property (güçlü, anatomik olmayan) ViewController * viewController;

@synthesize viewController;

Güçsüz

Varsayılan olarak otomatik olarak al ve nil olarak ayarlanır

  • IBOutlets (UIViewController's Childs) ve temsilci için genellikle zayıf kullanıyoruz
  • atama ile aynı şey, tutma veya bırakma yok

Örnek: @property (zayıf, anatomik olmayan) IBOutlet UIButton * myButton;

@synthesize myButton;


1

Güçlü ve elde tutma arasındaki farklar:

  • İOS4'te güçlü, elde tutmaya eşittir
  • Bu, nesneye sahip olduğunuz ve artık onu işaret etmeyene kadar öbekte tuttuğunuz anlamına gelir
  • Koru yazarsanız, otomatik olarak güçlü gibi çalışır

Zayıf ve ata arasındaki farklar:

  • “Zayıf” referans, saklamadığınız bir referanstır ve başkası güçlü bir şekilde işaret ettiği sürece onu saklarsınız
  • Nesne "serbest bırakıldığında", zayıf işaretçi otomatik olarak sıfır değerine ayarlanır
  • "Atama" özellik özelliği, derleyiciye özelliğin ayarlayıcı uygulamasını nasıl sentezleyeceğini bildirir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.