I am using storyboard instantiateViewControllerWithIdentifier:
and I\'m noticing that all the IBOutlets
I have wired up are still nil. However, the
If the object you're linking to is a top-level entity in the scene, like an ArrayController, the reference needs to be strong (not weak!) since it's not retained by the view hierarchy. A weak reference can cause a problem like what you describe.
Look here for more information: Should IBOutlets be strong or weak under ARC?
People gave solution of how to get the view loaded (some of which you should never use (loadView()
) so here is a way to check whether your view is already loaded
I ran into the problem because I had a property with a didSet
observer to update the UI which obviously doesn't work if the outlets are not yet set, so here is some example code how to work around it:
var name: String? {
didSet {
updateNameLabel()
}
}
override func viewDidLoad() {
super.viewDidLoad()
updateNameLabel()
}
func updateRoomLabel() {
guard isViewLoaded() else {
return
}
[...]
}
So now when you display the outlets get updated but also every time you update the property
[Use me as bad example]
Maybe not a good idea after all, it works but it violates the regular loading making the app unstable ^_^.
I'll leave the answer here in case someone else want to know if you do it.
I was having the same issue, however the custom component I designed isn't loaded via presentViewController (load in overlay to the previous view)
You can simply call
myViewController.loadView()
//Swift
[myViewController loadView]
//Obj-C
Setting the frame for the instantiated ViewController seems to set the IBOutlets.
ex:
DemoViewController *demoVC = [[self storyboard] instantiateViewControllerWithIdentifier:@"demoVC"];
demoVC.frame = self.view.frame; //or CGRectMake(0, 0, 1015, 604);
This would initialize the IBOutlets of DemoViewController like Label, TextField, Button, Table etc,.
Hope this helps.
The view seems to be initialized properly only after it is accessed first. The problem goes away when calling
[self presentViewController:vc animated:NO completion:nil];
or more simply
[vc view];
Outlets are established with Key Value Coding, you could put this into your view controller subclass:
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath {
[super setValue:value forKeyPath:keyPath];
}
- (void)setValue:(id)value forKey:(NSString *)key {
[super setValue:value forKeyPath:key];
}
And put a breakpoint on the two calls to super.
In the debugger, I'd try:
Comparing 'self' to the view controller you think you're applying the outlets to. Perhaps your storyboard has a second view controller you're not expecting. When you said you 'set up an owner' I thought that was strange terminology. Did you drag out one of the cube objects to represent your view controller in addition to the representation that's already there?
Compare [self valueForKey:key] or [self valueForKeyPath:keyPath] or just [self outletName] with the passed in value after the call through to super. Maybe you have setter that isn't doing what you intend. I've seen one mistake like this come up a couple of times where people have an outlet for an object with a name like "firstName" and then an action with the selector "setFirstName:". That confuses key value coding, and you end up with setFirstName: getting called during nib loading with intent of establishing the outlet, but the setter for the outlet is implemented as an action method, so the outlet is never set.