Hangi durumlarda, ARC altında __autorelasing sahiplik niteleyicisini yazmamız gerekir?


118

Bulmacayı tamamlamaya çalışıyorum.

__strongNSObject, NSString, vb. gibi tüm Objective-C tutulabilir nesne işaretçileri için varsayılandır. Güçlü bir referanstır. ARC -release, kapsamın sonunda onu bir ile dengeler .

__unsafe_unretainedeski yönteme eşittir. Tutulabilir nesneyi korumadan zayıf bir işaretçi için kullanılır.

__weakBu, __unsafe_unretainedotomatik olarak sıfırlanan zayıf bir referans olması, yani başvurulan nesnenin serbest bırakılmasının hemen ardından işaretçinin sıfıra ayarlanacağı anlamına gelmesidir. Bu, sarkan işaretçiler ve EXC_BAD_ACCESS hataları tehlikesini ortadan kaldırır.

Ama tam olarak ne için __autoreleasingiyidir? Bu niteleyiciyi ne zaman kullanmam gerektiğine dair pratik örnekler bulmakta zorlanıyorum. Bunun yalnızca aşağıdaki gibi bir işaretçi-işaretçi bekleyen işlevler ve yöntemler için olduğuna inanıyorum:

- (BOOL)save:(NSError**);

veya

NSError *error = nil;
[database save:&error];

ARC uyarınca şu şekilde beyan edilmelidir:

- (BOOL)save:(NSError* __autoreleasing *);

Ancak bu çok belirsiz ve nedenini tam olarak anlamak istiyorum . Bulduğum kod parçacıkları, bana tuhaf görünen __autor salıvermeyi iki yıldız arasına yerleştiriyor. Tür NSError**(NSError'a bir işaretçi), öyleyse neden __autoreleasingyıldızların arasına yerleştirip sadece önüne değil NSError**?

Ayrıca, güvenmem gereken başka durumlar da olabilir __autoreleasing.


1
Aynı soruyu soruyorum ve aşağıdaki cevaplar tamamen ikna edici değil ... örneğin, neden sizin gibi __autoreleasing dekoratörüyle bildirilen NSError ** argümanlarını alan sistem tarafından sağlanan arayüzler ve Arc'a Geçiş Sürüm Notları, olmalı? örneğin, NSFileManager.h'deki bu rutinlerin çoğundan herhangi biri?
Babam

Yanıtlar:


67

Haklısın. Resmi belgelerin açıkladığı gibi:

Referans (id *) ile iletilen ve dönüşte otomatik olarak serbest bırakılan bağımsız değişkenleri belirtmek için __autoreleasing.

Tüm bunlar ARC geçiş kılavuzunda çok iyi açıklanmıştır .

NSError örneğinizde, bildirim __strongörtük olarak şu anlama gelir :

NSError * e = nil;

Şuna dönüştürülecek:

NSError * __strong error = nil;

saveYönteminizi aradığınızda :

- ( BOOL )save: ( NSError * __autoreleasing * );

Derleyicinin daha sonra geçici bir değişken oluşturması gerekecektir __autoreleasing. Yani:

NSError * error = nil;
[ database save: &error ];

Şuna dönüştürülecek:

NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;

Hata nesnesini __autoreleasingdoğrudan olarak bildirerek bundan kaçınabilirsiniz .


3
Hayır, __autoreleasingyalnızca başvuru ile iletilen argümanlar için kullanılır. Bu, bir nesnenin işaretçisine bir işaretçiniz olduğu için özel bir durumdur. Kolaylık kurucuları gibi şeylerde durum böyle değildir, çünkü bir nesneye yalnızca bir işaretçi döndürürler ve ARC bunu otomatik olarak ele alır.
Macmade

7
__Autoreleasing niteleyicisi neden sadece NSError'ın önüne değil de yıldızların arasına yerleştiriliyor **? Tip NSError ** olduğu için bu bana garip geliyor. Yoksa bunun nedeni, NSError * 'a işaret edilen işaretçinin otomatik olarak yayımlanan bir nesneyi işaret edecek şekilde nitelendirilmesi gerektiğini göstermeye çalışıyor mu?
Gurur Üye

1
@Proud Üye ilk yorumunuzla ilgili olarak - bu yanlış (eğer sizi doğru anlarsam) - aşağıdaki Glen Low'un cevabına bakın. Hata nesnesi, kaydetme işlevi içinde bir otomatik yayınlama değişkenine (sizin ilettiğiniz) atanır ve atanır . Bu atama, nesnenin o anda tutulmasına ve otomatik olarak serbest bırakılmasına neden olur. Kaydetme işlevinin bildirimi, ona otomatik yayınlama değişkeni dışında herhangi bir şey göndermemizi engeller çünkü ihtiyacı olan şey budur - bu yüzden denersek derleyici geçici bir değişken oluşturur.
Colin

2
Öyleyse neden Apple arayüzlerinden hiçbiri buna sahip görünmüyor? örneğin NSFileManager.h'deki her şey?
Babam

1
@Macmade: Şans eseri, cevabınızın düzenlendiğini fark ettim ( stackoverflow.com/users/12652/comptrol tarafından ) ve en azından ilk örneğinizdeki değişikliklerin ("örtük olarak ... ...) yanlıştır, çünkü __strong niteleyicisi ikinci satırdan ilk satıra taşındı. Belki bunu kontrol edebilirsiniz.
Martin R

34

Macmade'in cevabını ve Proud Member'ın yorumlarda takip eden sorusunu takip etmek (bunu bir yorum olarak da yayınlardı, ancak maksimum karakter sayısını aşıyor):

__Autoreleasing değişken niteleyicisinin iki yıldız arasına yerleştirilmesinin nedeni işte budur.

Önsöz olarak, niteleyiciye sahip bir nesne işaretçisini bildirmek için doğru sözdizimi şöyledir:

NSError * __qualifier someError;

Derleyici bunu affedecektir:

__qualifier NSError *someError;

ama bu doğru değil. Bkz Elma ARC geçiş rehberi ( "Doğru değişkenleri süslemeleri gerektiğini ..." diye başlayan bölümü okuyun).

Eldeki soruyu ele almak için: Bir çift işaretçi ARC bellek yönetimi niteleyicisine sahip olamaz çünkü bir bellek adresine işaret eden bir işaretçi, bir nesneye işaretçi değil, bir ilkel tip göstericidir. Ancak, bir çift işaretçi bildirdiğinizde, ARC ikinci işaretçi için bellek yönetimi kurallarının ne olduğunu bilmek ister. Bu nedenle çift işaretçi değişkenleri şu şekilde belirtilir:

SomeClass * __qualifier *someVariable;

Dolayısıyla, bir çift NSError işaretçisi olan bir yöntem bağımsız değişkeni durumunda, veri türü şu şekilde bildirilir:

- (BOOL)save:(NSError* __autoreleasing *)errorPointer;

İngilizce'de "__autor yayımlayan bir NSError nesnesi işaretçisine işaretçi" diyor.


15

Kesin ARC şartname söylüyor

__Otomatik serbest bırakma nesneleri için, yeni işaretçi tutulur, otomatik olarak serbest bırakılır ve ilkel anlambilim kullanılarak lvalue içinde saklanır.

Örneğin, kod

NSError* __autoreleasing error = someError;

aslında dönüştürülür

NSError* error = [[someError retain] autorelease];

... bu yüzden bir parametreniz olduğunda çalışır NSError* __autoreleasing * errorPointer, çağrılan yöntem daha sonra hatayı atar *errorPointerve yukarıdaki anlambilim devreye girer.

Sen kullanabilirsiniz __autoreleasingsallanmasını havuza bir ARC nesnesi zorlamak için farklı bir bağlamda, ama ARC sadece sallanmasını yöntemi dönüş havuz ve zaten kolları otomatik olarak kullanmak gibi görünüyor beri bu pek kullanışlı değil bu.

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.