When initializing an NSMutableArray array with object, Why put nil at the end?
e.g.
NSMutableArray *fruits = [[NSMutableArray alloc] initWithObjects:apple, watemelon, nil];
In Xcode, when using auto complete for filling out function variables. What's the short cut key to jump to the next variable?
eg:
Fruit *fruit3 = [[Song alloc] initWithName:(NSString *)n description:(NSString *)d
I'm typing out the
initWithName
function and it auto completes. So, I press tab right away to get ton
, after finishing that, how do i get tod
?If I have a fruits array with fruit objects as in question 1. Fruit object being an
NSObject
subclass. Why have the "copy" in the@property
declaration for name property in my Fruit class.When I know that by default fruit object will reside in its own memory space. Since I am creating a fruit pointer.
Fruit *apple = [[Fruit alloc]....
NSString *a = @"Hello Everyone";
What does the
@""
do?Does it do something like this:
[[NSString alloc] initWithValue:"ok"];
views:
784answers:
3- The method is implemented using variable argument lists (,... in C function declaration) in C the number of parameters in this case is unknown. Therefor you have to close the list with a nil (0) value.
- Control-/
- Because a NSArray is an array of pointers. If you assign the array without copying it then other objects (that reference the array) can modify the array. With copy you are sure the elements of the array will not be changed outside your class.
- The @"xyz" contruct will return an autoreleased NSString. So it will be something like [[[NSString alloc] initWithUTF8String:"xyz"] autorelease].
- Variable arguments in C (and thus, in Objective-C) are very primitive. The method only gets a pointer to the stack, and has to have a mechanism to work out the types and number of parameters. For printf and similar, it’s format codes; for -initWithObjects:, it’s a sentinel, i.e. a known value indicating the end of the list, in this case nil.
- Preferences->Key Bindings->Text Key Bindings->Code Sense Select Next Placeholder.
- Consider the following:
NSMutableString *str = [NSMutableString stringWithString:@"Fred"];
fruit.name = str; // Legal; NSMutableString is a subclass of NSString
[str setString:@"Barney"];
If fruit.name
is not declared a copy property, the last line will change the name of the fruit (since fruit.name
and str
refer to the same object). If it is declared copy, they will be separate objects. (However, if you use a plain NSString
object, no copy will be made since NSString
s are immutable and there is no problem referring to the same object.
Here's a more complete explanation of question 1. C and Objective-C are rather much lower-level languages compared to languages such as Java, C#, Python, Ruby, and others. In C and Objective-C, functions with a variable number of arguments (so-called varargs or variadic functions) are allowed, but the language provides no mechanism for knowing the number of arguments actually passed in. Higher-level languages usually provide this by exposing the extra arguments as a list or array of objects; C and Objective-C use a more-limited set of macros to access the extra arguments one at a time.
Hence, as a result, any variadic function requires some other method of determining the actual number of parameters passed. The printf
and scanf
families of functions and their ilk use a format string as one of the fixed parameters, and the format specifiers found in the format string indicate the number and types of extra arguments passed in. The -initWithObjects:
message of the Objective-C class NSMutableArray
, on the other hand, requires the list of extra arguments to be terminated with nil
. As a consequence, you can't pass in nil
as an argument (since it would mark the end of the arguments list), but that's ok in this case since NSMutableArray
s specify that they cannot contain nil
objets.
On the x86 architecture, variadic functions are implemented using the C calling convention (cdecl), whereby the arguments are pushed on the stack from right-to-left. The caller is responsible for cleaning up the stack after the call. So, a call to printf()
might get compiled into something like this:
// 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
The reason the arguments are pushed right-to-left instead of left-to-right is that the stack grows downwards -- the x86 push
instruction decrements the stack pointer esp
by 4 bytes. So, when the called function examines the stack, it will see the arguments in the proper order. Immediately after the first call to printf
above, the stack looks like this:
%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
When the called function examines its arguments, it just walks the stack, but it doesn't know where to stop -- the calling convention doesn't specify how many arguments there are. The function just has to know by some other means. Most functions have a fixed number of parameters, so that's easy for them, but variadic functions need some other way of determining the exact number of parameters.
If there's a mismatch between how many parameters the function thinks it was passed and how many were actually passed (e.g. a bad format string was passed to printf
), then badness will result. The most likely case is that the function will keep reading down the stack, and you'll get garbage values somewhere. Worse, your program might crash. Even worse, your program might appear to work normally, but you may have inadvertantly opened up a security hole.