我一直看到我们使用中间对象,例如,创建一个数组来填充另一个数组:
characters = [[NSArray alloc] initWithObjects:@"Antony", @"Artemidorus", @"Brutus", nil];
play.characters = characters;
[characters release];
characters
在对象NSArray
中为play
。
我在@property
及其self
看到同样的事情:我们没有将新项直接添加到此属性中,就像我们没有直接填写characters
一样上面的例子。这只是关于“风格”吗?
答案 0 :(得分:2)
这不是风格问题。
play.characters
是一个属性,可以“包含”现有数组或nil
,但即使它“包含”现有数组,也无法更改{{1}的内容1}},所以你必须创建一个新的并将其分配给属性。
如果声明了所有属性,则分配给属性将导致其setter方法运行(可以由编译器创建,如果您使用NSArray
,或者由您在代码中编写),那将会注意删除任何现有阵列,分配新阵列并保留它。
答案 1 :(得分:1)
在这段小代码中实际上只有一个数组在运行。
数组不是中间数组,而是包含指针的变量 - 在本例中是变量字符。
这就是:
表达式
[[NSArray alloc] initWithObjects:@"Antony", @"Artemidorus", @"Brutus", nil]
分配一个对象并使用三个NSStrings(它们本身就是对象)进行初始化,但让我们暂时搁置一下。初始化还包括保留计数的增量,因此从一开始就是一个。
这个新创建的对象位于内存中的给定位置,比如0100H。然后将该位置存储在变量characters
中。在C语言中,我们说characters
是指向对象的指针。
然后,对象@"characters"
的属性play
被设置为指向内存中与局部变量characters
相同的位置。因此,现在有两个变量(其中一个也是属性)指向同一个对象,或者,如果您愿意,则指向内存中的相同位置。如果属性的类型为retain,则会自动增加对象的保留计数,因此现在为2。
使用最后一行中的release消息,对象将其保留计数减1,因此在此代码段的末尾,play.characters
属性指向该对象,并且它具有保留计数一个。
要非常干净,这段代码应该将局部变量设置为nil
,以避免在持有指向对象的指针和保留计数的变量之间产生混淆。
所有这些都是为了表明这里确实只有一个数组在运行,但有两个变量指向它。因此,乍看之下,没有多少计算机资源被浪费。
如果你想在一行中完成所有这些,你可以这样写:
play.characters = [[[NSArray alloc] initWithObjects:@"Antony", @"Artemidorus", @"Brutus", nil] autorelease];
但其确切的工作原理不太清楚,因为它涉及其中一个神秘的自动释放,即一个自动处理并推迟到某个后期的版本。
这是一个很长的描述,但我希望它能说明正在发生的事情。