Apa sebenarnya yang terjadi ketika saya menyetel properti objek menggunakan metode pengakses?

Katakanlah saya memiliki objek bernama MyClass, yang memiliki properti yang didefinisikan sebagai @property (nonatomic, retain) NSString *foo; dan saya mensintesis properti itu.

Kemudian di kelas lain, katakanlah delegasi aplikasi Saya mendefinisikan sebuah string (tetapi bisa berupa apa saja) NSString *myString = [[NSString alloc] initWithString:@"Hi"]; dan memanggil instance MyClass: [myClass setFoo:myString];

Apa yang sebenarnya terjadi? Apakah referensi ke ruang yang dialokasikan untuk myString sudah disetel? Atau apakah ia mendapatkan apa yang ada di memori yang dialokasikan untuk myString dan menyetelnya ke memori yang dialokasikan untuk foo, karena saya memanggil retain pada foo?

Dan saya harus melepaskan myString di delegasi aplikasi. Dan saya harus melepaskan foo di Kelas Saya, karena tetap dipertahankan, tetapi apakah saya harus melepaskannya lagi karena variabel lain yang dialokasikan telah ditetapkan padanya?


person Josh Sherick    schedule 13.08.2011    source sumber


Jawaban (3)


Itu semua tergantung bagaimana properti itu dideklarasikan. Karena milik Anda adalah (retain), ia akan menyimpan penunjuk objek yang sama, dan juga secara otomatis mengirimkan -retain sehingga dapat memastikan akses ke memori terlepas dari apakah pemanggil memiliki referensi atau tidak. Jika Anda menggunakan (copy), ia akan mengirimkan -copy yang akan membuat objek baru yang merupakan salinan dari objek lama (asalkan objek tersebut sesuai dengan `NSCopying).

Ini semua terjadi dalam implementasi aksesori, yang biasanya dibuat untuk Anda saat Anda menggunakan @synthesize. Jika Anda menerapkannya sendiri, pastikan untuk menggunakan perilaku yang benar!

person jtbandes    schedule 13.08.2011
comment
jadi apakah itu berarti jika saya mengubah myString atau foo, itu akan mengubah yang lain karena sebenarnya hanya referensi ke variabel yang sama. - person Josh Sherick; 13.08.2011
comment
Agak — ingatlah bahwa Anda tidak dapat mengubah NSString, hanya NSMutableString. Dan properti NSString biasanya (copy). - person jtbandes; 13.08.2011
comment
Ya. ini bukan contoh nyata saya hanya membahas objek secara umum, bukan string. jadi katakanlah itu adalah nsmutablestring dan saya mengubahnya, apakah itu akan mengubah yang lain? - person Josh Sherick; 13.08.2011
comment
Ya, jika bukan (copy). Cobalah! - person jtbandes; 13.08.2011

@synthesize pada dasarnya menciptakan dua metode untuk Anda. Dalam kasus Anda, kedua metode tersebut akan serupa dengan ini:

-(NSString*) foo;
{
    return foo; //synthesized ivar
}

-(void) setFoo:(NSString*)newValue;
{
    if(foo != newValue){
        [foo release];
        foo = [newValue retain];
    }
}

Namun, @synthesize tidak akan melepaskan nilai di dealloc, jadi Anda harus melakukannya secara manual.

Objek di Objective-C diperlakukan sebagai pointer, jadi ketika Anda mengatakan NSString* a = b; Anda tidak menyalin objek itu sendiri, Anda hanya membuat pointer lain ke objek tersebut. Properti yang disintesis tidak terkecuali dalam hal ini.

person Tom Dalling    schedule 13.08.2011
comment
Saya yakin ini hanya berlaku untuk properti (nonatomic) :) - person jtbandes; 13.08.2011
comment
Ya. Akan sedikit berbeda jika properti yang dimaksud adalah atomik. - person Tom Dalling; 13.08.2011
comment
Saya yakin Tom menyertakan peringatan di awal jawabannya. Penerapan metode sintesis sudah tepat untuk kata kunci yang digunakan OP. - person Perception; 13.08.2011
comment
Sebenarnya @synthesize foo; membuat kode seperti: return [[foo retain] autorelease];. Jika propertinya atomik, ia juga akan mengunci kode di setFoo:. - person Rudy Velthuis; 13.08.2011
comment
FWIW, properti string biasanya dideklarasikan sebagai (copy), dan kemudian salinannya sedang dibuat. - person Rudy Velthuis; 13.08.2011
comment
@Rudy Velthuis, sebenarnya ini tidak melepaskan ivar secara otomatis dari metode pengakses yang disintesis. - person Tom Dalling; 14.08.2011
comment
Dari pengambil? Apa kamu yakin? - person Rudy Velthuis; 14.08.2011
comment
Saya ingat pernah membaca sesuatu tentang itu beberapa waktu lalu, jadi saya mengujinya 5 menit yang lalu dan rilis otomatis tidak dipanggil. - person Tom Dalling; 14.08.2011

Apa yang terjadi adalah objek yang myString tunjuk mendapat jumlah retensi bertambah satu saat Anda melakukan [myClass setFoo:myString];

Awalnya, saat Anda mengalokasikan string dan menyimpan referensi di myString, jumlah penyimpanannya adalah 1. Menyimpannya di properti dengan penyimpanan seperti yang Anda miliki, jumlah penyimpanannya bertambah menjadi 2.

Tidak, Anda tidak perlu melepaskannya lagi. Jumlah retensi maksimum adalah 2. Oleh karena itu 2 rilis.

person Manish Burman    schedule 13.08.2011