What's up with setViewControllers: method?


I’m thinking this question will have a super-quick answer, but I’ve hunted around the help documentation and web a bit and can’t seem to figure this out.

The app is working great with the code straight out of ch 7, but I wanted some extra info on the setViewControllers: method, and found the the selector is actually this: setViewControllers:animated:. So, I went about trying to use this method with the animated: parameter set to NO or YES, and the app crashes. I wouldn’t say I’ve scoured the documentation or the web, but I did try just searching for setViewControllers:, and nothing came up.

My assumption is that when the message is sent without the parameter, the receiver interprets it as nil, but then I don’t understand why animated:NO doesn’t work??



Doesn’t sound right - what’s the crash reason ?



Hmmm…well now it’s working, and I’m not sure what I changed =(

I just went to check the crash for you Gareth, and now I can compile it with either YES or NO as the animated: parmeter, and it works. That’s frustrating, but I’m glad it it’s working right now, because I was seriously confused.

Out of curiosity, do you know if leaving a parameter out of a method call is the same as supplying nil as the explicit parameter value? I’ve primarily programmed in JavaScript, which does operate in this manner. Out of all the material I’ve read learning Obj-C, I don’t remember this being addressed.



I hadn’t thought about this so I knocked up a quick test with a method definition of:

-(void) tryThis:(NSString *) parm1 withThis:(NSString *) parm2

Then trying to omit parameters:

[self tryThis: @“Hello” withThis:@“World”]; - all good

[self tryThis: withThis:@“World”]; - won’t compile

[self tryThis: @“Hello” withThis:]; - won’t compile

[self tryThis: @“Hello”]; - warning on compilation (may not respond) and SIGABRT (unrecognised selector) on running

and if I try with a method with variable arguments such as NSLog

NSLog(@“String1 = %@ String2 = %@”,parm1); - warning on compilation and EXC_BAD_ACCESS on running.

So I’m pretty sure the answer is no you can’t.

What you can do to supply default parameters though is have 2 methods such as

-(void) tryThis:(NSString *) parm1;
-(void) tryThis:(NSString *) parm1 withThis:(NSString *) parm2;

then in the implementation
-(void) tryThis:(NSString *) parm1;
[self tryThis:parm1 withThis:@“Default String”];



Well then, I’m back to being confused =)

After reading your test, I went back into my code, which is run in the application:didFinishLaunchingWithOptions delegate method in the HypnoTimeAppDelegate class, and removed the animated: paramater from the setViewControllers:animated: method, and everything works just fine??? I don’t know if I’m just missing something simple, but I just don’t see a setViewControllers: method (without the animated: parameter in the signature) anywhere in the documentation. I checked up the chain of inheritance…I checked the UINavigationController…and then just did a straight search for "setViewControllers. The only thing that comes up is the documentation for the setViewControllers:animated: method.

So, the deal is, I can send the setViewControllers message to the UITabBarController with or without the animated: parameter, and based on your test, that shouldn’t work. Really strange. Hopefully there’s an answer out there somewhere.

Oh, and thanks again for your time Gareth.


What does the console say when it crashes? It’s possible that one of the objects in the array is not a view controller; check both header files for the two view controller subclasses and make sure they inherit from UIViewController.

And no, a method like setViewControllers:animated: can’t be called by using setViewControllers: and omitting the last argument.

Where does setViewControllers: come from then? If you check out the documentation, there is a viewControllers property. This property isn’t readonly, thus, there is a setViewControllers: method. When searching the docs for a setter method (anything prefixed with set), it’s usually better to just search for the stuff after the word set; that way, you will find properties. (It’s kind of a bummer the documentation isn’t smart enough to figure that out; I remember when properties were first introduced, I was confused for a bit because I couldn’t find setter methods for anything).



It is a bit confusing but in this case there are two different methods.

setViewControllers: animated - which is documented in the UITabBarController Class description under the Instance Methods section and is the one that you’ve found in your searches


setViewControllers - which isn’t explicitly documented as a method hence you can’t find it.
However, viewControllers is documented as a “property” of the UITabBarController class and has a getter [tabBarController viewControllers] and a setter [tabBarController setViewControllers].

If you look under Properties for the UITabBarController Class description you will also see a delegate property and yet there is no explicit mention of the setDelegate method either.

Sometimes you’ll see a property marked as read only - in which case there will be no setter method available and sometimes you’ll see notes in the description highlighting what you should and shouldn’t do when using the property and occasionally you’ll see things like @property(getter=theGetterName) which replaces the [object myProperty] version with [object theGetterName]. If you look at CALayer you’ll see an opaque property with a getter of isOpaque.

All I bit confusing I know but if in doubt check the properties.


Edit: [Joe snuck in while I was writing this but I’ll leave it in anyway]