I have a "container" viewController, that hold a few container views using storyboard.
each of that container view has a link to an embedded viewcontroller's view.
Since im working on a big project, it turns out that the storyboard file is massive and contains a lot of "child" viecontrollers view layout. it will be a problem working on that file when a few people needs to be working simultaneously on it. and thats not good for me.
i would like to know if theres a way to load into each container view a viewcontroller's xib file, and still be using storyboard.
Meaning, creating .xib files for each viewcontroller instead of holding them in the storyboard itself, and link them to the container views in the storyboard.
thanks,
You can move your view controller layout into a separate xib. As you say, this is a very convenient way to share layouts across storyboards.
When setting up a container view in your storyboard, make sure you delete the provided view in the embedded ViewController. Set the custom class for the ViewController to your class name. Name the xib to match the class (e.g. FooViewController.xib so it can be found when FooViewController.m is loaded.)
If you don't delete the View in the storyboard view controller layout, you'll see that empty view instead. Your viewDidLoad method in your view controller won't be called, because the View is the default Storyboard View.
I'm using Xcode 6.1 for iOS 8 on a pre-iOS 7 project.
Yes, you can. A few observations:
All you need to do is to put in the sort of code that we used to use when using NIBs. In the case of containers, that means the typical container methods. If you've not done containment via code, see Creating Custom Container View Controllers in the View Controller Programming Guide. Bottom line, as you transition to a non-storyboard scene (or add a non-storyboard child view controller), just code it like you always used to in the NIB-based environment. You cannot represent this NIB-based scene in the storyboard. But you just get the controller like you always do with NIBs:
SecondViewController *controller = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
You obviously lose many of the benefits of using storyboards (e.g. sizing the child scene on the basis of the container view in the parent scene), but you're no worse off than you were in a NIB environment. But in answer to your question as to whether you can "link them to the container views in the storyboard", you cannot represent this relationship in the storyboard itself, but rather you link them up programmatically.
If your separate teams are working in single-scene environments, you can use this NIB approach. You should also contemplate, though, just having multiple storyboards, one for each logical team. You'll still have to resort to code as you transition between storyboards, just like you do in this NIB approach, but if one of your teams has multiple scenes to deal with, they can enjoy storyboard benefits within their portion of the project. When you want to get to the first scene in the next storyboard, you can:
UIStoryboard *secondaryStoryboard = [UIStoryboard storyboardWithName:#"SecondStoryboard" bundle:nil];
SecondViewController *controller = [secondaryStoryboard instantiateInitialViewController];
If your child needs to transition to a new scene on your storyboard, I find it useful to add my own parentStoryboard property to my child controller, which it can then useful if you need to do something like instantiateViewControllerWithIdentifier. Obviously, if you're not transitioning to new controllers, you may not need to do that, but if you are, having a UIStoryboard property can be useful.
Related
I have created Storyboard with several views calling each other, now I need to create the code
I notice that XCode didn't created .h and .m controller files for each View from storyboard.
Should I create them manually?
Should I keep only one controller? (or few depending of separation of concerns on MVC)
Is there a pattern for developing this?
thanks
The usual approach is one view controller pr. screen full of content. You can imagine having one view controller for a tableview, with any sort of content, and then another view controller that presents that content in a new screen full of content if a row is pressed.
Normally when you have subviews inside of your view controllers, you wire them up in interfacebuilder. Then for instance if you want to populate a view that has a uiimageview and a uiactivityindicatorview inside it, you can control their behavior and how their populated from the view controllers code. You could also if you want something very generic and you feel that one view will probably take up a lot of code in your view controller, create a uiview subclass for it, and then set the class in interface builder.
Did this help? Please let me know if you need more clarification.
It's entirely up to you whether you have a ViewController for each view. If you have many views I would recommend it. Even if you have 2 or 3 views you probably still should. Things can get really confusing when each view has a different task but all have similar IBOutlets.
TLDR; Personally, I would say it was good practice to have a ViewController for each view if each view has a separate task.
I want to use generally the old .xib files in my iPhone application. But when it comes to tableViewController storyboard is a lot more convenient in order to make custom cells etc. Is it possible to make a .xib based application and in the middle of it, to use a storyboard for a UITableViewController and its DetailedViewController only?
You can use a storyboard for any part of a program. Storyboards are not an all or nothing concept. You can have just one view controller in a storyboard, or a small network that just represents a subsection of your app.
To use just one view controller from a storyboard:
Add a new storyboard to your existing project.
Add a single view controller to the storyboard.
Assign an identifier to the view controller in the inspector.
Use the UIStoryboard class to load the storyboard resource
Use -[UIStoryboard instantiateViewControllerWithIdentifier:] to create a new instance of that view controller.
Install the view controller some place in your app by doing something like pushing it on to a navigation controller, or run it modally.
Both can work fine together (Storyboards and Nib files). In the TVC that is part of your storyboard, just instantiate the destination VC in code and use the usual initWithNibName method to load the nib file.
You can add a storyboard to any project, but the point of storyboards is to centralize your XIB files into one location rather than having 10 XIB files you can have 1 .storyboard file that contains 10 scenes representing your views. This shows your connections to other scenes, and you can manage all the seques and transitions of each scene. So is it possible, yes you could add a storyboard to your project, but I would recommend you design you entire application in a storyboard if you want to use them.
In iOS5 using storyboard feature I want to create a custom container which will have 2 ViewControllers embedded in it. For Example, embed Table view controller as well as a view controller both in one ViewController.
That is, one view controller will have 2 relationship:
to table view controller
to view controller which in turn will have 4 UIImage view Or UIButton in it
Is creating this type of relationship possible using storyboard's drag drop feature only & not programmatically?
,You should only have one view controller to control the scene. However, this viewController might have two other view controllers that control particular subviews on your scene. To do this you create properties in your scene viewController, in your case one for your tableViewController and one for your view. I like to keep things together so I make both these viewControllers outlets and create them in interface builder. To create them in interface builder pull in an Object from the Object library and set its type to the relevant viewController. Hook it up to the appropriate outlet you just created in your scene's viewController - Note: this is important otherwise the viewController will be released if you are using ARC and crash your app. Then hook these viewControllers up to the view you want them to control and you are done.
Alternatively you can instantiate and hop up your viewControllers in your scenes viewController should you prefer to do this.
Hope this helps.
Edit: On reflection this is not a good idea and actually goes against the HIG you should maintain only one ViewController for each screen of content and instead try to create a suitable view class and have the single view controller deal with the interactions between the various views.
There is a way to do it that isn't too hacky. It is described at the following URL for UITabBarControllers, which you could use the first view controller in the list control the first subview, and the second one control the other. Or, you can probably adapt the code to work with UISplitViewController.
http://bartlettpublishing.com/site/bartpub/blog/3/entry/351
Basically, it works by replacing the tabbarcontroller at runtime after iOS has finished configuring it.
In a navigation based application, when I want to create and use other uiviews and uitableviews I need to create their controller and views. in an example I saw that I can simply create a new controller with .xib file, design it, and just call that xib file from my navigationcontroller.
In another example, some stuff was going on also in the mainwindow.xib and some new controllers and navigation items were added from the mainwindow.xib.
What is the difference between these methods? when and why I should need to open and edit the mainwindow.xib file to add a controller?
The mainwindow.xib is your UIWindow component which you can see as a representation of your iphone screen, it will always be there no matter what. In your examples when you are showing your view controller dirrctly that is because the controller is already a subview of your UIWindow which is the mainwindow.xib in the Interface Builder.
There really is no difference between the 2 methods, in the first one you are adding your controller as a subview progrmatically using:
[window addsubview:mynavcontroller]
And in the second one youbare doing it thru interface builder, you may use whichever method you feel more comfortable with.
You do not really need a controller to show a view, however they can be handy if you want to do any extra stuff such as rotating your view or loading certain data when the view is loading. That being said you could add your view as a subview of your window and it would still work.
I'm having a problem setting a View Controller nib's default View Outlet in Interface Builder. Here's my setup:
I have a TabBar based application where I load a Navigation Controller as a modal view...
MyNavCtrlrSubClass *menu = [[MyNavCtrlrSubClass alloc]initWithNibName:#"MenuController" bundle:nil];
[tabBarController presentModalViewController:menu animated:anim];
MenuController itself is structured as follows:
MenuController.xib
File's Owner (MyNavCtrlrSubClass : UIViewController)
Navigation Controller (UINavigationController)
Navigation Bar (UINavigationBar)
Root View Controller (Nib Name is set to load AnotherViewController.nib)
Navigation Item -> (UINavigationItem)
This all works fine, except that when MyNavCtrlrSubClass is loaded, I get the following error:
Loaded the "MenuController" nib but the view outlet was not set
It's clear why this is happening - File's Owner doesn't have an outlet connection for its view. The question is what should I set as its view, and does something have to be set in the first place? The Navigation Bar is the only candidate in MenuController.xib, but doing this will just size the UINavigationBar itself to the fullscreen mode, so to speak.
I'm obviously missing something in IB, but what? MyNavCtrlrSubClass.m has no code itself, except an IBOutlet for the UINavigationController. Am I making a mistake trying to set this up entirely in IB? The idea is to keep the modal Navigation Controller in one nib, and all the views it loads in separate nibs, but since MenuController is just a container for the navigation and contains no views itself, I'm obviously designing it wrong. :)
If you're wondering why I'm not designing it some other way, it's because I'm trying to obey my (possibly mistaken) perception of how IB asks you to build an ideal hierarchy.
Any help would be greatly appreciated.
I think you might not be understanding how the File's Owner is meant to be used in a NIB file. I've written up a response describing the file's owner under another question.
When you invoke this line:
[[MyNavCtrlrSubClass alloc] initWithNibName:#"MenuController" bundle:nil]
You create an instance of MyNavCtrlrSubClass, and tell it to load #"MenuController". Then in the MenuController.xib file, there is a second unrelated UINavigationController with things inside of it. When MenuController.nib is loaded at runtime, that second navigation controller will be created.
A second problem is that telling a UINavigationController to load a NIB file isn't really sensible because navigation controllers create and manage their own views. You really want to create the root view controller, and tell that view controller to load a NIB file.
Try this:
MyRootViewController *rootController = [[[MyRootViewController alloc] initWithNibName:#"AnotherViewController" bundle:nil] autorelease];
MyNavCtrlrSubClass *menu = [[MyNavCtrlrSubClass alloc] initWithRootViewController:rootController];
Where your XIB File looks like this:
File's Owner (Class set to MyRootViewController, view outlet connected to subsequent UIView)
UIView
Subview A
Subview B
After you're confortable with how all of this is working, you might also consider instantiating the navigation controller and root view controller in one XIB file like you were starting to do in the code you posted.
The crux of this question is stated by Travis himself: "How would you load Navigation Controller nib, designing as much as possible in Interface Builder?" And also from the example, it looks like this means the UINavigationController and associated UIViewControllers.
With this interpretation, the answer is you cannot fully configure a UINavigationController and it's UIViewControllers in a single XIB. Yes it is intuitive to want to do this so you are not crazy.
When I say you cannot do this, I mean the most commonly used framework methods do not have a way to handle this. There is no [UINavigationController alloc] initWithMegaNibName. Yes you could stuff almost anything in a single XIB and write code to hydrate objects in special ways, but I don't think that's what you're looking for.
You could use two or more XIBs as Jon suggested, but then things are less self contained and so you have many folks who find it simpler to do part, or all, of the controllers in code.
Unfortunately there is not a 1:1 correspondance between Interface Builder capability and code like there is on other dev platforms. I generally prefer to be able let designers participate as much as possible in creating assets, but most of them I know do not code objective-c.
In IB, in the MenuController nib add a UIView and set that view as the outlet. You will need to set that view for a UIViewController. Here is a quick link to an Apple page showing a basic setup. Not sure if it will help you at your current stage though.