我在这里有这个问题(以及关于 SO 的其他问题),以及关于 Objective-C 集合和快速枚举的 Apple 文档。尚不清楚的是是否NSArray
填充了不同的类型,并且创建了一个循环,如下所示:
for ( NSString *string in myArray )
NSLog( @"%@\n", string );
这里到底发生了什么?循环是否会跳过任何不是NSString
? 例如,如果(为了参数)aUIView
在数组中,当循环遇到该项目时会发生什么?
我在这里有这个问题(以及关于 SO 的其他问题),以及关于 Objective-C 集合和快速枚举的 Apple 文档。尚不清楚的是是否NSArray
填充了不同的类型,并且创建了一个循环,如下所示:
for ( NSString *string in myArray )
NSLog( @"%@\n", string );
这里到底发生了什么?循环是否会跳过任何不是NSString
? 例如,如果(为了参数)aUIView
在数组中,当循环遇到该项目时会发生什么?
你为什么想这么做?我认为这会导致错误和意外行为。如果您的数组填充了不同的元素,请改用:
for (id object in myArray) {
// Check what kind of class it is
if ([object isKindOfClass:[UIView class]]) {
// Do something
}
else {
// Handle accordingly
}
}
您在示例中所做的实际上与,
for (id object in myArray) {
NSString *string = (NSString *)object;
NSLog(@"%@\n", string);
}
仅仅因为你转换object
为(NSString *)
并不意味着string
实际上会指向一个NSString
对象。NSLog()
以这种方式调用将根据 NSObject 协议调用方法- (NSString *)description
,数组中引用的类可能符合也可能不符合。如果符合,它将打印出来。否则,它会崩溃。
You have to understand that a pointer in obj-c has no type information. Even if you write NSString*
, it's only a compilation check. During runtime, everything is just an id
.
Obj-c runtime never checks whether objects are of the given class. You can put NSNumbers into NSString pointers without problems. An error appears only when you try to call a method (send a message) which is not defined on the object.
How does fast enumeration work? It's exactly the same as:
for (NSUInteger i = 0; i < myArray.count; i++) {
NSString* string = [myArray objectAtIndex:i];
[...]
}
It's just faster because it operates on lower level.
有趣的问题。快速枚举最通用的语法是
for ( NSObject *obj in myArray )
NSLog( @"%@\n", obj );
我相信通过做
for ( NSString *string in myArray )
NSLog( @"%@\n", string );
相反,您只是将每个对象转换为NSString
. 也就是说,我相信以上等价于
for ( NSObject *obj in myArray ) {
NSString *string = obj;
NSLog( @"%@\n", string );
}
我在 Apple 的Fast Enumeration 文档中找不到对此的准确提及,但您可以通过示例查看它,看看会发生什么。
我只是尝试了一个简单的例子......这是我的代码。
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1];
NSNumber *number = [NSNumber numberWithInteger:6];
[array addObject:number];
[array addObject:@"Second"];
现在,如果我只是简单地记录对象,没问题。该NSNumber
实例被转换为NSString
,但两种方法都响应-description
,所以它不是问题。
for (NSString *string in array)
{
NSLog(@"%@", string);
}
但是,如果我尝试登录-length
...NSString
for (NSString *string in array)
{
NSLog(@"%i", string.length);
}
...它抛出一个NSInvalidArgumentException
因为NSNumber
不响应-length
选择器。长话短说,Objective-C 给了你很多东西。不要用它来吊死自己。
由于所有 NSObject 都响应 isKindOfClass,您仍然可以将转换保持在最低限度:
for(NSString *string in myArray) {
if (![string isKindOfClass:[NSString class]])
continue;
// proceed, knowing you have a valid NSString *
// ...
}