2011-09-02 200 views
8

我有一個類A與財產NSString *name。如果有一個NSArray並將許多A對象添加到此數組中,每次檢索對象時都需要進行強制轉換?即NSArray的對象和鑄造

NSString* n = (NSString*)[arr objectAtIndex:1]; 

還是有另一種方式來做到這一點有點像在Java中,你必須ArrayList<A> arr

回答

20

NSArray不存儲關於其中包含的對象類型的信息。如果你確切地知道類型的數組中的對象,你可以進行一次造型,無論是或明或暗地:

NSString *n = [arr objectAtIndex:1]; // implicit type conversion (coercion) from id to NSString* 
NSString *n = (NSString *)[arr objectAtIndex:1]; // explicit cast 

有一個在隱式和顯式轉換之間的運行成本沒有什麼區別,它只是一個風格問題。如果你的類型錯誤,那麼很可能會發生的是你會遇到令人生畏的unrecognized selector sent to instance 0x12345678異常。

如果您有不同類型的對象的異構陣列,您需要使用isKindOfClass:方法來測試對象的類:

id obj = [arr objectAtIndex:1]; 
if ([obj isKindOfClass:[NSString class] ]) 
{ 
    // It's an NSString, do something with it... 
    NSString *str = obj; 
    ... 
} 
+2

值得注意的是,在運行時無法區分NSStrings和NSMutableStrings,它們都對'isKindOfClass:[NSMutableString class]'回答YES。 – Chuck

+0

@Chuck:我不知道。怎麼來的? –

+0

@Chuck:我注意到NSString也向'[myNSString respondsToSelector:@「appendFormat:];'ISTM返回YES,可變和不可變字符串都是由__NSCFString實現的,並且有一些內部標誌,告訴它它是否可變或不可變。如果你調用'[myNSString appendFormat:@「world」];'你得到一個異常,但不是一個表明它不響應選擇器的異常。顯然'appendFormat:'檢查不可變標誌,如果它被設置,引發一個異常,可變和不可變的字符串實際上是同一個類,'__NSCFString'。 –

1

這是做到這一點的方法。無論如何,你可以實際執行上述操作,而無需強制返回,因爲你正在將它讀入NSString。

-2

這是這樣的:

NSMutableArray *objectsArray = [[NSMutableArray alloc] init]; 

A *a= [[A alloc] init]; 

[objectsArray addObject:a]; 

[a release]; 

您不必擔心proprety型

+0

該代碼泄露... – Daniel

+2

其實也沒什麼,增加了數組保留了該對象,所以在該片段之後,您有一個+2的保留數,所以您實際上需要刪除該項並釋放它以便它不泄漏,所有這些都是不好的練習,我應該說這個代碼可能會導致泄漏。 – Daniel

+0

丹尼爾是正確的指出,這是不好的風格。只有一個對'A'實例的引用,它是通過數組的,但是數組和'alloc'代碼都擁有所有權聲明。/cc @Chuck –

11

NSArrayobjectAtIndex:返回id類型的變量。這大致相當於在Java中返回一個Object-「我們不能保證太多關於這個變量的類型。」然而,在Objective-C中,您可以發送消息到id變量,而無需編譯器抱怨。所以,因爲知道該數組只包含A個實例,所以你最好把它發送給name消息。例如,下面將編譯沒有警告:

NSString *name = [[array objectAtIndex:0] name]; 

但是,如果你想使用點符號(如[array objectAtIndex:0].name),你需要的id強制轉換爲A *如下所示:

NSString *name = ((A *)[array objectAtIndex:0]).name; 
+0

perfect ..只是我正在尋找的信息 – Tim