Objective-C'deki ivars ve özellikler arasındaki fark nedir


82

Objective-C'de ivars ve özellikler kullanmanın bu 3 yolu arasındaki anlamsal fark nedir?

1.

@class MyOtherObject; 
@interface MyObject {
}
@property (nonatomic, retain) MyOtherObject *otherObj;

2.

#import "MyOtherObject.h"
@interface MyObject {
    MyOtherObject *otherObj;
}
@property (nonatomic, retain) MyOtherObject *otherObj;

3.

#import "MyOtherObject.h"
@interface MyObject {
    MyOtherObject *otherObj;
}

Yanıtlar:


57

Sayı 1 , derleyici ve bağlayıcı tarafından görülen kod miktarını en aza indirmek ve ayrıca potansiyel olarak döngüsel referanslardan kaçınmak için MyOtherObject sınıfını ileri bildirerek diğer ikisinden farklıdır. Bu şekilde yaparsanız, #import'u .m dosyasına koymayı unutmayın.

Bir @property bildirerek (ve .m içinde @synthesize ile eşleşerek), belirttiğiniz şekilde işlenen bellek semantiğiyle otomatik olarak erişimci yöntemleri oluşturursunuz. Çoğu nesnenin genel kuralı Saklama'dır, ancak NSStrings, örneğin Kopyayı kullanmalıdır. Oysa Singletons ve Delegeler genellikle Assign kullanmalıdır. El yazısı erişimcileri sıkıcı ve hataya meyillidir, bu nedenle bu, birçok yazım ve aptalca hatadan tasarruf sağlar.

Ayrıca, sentezlenmiş bir özelliği bildirmek, aşağıdaki gibi nokta gösterimini kullanarak bir erişimci yöntemini çağırmanıza izin verir:

self.otherObj = someOtherNewObject; // set it  
MyOtherObject *thingee = self.otherObj; // get it 

Normal, mesaj iletme yolu yerine:

[self setOtherObject:someOtherNewObject]; // set it
MyOtherObject *thingee = [self otherObj]; // get it 

Perde arkasında gerçekten şöyle görünen bir yöntemi çağırıyorsunuz:

- (void) setOtherObj:(MyOtherObject *)anOtherObject {

    if (otherObject == anOtherObject) {
        return;  
    }

    MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second
    otherObject = [anOtherObject retain]; // put the new value in  
    [oldOtherObject release]; // let go of the old object
} // set it

…veya bu

- (MyOtherObject *) otherObject {  
    return otherObject;
} // get it

Tamamen popodaki ağrı, doğru. Şimdi bunu sınıftaki her ivar için yapın. Tam olarak doğru yapmazsanız, bir hafıza sızıntısı yaşarsınız. Derleyicinin işi yapmasına izin vermek en iyisidir.

1 Numaranın bir ivarı olmadığını görüyorum . Bunun bir yazım hatası olmadığını varsayarsak, sorun değil çünkü @property / @synthesize yönergeleri sizin için sahne arkasında da bir ivar bildirecektir. Bunun Mac OS X - Snow Leopard ve iOS4 için yeni olduğuna inanıyorum.

Numara 3'ün oluşturulmuş erişimcileri yok, bu yüzden onları kendiniz yazmanız gerekiyor. Eğer erişimci yöntemlerinizin yan etkilere sahip olmasını istiyorsanız, yukarıda gösterildiği gibi standart hafıza yönetimi dansınızı yapın, ardından ihtiyacınız olan yan işi, erişimci yönteminin içinde yapın. Eğer bir mülk sentezlemek ise sıra kendi yazarken , daha sonra da sürüm önceliğe sahiptir.

Her şeyi kapattım mı?


Evet çok teşekkür ederim! Yapmak istediğim bir not, # 1'deki ileri sınıf pragmasını çıkarırsanız ve onu bir #import "MyOtherObject" ile değiştirirseniz, bir derleme zamanı hatası alırsınız, ancak neden olduğundan emin değilsiniz ....
ennuikiller

1. yaklaşıma göre 2. yaklaşımı kullanmanın herhangi bir avantajı var mı?
Greg

@Greg Yöntemi # 1 döngüsel bir referansı engelleyecektir. Stackoverflow.com/questions/7221174/… sayfasına
willc2

3
Nokta gösterimi dışında güzel cevap. Özelliği nokta gösterimi için kullanmak üzere sentezlemenize gerek yoktur. Aslında, bir mülk beyan etmenize hiç gerek yoktur. Bildirilmiş bir ayarlayıcı ve alıcıya sahip olduğunuz sürece (örneğin setFoo:ve foo) noktalı gösterimi kullanabilirsiniz.
JeremyP

Alaka düzeyi açısından, ARC kullanılıyorsa, sentezleme otomatik olarak yapılır.
Sean Larkin

17

Eski günlerde ivars vardı ve başka bir sınıfın onları ayarlamasına veya okumasına izin vermek istiyorsan, bir alıcı (yani, -(NSString *)foo)bir ayarlayıcı (yani -(void)setFoo:(NSString *)aFoo;) tanımlaman gerekiyordu .

Özelliklerin size verdiği şey, bir ivar ile birlikte ücretsiz (neredeyse!) Ayarlayıcı ve alıcıdır. Dolayısıyla, şimdi bir özelliği tanımladığınızda, atomikliği (örneğin, birden çok iş parçacığından birden çok ayar eylemine izin vermek istiyor musunuz) ve ayrıca semantiği atayabilir / tutabilir / kopyalayabilirsiniz (yani, ayarlayıcı yeni değeri kopyalarsa) veya sadece geçerli değeri kaydedin - başka bir sınıf, daha sonra değiştirilebilecek değişken bir dizeyle dize özelliğinizi ayarlamaya çalışıyorsa önemlidir.

Bu ne @synthesizeyapar. Birçok kişi ivar adını aynı bırakır, ancak sentezleme @synthesize foo=_foo;ifadenizi yazarken değiştirebilirsiniz (yani, _fooözellik için bir ivar adı yapmak anlamına gelir foo, bu nedenle bu özelliği okumak veya yazmak istiyorsanız ve kullanmıyorsanız self.foo, yapacaksınız) kullanmak zorunda _foo = ...- sadece ayarlayıcı ve alıcıdan geçmek istiyorsanız, sadece ivar'a doğrudan referansları yakalamanıza yardımcı olur).

Xcode 4.6'dan itibaren, @synthesizeifadeyi kullanmanıza gerek yoktur - derleyici bunu otomatik olarak yapacak ve varsayılan olarak ivar isminin başına _.


1
Bir özelliğin atomikliğinin iplik güvenliğini garanti etmediğine dikkat edilmelidir .
jscs

Yani, atomik bir ivar'ım varsa, ayarlayıcı onu ayarlarken veya alıcı onu alırken, başka bir iş parçacığının devreye girip ikisini de yapmaya çalıştığını, yani her şeyin engellendiğini mi kastediyorsunuz? O zaman atomik olmanın anlamı nedir? Anladığım kadarıyla atomik, en azından bir ivar ayarlarsanız, ayarlandığından, tutma sayısının uygun olduğundan vs. emin olur. Aksi halde neden atomik? [Tüm sorunları çözdüğünden değil, sadece ayıplanmanızı engelliyor]
David H

2
Geçerli, bütün bir nesneyi elde etmeniz garanti edilir - alıcı, ayrılma işleminde olan bir nesneyi geri getirmez - ancak başka bir evre ayarlayıcıyı kullanıyorsa, değeri öncekinden veya sonradan alabilirsiniz. Alıcılar ve ayarlayıcıların dışında kullanılması gerektiğini belirtme. Diğer bir deyişle, alıcı veya ayarlayıcı işlemi sırasında hiçbir iş parçacığı kesintiye uğramayacaktır , ancak işlemlerin sırası tanımlanmamıştır (bu seviyede, AFAIK olamaz).
jscs

Evet, orijinal yorumunuzun yanlış yerleştirildiğini savunabilirim - atomiklik onurlandırılmıştır, sadece iş parçacıkları yoluyla erişim bir dizi soruna yol açabilir - bu nedenle, şimdiye kadar ilan ettiğim her ivar atomiktir ve işin içinde iş parçacığı varsa o zaman eşzamanlılık başka bir yerde ele alınır.
David H
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.