For loops - Object type not taken into account?

I sometimes like to organize IB elements in NSArray , primarily to help me organize my elements. Most often, different classes of objects turn them into the same array with each other. Although this is a convenient way to organize, I can't seem to wrap my head around why, if I have such an array:

 NSArray *array = [NSArray arrayWithObjects:((UITextField *)textField), ((UISegmentedController *)segmentedController), nil]; 

Why do I get the "Doesn't respond to selector" messages when I put a for loop like this:

 for (UITextField *text in array) { [text setText:@""]; } 

The for loop seems to be passed to objects that are not in the UITextField class.

What is the point of declaring an object class if all the objects in the specified array go through a loop?

EDIT Just for reference, here's how I handle it now:

 for (id *object in array) { if ([object isMemberOfClass:[UITextField class]]) { foo(); } else if ([object isMemberOfClass:[UISegmentedController class]) { bar(); } } 
+7
source share
3 answers

When you do

 for (UITextField *text in... 

pointers of objects from the array are passed to the type UITextField *, so if the object is actually not UITextField, all sorts of strange things can happen if you try to call UITextField methods.

So, use id type instead (no * required, btw):

 for (id obj in array) 

Then check the type of how you do this and call the appropriate methods. Or, filter the array to get only objects of a particular type, and then go only with that type:

 for (UITextField* text in [array filteredArrayUsingPredicate:...]) 

Edit: here's how to create class filter predicates:

Is it possible to filter NSArray by class?

+10
source

What is the point of declaring an object class if all the objects in the specified array go through a loop?

The class name is there, so that the compiler knows what it should expect to find. This allows him to try to figure out what methods should be expected from you, and how you can treat the object. This is the same idea as passing an int method that accepts a float . The method will not ignore ints - it assumes that you are passing the correct type. You just give this design a little more credit than it should:

 for (UITextField *text in array) 

It just does not have this functionality. How you are dealing with it now is the right way.

+5
source

Are you sure you are not getting an error if you run this code? The message "does not respond to the selector" is a run-time error, not a compile-time error. The compiler does not know whether the objects in the -setText: array are -setText: , but you should definitely get an error message when sending this message to the UISegmentedControl instance.

Another possibility is that you have a class called UISegmentedController that has the -setText: method. The class name that implements the multi-part UI widget looks like UISegmentedControl . Thus, either the code you show is not real, verified code, or you have a class that we do not know about.

0
source

All Articles