I thought that I knew how to use fast enumeration, but there is something I don't understand about it. If I create three NSString
objects and three NSNumber
objects and put them in an NSMutableArray
:
NSString *str1 = @"str1";
NSString *str2 = @"str2";
NSString *str3 = @"str3";
NSNumber *nb1 = [NSNumber numberWithInt:1];
NSNumber *nb2 = [NSNumber numberWithInt:2];
NSNumber *nb3 = [NSNumber numberWithInt:3];
NSArray *array = [[NSArray alloc] initWithObjects:str1, str2, str3, nb1, nb2, nb3, nil];
then I make do fast enumeration on all NSString
objects, like this:
for (NSString *str in array) {
NSLog(@"str : %@", str);
}
In the console, I get this result :
2011-08-02 13:53:12.873 FastEnumeration[14172:b603] str : str1
2011-08-02 13:53:12.874 FastEnumeration[14172:b603] str : str2
2011-08-02 13:53:12.875 FastEnumeration[14172:b603] str : str3
2011-08-02 13:53:12.875 FastEnumeration[14172:b603] str : 1
2011-08-02 13:53:12.876 FastEnumeration[14172:b603] str : 2
2011-08-02 13:53:12.876 FastEnumeration[14172:b603] str : 3
I logged only the NSString
s, but I get a line for every object in the array, even the NSNumber
s and I don't understand why. Does fast enumeration always use every object contained in an array?
When you write a forin loop like that, it casts every object in the array as an NSString, then prints them out as requested.
If you want only the NSStrings, you would need to write something like this:
for (id obj in array) {
if ([obj isKindOfClass:[NSString class]]) {
NSLog(@"str: %@", obj);
}
}
The for all
loop doesn't know the difference between NSStrings and Integers -- it will simply go through the entire array, cast each as an NSString, and print them out as you asked.
I'm pretty sure that fast enumeration returns all objects in the array- all that you're doing in for (NSString *str in array)
is typecasting str
to an NSString
. In the body of the loop you need to check the class of the returned object to make sure that it is an NSString
.
for(NSString *str in array)
{
if([str isKindOfClass:[NSString class]])
NSLog(@"str : %@", str);
}
Objective-C is dynamically typed, meaning that at runtime (when the loop actually runs), objects are all effectively one type (id
) with different classes. The language allows optional compile-time static typing, but all that does is check whether the messages you're sending are valid for the type you've marked. It doesn't actually change the behavior of your program. If you cast an object to be a different type than it actually is, all you're doing is lying to the compiler and defeating its type-checker.
Every object that descends from NSObject implements the method - (NSString)description, %@ in Objective-C formate string will take the corresponding argument for the %@ and call its description method, Most subclasses of NSObject will implement there own version of - (NSString)description. The same thing happens when you type
> po anObject
in the debugger.
for (NSString *str in array) {
is a way to enumerate through all the elements in array.
You expectative that by specifying NSString
you get only the objects of that type is not correct. Rather, all the objects pointers are cast to that type (NSString*
).
Have a look at Fast Enumeration in The Objective-C Programming Language guide.
I don't understand where is the unexpected behavior, using the enhanced for loop in an NSMutableArray
will just iterate thru every single object in the array which in your case is 6, the result is correct and expected.
The numbers will just get casted to Strings.
in fast enumeration no typecasting,just assigning the pointer into new object
来源:https://stackoverflow.com/questions/6918620/why-does-fast-enumeration-not-skip-the-nsnumbers-when-i-specify-nsstrings