To create from code a parent/child relationship between 2 view controllers basically it's just matter of doing something like:
[self addChildViewController:childViewController];
[self.view addSubview:childViewController.view];
where self is the parent view controller.
But, what if I want to create the same relationship completely from Interface Builder?
Or in other words: is there a way to re-create the behavior of the method addChildViewController using Interface Builder?
I didn't find a lot of documentation about that, here is an old unresolved post about the topic: https://devforums.apple.com/message/455758#455758
Without properly setting up the addChildViewController relationship, none of the rotation methods are forwarded to my child view controller, here where my question come from.
This is what I've done in IB:
drag and dropped a "View Controller" object from the "Object Library" panel into the "Objects" panel
in the identity inspector I've changed its class to my UIViewController subclass ("Items View Controller")
connected the view outlet to the controller
connected all the other required outlets to the controller (List name, Table View)
The first "View" object in the picture is the view of my parent view controller, instead the highlighted "View" is the view of the child view controller ("Item View Controller").
The container controller also retain its child instance through an additional IBOutlet:
#property (nonatomic, strong) IBOutlet ItemsViewController *itemsViewController;
Thanks
Update 1: If I manually set the parent/child relationship in viewDidLoad of the container controller, all the rotation methods are correctly forwarded to the child.
[self addChildViewController:self.itemsViewController];
But I don't really know if this is the correct way of doing that, since I would like to do all using IB.
Update 2: Thanks to #micantox for his hint to use the "Container View" in the Object Library, I have converted my xib file to a Storyboard and now the child view controller is added to its parent, so I don't have to add it manually from code with addChildViewController and the rotation methods are forwarded as expected.
"Container View" basically implements the embed segue and is supported only from iOS 6.
This is an updated screenshot from my Storyboard:
The right way of creating container views for child view controllers is through the use of the object "Container View" in the Object Library. Dragging one in your View Controller's scene will create a new scene for the child view controller that can be managed separately from the the parent view controller.
Also, if you're trying to create an embed segue to an existing view controller in your storyboard, control-drag from the container view, not the container VC, to the VC you want to embed.
A very simple way to do it is just instantiate the child view controller by referencing its storyboard ID:
UITableViewController *childViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"childViewController"];
[self addChildViewController:childViewController];
[self.view addSubview:childViewController.view];
That way, you can build both view controllers in interface builder. You can set the storyboard ID in interface builder: select the view controller and you'll see a field for it in the identity inspector.
Related
I'd like to be able to layout my view controller in code but see the layout displayed in interface builder.
I know I can create a UIView subclass, make that IBDesignable, and assign it to the view controller's view, but this would require that I make all other subviews properties of this UIView subclass instead of properties of the view controller.
The real desire is to be able to layout my view controllers in code but quickly see any changes without rebuilding the project. If this is possible with playgrounds instead, an answer describing how to do that would also be appreciated.
Thanks for any suggestions.
I found a workaround to test view controller layout using IBDesignable.
1.Layout your view controller in code just as you'd do normally
2.Create an IBDesignable UIView subclass and add the view controller's view as a subview.
3.Create a xib and set the class of its view to the subclass you created in step 2
To elaborate on step 2, your IBDesignable's initWithFrame: method may look like
{
self = [super initWithFrame:frame];
MyViewController *viewController = [MyViewController alloc] init];
viewController.view.frame = self.bounds;
[self addSubview:viewController.view];
return self;
}
So beyond this initWithFrame method, all of your layout code can be handled by your view controller. You may want to pass data to your view controller in your subview's prepareForInterfaceBuilder method.
In order to layout you own classes in Xcode you need first to import then in your swift playground: here more information.
After you do that, it's came the "tricky" part. In order to make your how class debuggable and visibile in playground, your class must conform to the protocol: CustomPlaygroundQuickLooacable:
Here there is a quick example from the WWDC:
By implementing this protocol, you're basically telling playground how to represent you hown class. I haven't fond any better solution yet.
I am newbie to iOS development.I have two view controllers in my app. I am trying to navigate from first view controller to second view controller in my app.
SecondView *ss=[[SecondView alloc] initWithNibName:#"Second Page" bundle:nil];
[self.navigationController pushViewController:ss animated:YES];
I found this code in "Stack overflow" but it won't work.
You are getting this error because you are likely trying to go from one VC to another using Navigator controller code (push) and you likely do not have a navigation controller setup in code or Interface Builder.
You can present/dismiss VCs without using Navigation Controller though and I recommend you start with this.
Notice the terminology: push/pop is used for VCs on the Navigation Controller stack, present/dismiss is for VCs on other VCs (not on a Navigation Controller stack).
There are a couple of way to present a VC on "top" of another VC and it depends on whether that VC exists on your SB as well:
1- If the VC does not exist in your IB and you are just creating and presenting the VC programmatically, you can do:
MyUIViewControllerSubclass *myLittleSubclass=[[MyUIViewControllerSubclass alloc]init];
myLittleSubclass.view.frame=self.view.frame; //this is for example only
[self presentViewController:myLittleSubclass animated:YES completion:nil];
With the above, you obviously would have to add the MyUIViewControllerSubclass Objective C class first to your project (using add files) and import it to whichever class you are putting the above code.
Later to dismiss it, you can use the following code from the MyUIViewControllerSubclass class itself.
[self.parentViewController dismissViewControllerAnimated:YES completion:nil];
2- If you have already added the MyUIViewControllerSubclass Objective C class to your project (using add files) but you intend to use the IB to design it and you have added the VC in the IB and changed its class in the IB to MyUIViewControllerSubclass, you can then use this code:
mySubclass *myLittleSubclass=[self.storyboard instantiateViewControllerWithIdentifier:#"theVC"];
[self presentViewController:myLittleSubclass animated:YES completion:nil];
You can dismiss same as above. Make sure that you click on the VC in SB and in the identity inspector, put the SB ID as "theVC" and check "Use SB ID".
Hope this helps.
Make sure that you have nib name with Second Page. Your class name is SecondView and nib(xib) name is Second Page then only it will navigate.
I have three UIViews in my storyboard, how can I navigate between them with push like animation without using Navigationbar or Tab Bar? I have my custom buttons on views.
Control-click and drag does not work with this error:
Terminating app due to uncaught exception 'NSGenericException', reason: 'Push segues can
only be used when the source controller is managed by an instance of UINavigationController.
You can present/dismiss VCs without using Navigation Controller.
Notice the terminology: push/pop is used for VCs on the Navigation Controller stack, present/dismiss is for VCs on other VCs (not on a Navigation Controller stack).
There are a couple of way to present a VC on top of another VC and it depends on whether that VC exists on your SB as well:
1- If the VC does not exist in your IB and you are just creating and presenting the VC programmatically, you can do:
MyUIViewControllerSubclass *myLittleSubclass=[[MyUIViewControllerSubclass alloc]init];
myLittleSubclass.view.frame=self.view.frame; //this is for exmaple only
[self presentViewController:myLittleSubclass animated:YES completion:nil];
With the above, you obviously would have to add the MyUIViewControllerSubclass Objective C class first to your project (using add files) and import it to whichever class you are putting the above code.
Later to dismiss it, you can use the following code from the MyUIViewControllerSubclass class itself.
[self.parentViewController dismissViewControllerAnimated:YES completion:nil];
2- If you have already added the MyUIViewControllerSubclass Objective C class to your project (using add files) but you intend to use the IB to design it and you have added the VC in the IB and changed its class in the IB to MyUIViewControllerSubclass, you can then use this code:
mySubclass *myLittleSubclass=[self.storyboard instantiateViewControllerWithIdentifier:#"theVC"];
[self presentViewController:myLittleSubclass animated:YES completion:nil];
You can dismiss same as above.
Make sure that you click on the VC in SB and in the identity inspector, put the SB ID as "theVC" and check "Use SB ID".
Hope this helps.
The push animation is only supported when using a UINavigationController inside the parent view. You can embed your view controller in one edit->embed in->navigation controller in IB, and hide the navbar. This may provide the functionality you desire.
I have a UItableview custom sized inside a Viewcontroller (for certain reasons, it cannot be inside a navigationcontroller). This is set to display a number of cells based on mysql importing into core data. How do I transition it from one view controller to another when a user clicks on an unknown row?
If you're not using a navigation controller, then I would just use presentViewController:animated:completion: inside the tableView:didSelectRowAtIndexPath method.
if you have set delegate to you UITableView then - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath will be called on your delegate when user taps on any cell. And then all you need is to find a model in your array or whatever which correspondes to that index path (the most common case is [array objectAtIndex:indexPath.row])And then you can push another view controller to the navigation stack or do a modal one
I've just created a storyboard with few table controllers and one view controller.
Everything works fine until my app push the view controller: it's shown completely black.
I can add map view, image view or whatever, or even nothing (a complete empty view controller), but it's always shown black.
I push it using the the navigation [self.navigationController pushViewController] code line.
This is not happening with table controllers, just with view controllers.
Any suggestion?
I'm using Xcode 4.3.2 4E2002.
Thanks in advance,
Samuel
Have you defined your storyboard correctly? This behavior could happen if you failed to properly initialize your storyboard and instantiate your controller from the storyboard. IE, you need to create a UIStoryboard object and need to instantiate your controller by calling
[storyboardObject instantiateViewControllerWithIdentifier: #"controllerName"]; ...See the thread here: http://mobile.tutsplus.com/tutorials/iphone/ios-5-sdk-storyboards