使用object初始化NSMutableArray数组时,为什么将nil放在最后?
e.g。
NSMutableArray *fruits = [[NSMutableArray alloc] initWithObjects:apple,
watemelon,
nil];
在Xcode中,使用auto complete填写函数变量时。什么是跳转到下一个变量的捷径?
例如:
Fruit *fruit3 = [[Song alloc] initWithName:(NSString *)n
description:(NSString *)d
我正在输入initWithName
功能并自动完成。所以,我立即按Tab键前往n
,完成后,我如何到达d
?
如果我有一个带有水果对象的水果数组,如问题1,水果对象是NSObject
子类。为什么在我的Fruit类的@property
声明中声明了“复制”。
当我知道默认情况下,水果对象将驻留在自己的内存空间中。因为我正在创造一个水果指针。 Fruit *apple = [[Fruit alloc]....
NSString *a = @"Hello Everyone";
@""
做了什么?
它是否像这样:
[[NSString alloc] initWithValue:"ok"];
答案 0 :(得分:8)
答案 1 :(得分:4)
NSMutableString *str = [NSMutableString stringWithString:@"Fred"];
fruit.name = str; // Legal; NSMutableString is a subclass of NSString
[str setString:@"Barney"];
如果fruit.name
未声明为复制属性,则最后一行将更改水果的名称(因为fruit.name
和str
引用同一个对象)。如果它被声明为副本,则它们将是单独的对象。 (但是,如果使用普通的NSString
对象,则不会进行任何复制,因为NSString
是不可变的,并且引用同一个对象没有问题。
答案 2 :(得分:3)
以下是对问题1的更完整的解释。与Java,C#,Python,Ruby等语言相比,C和Objective-C是相当低级的语言。在C和Objective-C中,允许使用具有可变数量参数的函数(所谓的 varargs 或可变参数函数),但该语言不提供用于知道数字的机制实际传入的参数。高级语言通常通过将额外参数公开为对象的列表或数组来提供此功能。 C和Objective-C使用一组更有限的宏来一次访问一个额外的参数。
因此,因此,任何可变函数都需要一些其他方法来确定传递的实际参数数量。函数及其类似printf
和scanf
系列使用格式字符串作为固定参数之一,格式字符串中的格式说明符表示传入的额外参数的数量和类型。另一方面,Objective-C类-initWithObjects:
的{{1}}消息要求使用NSMutableArray
终止额外参数列表。因此,您不能将nil
作为参数传递(因为它会标记参数列表的结尾),但在这种情况下可以正常,因为nil
指定它们不能包含{ {1}} objets。
在x86架构上,使用C调用约定(cdecl)实现可变参数函数,从而将参数从右到左推入堆栈。呼叫者负责清理堆栈。因此,对NSMutableArray
的调用可能会编译成这样的内容:
nil
从右到左而不是从左到右推送参数的原因是堆栈向下向下 - x86 printf()
指令递减堆栈指针{{ 1}} 4个字节。因此,当被调用函数检查堆栈时,它将以正确的顺序看到参数。在第一次调用// ignore the fact that these are invalid calls to printf
printf("format string 1", a1, a2);
printf("format string 2", b1, b2, b3);
// The above might get compiled into this:
push a2
push a2
push <address of "format string 1">
call printf
add $12. %esp // restore stack pointer to offset the pushes
push b3
push b2
push b1
push <address of "format string 2">
call printf
add $16, %esp // restore stack pointer
之后,堆栈就像这样:
%esp+0x00: return address to calling function %esp+0x04: address of "format string 1"> %esp+0x08: a1 %esp+0x0c: a2 %esp+0x10 and above: local variables from calling function, rest of stack
当被调用的函数检查它的参数时,它只是遍历堆栈,但它不知道在哪里停止 - 调用约定没有指定有多少参数。该功能只需要通过其他方式知道。大多数函数都有固定数量的参数,因此对它们来说很容易,但是可变函数需要一些其他方法来确定参数的确切数量。
如果函数认为传递的参数数量与实际传递的数量之间存在不匹配(例如,将错误的格式字符串传递给push
),则会导致错误。最可能的情况是该函数将继续读取堆栈,并且您将在某处获得垃圾值。更糟糕的是,您的程序可能会崩溃。更糟糕的是,您的程序似乎可以正常工作,但您可能无意中打开了一个安全漏洞。