NSArray对象和Casting

bub*_*les 8 iphone objective-c ios

我有A一个属性的班级NSString *name.如果有一个NSArray并且A在这个数组中添加了许多对象,那么每次检索对象时都需要进行强制转换吗?即

NSString* n = (NSString*)[arr objectAtIndex:1];
Run Code Online (Sandbox Code Playgroud)

或者是否有另一种方法可以像你在java中那样做ArrayList<A> arr

Ada*_*eld 21

NSArray不存储有关其中包含的对象类型的信息.如果您确定数组中的对象类型,则可以隐式或显式执行强制转换:

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

隐式和显式转换之间的运行时成本没有区别,只是风格问题.如果你输入错误的类型,那么很可能会发生的是你会遇到可怕的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;
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,在运行时无法区分NSStrings和NSMutableStrings - 它们都对`isKindOfClass:[NSMutableString class]`回答YES. (2认同)

Chr*_*ble 11

NSArrayobjectAtIndex:返回类型的变量id.这大致相当于Object在Java中返回 - "我们无法保证这个变量的类型." 但是,在Objective-C中,您可以在id没有编译器抱怨的情况下向变量发送消息.因此,因为知道该数组只包含A实例,所以您最好向其发送name消息.例如,以下内容将在没有警告的情况下编译:

NSString *name = [[array objectAtIndex:0] name];
Run Code Online (Sandbox Code Playgroud)

但是,如果要使用点表示法(例如[array objectAtIndex:0].name),则需要将其id转换A *为如下所示:

NSString *name = ((A *)[array objectAtIndex:0]).name;
Run Code Online (Sandbox Code Playgroud)