2009-07-26 57 views
0
  1. 當用對象初始化一個NSMutableArray數組時,爲什麼在末尾放置nil?關於Objective-C,Cocoa和Xcode的一些問題

    例如

    NSMutableArray *fruits = [[NSMutableArray alloc] initWithObjects:apple, 
                       watemelon, 
                       nil]; 
    
  2. 在Xcode中,當使用auto complete來填寫函數變量時。跳到下一個變量的捷徑是什麼?

    如:

    Fruit *fruit3 = [[Song alloc] initWithName:(NSString *)n 
               description:(NSString *)d  
    

    我打字了initWithName功能,它自動完成。所以,我按下標籤馬上去n,完成後,我怎麼去d

  3. 如果我有水果陣列與水果對象作爲問題1水果對象作爲一個NSObject子類。爲什麼在我的Fruit類中有@property聲明名稱屬性的「副本」。

    當我知道,在默認情況下水果對象將駐留在自己的內存空間。由於我正在創建一個水果指針。 Fruit *apple = [[Fruit alloc]....

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

    什麼是@""嗎?用C

    [[NSString alloc] initWithValue:"ok"]; 
    

回答

8
  1. 的方法實現使用變量參數列表(...在C函數聲明)的參數的數量在這種情況下:

    是否做這樣的事情是未知的。因此,您必須用零(0)值關閉列表。

  2. 控制 -/
  3. 因爲NSArray的是一個指針數組。如果分配數組而不復制數組,則其他對象(引用數組)可以修改數組。通過複製,你可以確保數組的元素不會在你的課堂外被改變。
  4. 的@ 「XYZ」 contruct將返回一個自動釋放的NSString。所以它會像[[[NSString alloc] initWithUTF8String:「xyz」] autorelease]。
+0

thx..perfect回答 – user145374 2009-07-26 20:33:56

+3

注意的是,在雪豹的XCode,你可以完成參數之間進行切換。 – 2009-07-27 01:08:58

4
  1. C中的變量參數(因此在Objective-C中)是非常原始的。該方法只獲得一個指向堆棧的指針,並且必須有一個機制來確定參數的類型和數量。對於printf和類似的,它是格式代碼;對於-initWithObjects:它是一個標記,即一個已知值,表示列表的結束,在這種情況下爲零。
  2. 首選項 - >重點Bindings->文本主要Bindings->代碼預見選擇一個佔位符。
  3. 考慮以下幾點:
NSMutableString *str = [NSMutableString stringWithString:@"Fred"]; 
fruit.name = str; // Legal; NSMutableString is a subclass of NSString 
[str setString:@"Barney"];

如果fruit.name未聲明的副本屬性,最後一行會改變水果的名稱(因爲fruit.namestr指向同一個對象)。如果它被聲明爲複製,它們將是單獨的對象。 (但是,如果使用普通的NSString對象,則由於NSString是不可變的,所以不會進行復制,並且指向同一對象沒有問題。

3

下面是對問題1的更完整說明。C和Objective-C在C和Objective-C中,具有可變參數數量的函數(所謂的可變參數可變參數函數函數)是比較低級的語言,比如Java,C#,Python,Ruby等語言。是允許的,但語言沒有提供機制,瞭解在實際傳遞的參數數目更高級的語言通常通過暴露額外的參數列表或對象的數組提供此; C和Objective-C使用一組更有限的宏訪問額外的一次一個參數。

因此,任何可變參數函數都需要一些其他方法來確定傳遞的參數的實際數量。 printfscanf系列函數及其流派使用格式字符串作爲固定參數之一,格式字符串中的格式說明符指示傳入的額外參數的數量和類型。Objective-C類的-initWithObjects:消息NSMutableArray,而另一方面,需要額外的參數列表與nil被終止。因此,您無法傳入nil作爲參數(因爲它會標記參數列表的末尾),但在這種情況下沒關係,因爲NSMutableArray指定它們不能包含nil objets。

在x86體系結構上,可變參數函數是使用C調用約定(cdecl)實現的,參數從右到左被壓入堆棧。來電者負責在通話結束後清理堆棧。所以,printf()通話可能會被編譯成這樣的:

// 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 

原因的爭論推從右到左,而不是左到右是堆棧增長向下 - 中x86 push指令將堆棧指針esp減少4個字節。所以,當被調用函數檢查堆棧時,它會按照正確的順序查看參數。第一次調用上述printf後,堆棧看起來是這樣的:

 
%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 

當被叫功能檢查它的參數,它只是走棧,但它不知道在哪裏停止 - 調用約定沒有指定有多少個參數。該功能只需通過其他方式知道即可。大多數函數都有固定數量的參數,所以對他們來說很容易,但可變參數函數需要一些其他方法來確定參數的確切數量。

如果有之間的功能多少個參數,認爲這傳遞了多少實際上是通過(例如一個壞的格式字符串傳遞給printf)不匹配,則不良會導致。最可能的情況是該函數將繼續讀取堆棧,並且您會在某處獲得垃圾值。更糟的是,你的程序可能會崩潰。更糟糕的是,你的程序似乎可以正常工作,但你可能會無意中打開一個安全漏洞。