I am new to Iphone development. My app consists of two storyboards one for the Ipad and other for the Iphone.Now, my problem is I have an IBOutletCollection of UILabels hooked up as a property with one of the viewcontrollers in my Iphone storyboard..How am I suppose to hook up the same Ipad storyboard viewcontroller with the IBOutletCollection of UILabels for the same class..?
Thanks in advance..
Just like you'd hook up any other IBOutlet, IBOutletCollection or IBAction.
Your UIViewController sub-class contains the bits which let you hook something in a storyboard to it.
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *tabButtons;
In your storyboard, you can assign the view controller to be of a certain class, in this case it will be a your UIViewController sub-class. Now all you have to do it drag the storyboard artifacts to your existing IBOutlet stubs. It works.
You can do this for multiple storyboards using the same class (or multiple view controller in the same storyboard too). When you load it into memory, you specify the item in the storyboard, then the storyboard creates and instance of the view controller and hooks up all the references, so all is good.
MyViewController *myVC = [storyboard instantiateViewControllerWithIdentifier:#"foo"];
I'm having some problems because I don't know how it can be done. Someone help me please.
Problem:
I have a project with a UIViewController class with created all time when I create a new project in Xcode. In this viewController, I have a xib file for designing in Xcode.
What I need is to create some views and design them in Interface Builder like this:
But I need these views to be UIViewControllers, not UIViews.
The project should look like:
So I don't know how I can do this in IB but I can do it from source code in ViewController.m
tab = [[TabBarController alloc] initWithNibName:#"mytestview" bundle:nil];
[tab.view setFrame:CGRectMake(100, 100, 400, 600)];
[self.view addSubview:tab.view];
But it's not my views it's a different object, and if I want to change position or size I must do it from code. How I can do same things in Interface Builder?
Let's consider following example based on Master-Detailed Application for iPhone only.
So, add new view controller in newly created project in Xcode:
I called it NewInsideViewController. Create it without xib:
Open DetailViewController.xib. Drag View Controller and View(*) objects from library to Objects area like this (I changed view's color to LightGray):
Choose this View Controller and change its Class from UIViewController to NewInsideController at the Identity Inspector:
Assign our View(*) to NewInsideController as a view:
Now all main actions in IB finished. We need to create instance of NewInsideController in our DetailViewController. You can do it by hand, but Xcode has a nice feature - drag-n-drop ;)
I called this property as myNewInsideController and DetailViewController.h looks like this:
#import <UIKit/UIKit.h>
#import "NewInsideController.h"
#interface DetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet NewInsideController *myNewInsideController;
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
Well, now our NewInsideController ready to work and manage its view. Let's add button and action to that view in order to verify this:
Write some code in IBAction in NewInsideController.
- (IBAction)insideButtonClick:(id)sender {
float rPart = arc4random()%100/100.0f;
float gPart = arc4random()%100/100.0f;
self.view.backgroundColor = [UIColor colorWithRed:rPart green:gPart blue:0.5f alpha:1.0f];
}
Run program.
If I understand the question clearly:
You have a parent view and controller, coming from a XIB.
You have placed subviews into the parent view.
You're wanting each subview placed into the parent view to have it's own (custom) controller, but you don't know how to add view controller's to your hierarchy (XCode will not let you drag view controllers into a view's canvas).
So, to answer the question succinctly: Let's assume you have a handful of custom UIViewController's in your project (each view controller consisting of a .h and a .m). Remember that you if you are laying these out in the context of the parent, they shouldn't have their own XIBs (you cannot nest XIBs in IB). What is important to note here is that you should only "layout" the interface in one location. If you want to have a XIB for each subview, this is not the correct approach. What you can (not should) do, however, is have several custom viewControllers, each connected to it's own view sitting within your parentView, and you can have the outlets of your sub view controller's set to objects in this parentView. Phew, kinda messy. The other thing you'd need to be aware of is that your parent view controller would need a reference to each of it's sub view controllers in order for you to be able to access those sub-controllers and their outlets programmatically, so for each sub view controller you add, you would also need to add an IBOutlet in your parent view controller pointing to each subviewController:
ParentViewController.h
#property (nonatomic, weak) IBOutlet CustomUIViewController *firstCustomController;
And then for example to set the background color on the view of your first custom subview/controller:
ParentViewController.m
[[[self firstCustomController] view] setBackgroundColor:[UIColor whiteColor]];
Open up your parent view controller in IB. If you look in your drawer of available objects, you'll find a generic UIViewController object. Drag this into your parent view controller (NOT onto it's views canvas, rather into the parent UIViewController object itself as seen in the left-column of IB builder). Select the generic view controller you've added and set it's class to your desired UIViewController subclass. Now, when your XIB loads, it will instantiate an instance of your custom view controller along with whatever you've added to it's canvas.
Finally, drag a generic UIView onto your canvas, placing it inside your existing controller's view (your screenshot already shows this as done). Right-click your custom view controller, and connect it's 'view' outlet to the view you added.
Now when you run, your custom view controller has a view that is on the screen that is the view of your custom controller subclass, and you didn't do any of it in code.
So now that you've done it, consider whether or not it is the best choice: Nested view controllers are messy to build (as you've seen) and aren't necessarily a good design decision: http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/
Although iOS5 does support nested view controllers, personally I'd avoid using them. I value a best practice dictating one screen = one view controller.
You never, EVER, want to take views which are already under the control of a certain view controller, and make them subviews of another view controller's view.
View Controllers are the C part in the MVC design pattern - They are in charge of controlling a view (and its subviews). You can't take a view which is being managed by a controller, and stick it as a subview of a different controller's view - If you do that, it becomes ambigous who is responsible to manage this view.
Even though this "sticking" might be possible technically, it creates code which is hard to understand, hard to maintain, and most importantly - will cause bugs due to the unclarity of who is responsible to manage the view, and due to the fact that Apple's View/Controller framework doesn't support this.
For example: If the device is low on memory, Apple makes sure to unload views which are not currently displayed. Apple relies on the view controllers hierarchy to know when it can unload views. If you stick the view controller's view in another view controller's view, it's very likely that the view will never be unloaded even if it isn't visible.
Instead of breaking the view controller hierarchy, do one of the following:
Just add subviews to your view normally, either in interface builder, or in -viewDidLoad: to add them programatically, or (rarer) override -loadView.
Use view controller containment, either with Apple's ready-made ones (UINavigationController,UISplitViewController etc.) or with your own container view controllers (iOS>5).
Display view controllers modally.
The bad idea of breaking a view controller hierarchy is indeed very common and often seen in 3rd parties, probably because it's so easy and seemingly straightforward. Unfortunately this causes the aforementioned bugs :-(
I really recommend to everyone participating in this thread and comments to read Apple's View Controller Programming Guide, and watch WWDC 2011 "View Controller Containment" video.
I know this has been discussed a number of times but I still have some problems getting around the problem, so any help would be appreciated. I have a class MyView which subclasses UIView. So far so good, in this custom class I basically configure the layout, UI, etc.
Now, I have a separate UIViewController and what I want to do is create an outlet for that custom view. In the view controller's Nib I set the view's class to that of my custom view and connect it to the outlet, but I can't see anything apart from a blank view.
How and where do I load the view from nib? Do I simply say self.theOutletForMyCustomView = load from nib or is it something else? Thanks for your help
First of all, you have to set the name of your CustomView inside your UIViewController nib file like that
Then, you have to retain your property like that inside your UIViewController interface :
#property (nonatomic, retain) IBOutlet CustomView *myCustomView;
or an ivar should work, but assign an IBOutlet property doesn't work.
And if you customize your CustomView inside your CustomView class implementation. Beware of doing your initialization in awakeFromNib or initWithCoder: instead of initWithFrame:
Inside Interface Builder I have a UINavigationController, which contains a UIViewController, which has a UIView inside it. This main UIView has a bunch of labels as well as a few ImageViews and custom UIViews as well.
What I want to do though is throw a UITableView inside this main UIView. This UITableView will take up about half the screen in the UIView. I'm trying to add a UITableViewController below the UIView but everytime I do it, the UITableViewController object replaces my UIViewController object in IB??
What am I doing wrong?
I want:
UINavigationController
UIViewController
UIView
UITableViewController (since the UTableView will be inside the preceding UIView)
Where am I going wrong in this setup? When I try to add the UITableViewController in IB I get:
UINavigationController
UITableViewController (..err? Why's it replacing my ViewController?)
Thanks in advance!
After putting UITableView into UIView instead of UITableViewController, and then set table view's delegate and data source to UIViewController.
Naturally, UIViewController should implements two protocol (table view deleate and data source).
You probably don't need table view controller at all. You have to add UITableView and implement all necessary data source and delegate methods in your view controller.
Do I need a UITableViewController in addition to my UIViewController if I want to load a UITableView as a subview along with several other views at one time?
No, just make your UIViewController the data source and delegate of the UITableView subview, and make sure the UIViewController adopts the appropriate protocols in the header file.