我有一个问题,它在此处(以及SO上的其他问题),还有关于Objective-C集合和快速枚举的苹果文档。不清楚的是,如果使用不同类型填充了NSArray
,并创建了循环,例如:
for ( NSString *string in myArray )
NSLog( @"%@\n", string );
这里到底发生了什么?循环会跳过任何不是NSString
的东西吗?举个例子,假设一个UIView
在数组中,当循环遇到该项时会发生什么?
我有一个问题,它在此处(以及SO上的其他问题),还有关于Objective-C集合和快速枚举的苹果文档。不清楚的是,如果使用不同类型填充了NSArray
,并创建了循环,例如:
for ( NSString *string in myArray )
NSLog( @"%@\n", string );
这里到底发生了什么?循环会跳过任何不是NSString
的东西吗?举个例子,假设一个UIView
在数组中,当循环遇到该项时会发生什么?
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
方法,该协议所引用的类可能符合规范也可能不符合规范。如果符合规范,它将打印出来。否则,它将崩溃。
NSObject
本身符合 NSObject
协议,因此任何继承自 NSObject
类的对象(即除了极少数之外的所有对象)也符合该协议。 - jscsNSLog()
这样看似无害的调用也不会在未定义类型或错误类型的对象上始终正常工作。 - johnNSString*
,这只是编译检查。在运行时,一切都只是一个id
。
for (NSUInteger i = 0; i < myArray.count; i++) {
NSString* string = [myArray objectAtIndex:i];
[...]
}
它之所以更快,是因为它在更低的层次上运行。
我刚刚尝试了一个快速的例子...这是我的代码。
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1];
NSNumber *number = [NSNumber numberWithInteger:6];
[array addObject:number];
[array addObject:@"Second"];
for (NSString *string in array)
{
NSLog(@"%@", string);
}
NSString
上记录-length
...for (NSString *string in array)
{
NSLog(@"%i", string.length);
}
...当NSNumber
无法响应-length
选择器时,它会抛出一个NSInvalidArgumentException
异常。简而言之,Objective-C给了你很多自由,但不要用它来绊倒自己。
description
方法,就像你所说的那样。但是这里没有涉及到类型转换。 - user1040049NSNumber
实例上发送 -length
消息的警告。 - Mark Adamsstring
。我以为你是说NSLog正在执行转换(从提到description
来看)。我的错! - user1040049有趣的问题。快速枚举最通用的语法是
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 );
}
我在苹果的快速枚举文档中��有找到准确的提及,但你可以通过一个例子来检查它并看看会发生什么。
for(id obj in arr)
吗?(因为它涵盖了(数量很少的)不从NSObject
派生的对象)? - jscs由于所有的NSObject都会响应isKindOfClass方法,因此您仍然可以将类型转换降到最低:
for(NSString *string in myArray) {
if (![string isKindOfClass:[NSString class]])
continue;
// proceed, knowing you have a valid NSString *
// ...
}