views:

784

answers:

3
  1. When initializing an NSMutableArray array with object, Why put nil at the end?

    e.g.

    NSMutableArray *fruits = [[NSMutableArray alloc] initWithObjects:apple,
                                                                     watemelon,
                                                                     nil];
    
  2. 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 to n, after finishing that, how do i get to d?

  3. 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]....

  4. NSString *a = @"Hello Everyone";

    What does the @"" do?

    Does it do something like this:

    [[NSString alloc] initWithValue:"ok"];
    
+8  A: 
  1. 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.
  2. Control-/
  3. 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.
  4. The @"xyz" contruct will return an autoreleased NSString. So it will be something like [[[NSString alloc] initWithUTF8String:"xyz"] autorelease].
Diederik Hoogenboom
thx..perfect answers
Note that in the Snow Leopard XCode, you can just tab between completed parameters.
Kendall Helmstetter Gelner
+3  A: 
  1. 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.
  2. Preferences->Key Bindings->Text Key Bindings->Code Sense Select Next Placeholder.
  3. 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 NSStrings are immutable and there is no problem referring to the same object.

Ahruman
your analogy for number 3 made it crystal clearthx very much
+2  A: 

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 NSMutableArrays 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.

Adam Rosenfield