2011-09-02 90 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