Why must I hookup an IBOutlet twice in a custom NIB / XIB? - iphone

I have created a custom myViewController class and it has the default view, as well as an IBOutlet (topleftView) to a subview.
I have created a custom NIB/XIB file to load this myViewController.xib. Inside the XIB file I have set the file owner to myViewController and set the UIViewController identity class to myViewController as well.
My question is why do I have to hook up and draw a reference from the IBOutlet in the subview to both the file owner AND the UIViewController in interface builder?
Just trying to get my head around it since this is the first time I'm creating a custom NIB/XIB. I usually just did everything in MainWindow but my application is getting too large so I want to spread things out.
If I don't have these multiple connections for the one IBOutlet to both the UIViewController and File Owner in the same nib file I crash with _EXC_BAD_ACCESS_ errors.

"Inside the XIB file I have set the
file owner to myViewController ..."
I'm not sure what you are doing here. I think this is where the problem is. How many items do you have on the top level of your XIB? It should just be File's Owner, First Responser and a View. If there is another controller object in here, that's your problem. Get rid of it.
"...and set
the UIViewController identity class to
myViewController as well"
This part is correct. To connect your custom UIViewController to the XIB, clock on your "File's Owner", go to the "Identity Inspector" then look under "Class Identity" at the "Class" field. Set this to 'myViewController' (or whatever you named it).
At this point you should do 1 ctrl-drag from your File's Owner for each outlet you have setup.

My question is why do I have to hook
up and draw a reference from the
IBOutlet in the subview to both the
file owner AND the UIViewController in
interface builder?
Short answer: You don't. Just set your File's Owner's class to the class name of your UIViewController subclass and you're set.

Related

Custom UIView iboutlet not set

I have created a custom UIView class named "abc" and a nib with it. Created a UIButton in IB in that nib. Now when I try to create outlet of that UIButton by extending arrow to File's Owner it wont allow me to do so. Please tell What i am doing wrong
You need to change the view of your nib file to the customView class name, in the Identity Inspector, change the UIView Class in the picture to your custom class
Problem might be you are not setting Custom Class name for "abc" in xib file. Please not that whenever you create a subclass of UIView. You have to bind its view with that class. And when you are going to make IBOutlet connection instead of connecting it to File's Owner you have to connect it to you View placed in Objects(object list is on left side in interface builder).
*) Goto the views xib
*) Click on the File's Owner Identity inspector
*) and change the class name to the name of the View yu want.

How would I change the default loaded view controller in Xcode?

How would I do this? Is it simple enough to explain clearly? If not, a tutorial would be nice. I checked the web and this site and still couldn't find exactly what I was looking for.
The default XIB file loaded when your application start is MainWindow.xib by default.
If you want you app to load another XIB instead, this can be changed in the Info.plist file of your project.
In this XIB loaded when the app is launched (MainWindow.XIB by default), you will find:
a placeholder for the File's Owner (like in any XIB) which in the case of the XIB loaded by the application on startup is the UIApplication itself.
a UIWindow (the main and unique window of your iPhone app),
an object that acts as the delegate of your UIApplication (commonly called "the AppDelegate")
And probably a UIViewController too.
When the XIB is loaded at startup, the AppDelegate objet is instanciated (like all objects in the XIB except the File's Owner) and as it is set as the delegate of the application, application:didFinishLaunhcingWithOptions: will be executed. This code then generally add the viewController's view as a subview of your app window using a line like [self.window addSubview:self.viewController.view]. (As your AppDelegate have an IBOutlet that points to the ViewController in the XIB)
If you need to change the class of the ViewController used in your MainWindow.xib, change the class of the UIViewController in Interface Builder, and also change the type of the associated IBOutlet in the AppDelegate header file.

How to get a reference to a control in the view?

If I have a UIScrollView set up in the view via the Interface Builder, how do I get a reference to it in the ViewController implementation? I want to programmatically add labels to the scroll view.
For example, in C# if you have a textbox declared in the UI/form, you can access it by simply using the ID declared for that textbox. It doesn't seem this simple in objective c.
Thanks
Kevin
Assuming I understand you rightly and you are instantiating a view controller from a .xib containing subviews including the UIScrollView you want, there are two ways - first, you can find it in the subviews array that is owned by the view controller. Second, you can add an IBOutlet reference to it in your header file, then in interface builder make the connection using the connections inspector. Then you can refer to the object in your code, change frame, add labels etc.
You need to wire your ViewController up to your Nib files. This is pretty straightforward. This is your basic workflow for using Interface Builder on the iPhone/iPad:
Set the Class of the 'File's Owner' to the class of your view controller. You can do this by selecting the 'File's Owner' object in your nib window, pressing Command-4, and setting the class via the drop-down.
Create properties in your View Controller with the following format:
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
The IBOutlet keyword is a macro that evaluates to nothing. So it doesn't actually do anything to your code, it just exists to let Interface Builder know that the 'scrollView' property can be bound to.
Control-drag from the object you'd like to bind to your ViewController. In the popup you can select the property you'd like to bind to the scroll view object.
This sort of stuff is pretty basic Xcode stuff. If you read any tutorial out there it'll cover this. Good luck, and enjoy!
edit:
I should add that if you used the default "New UIViewController Subclass" from the New File dialog, it will have done step one for you. You'll have a nib file and a View Controller that already know about each other.
Yes, the code you wrote is all you need in your header. Just make sure you connect the Scroll View object to the property in Interface Builder.
Yup! 'viewDidLoad' is added after all the connections specified in the Nib file have been made, so you can be confident that scrollView point to the correct object (assuming everything in the Nib is wired correctly, which is an easy mistake to make)

UITableView and UIImage inside a UIView

I am developing an application that currently has a View Controller (call it ViewControllerX). The MainWindow.xib file contains the following:
File's Owner UIApplication
First Responder UIResponder
AppX App Delegate myAppDelegate
myViewControllerX myViewControllerX
Window UIWindow
When I look at the MainWindow.xib in Interface Builder it shows View Loaded from "myViewControllerX". The myViewControllerX.xib file for this contains the following:
File's Owner UIApplication
First Responder UIResponder
MainView UIView
Image View (image1.jpg) UIImage View (Inside MainView)
Rounded Rect Button UIButton (Inside MainView)
Rounded Rect Button UIButton (Inside MainView)
Table View UITableView (Inside MainView)
On the Table View, I have the Outlets set to dataSource = File's Owner and Delegate = File's Owner. The Referencing Outlet is set to mTableView which is defined using IBOutlet in XCode. When I run this all works fine and the table gets populated.
When the users clicks an Item within the Table View I want a new view to slide into place, which also contains a TableView (basically the first View Controller shows an overview list, when the user clicks on an Item I want it to show the details of the choice). In the myViewControllerX.m file, I have the following code:
- (void)tableView:(UITableView*)theTableView didSelectRowAtIndexPath:(NSIndexPath*)theIndexPath
{
[self.navigationController pushViewController:self.mViewControllerY animated:YES];
}
I have created a ViewControllerY and have the following files:
ViewControllerY.xib, ViewControllerY.m and ViewControllerY.h.
In the .xib file for ViewControllerY, I have:
File's Owner UIApplication
First Responder UIResponder
Table View UITableView
When I run this it works (so the code and the hook-ups in Interface Builder are ok). The Problem is it takes over the whole of the view whereas want I want it to have an Image (and other UI objects) as well as a Table View. I've tried changing the UITableView of ViewControllerY to be of type UIView and then adding an UIImageView and UITableView inside of the UIView in a similar way to ViewControllerX but I can't get it to work and now I'm not sure what to do! So, my question is, how do I go about Implementing this? I'd like to be able to have it setup in Interface Builder, so how to I change it to handle this? e.g How do I hook up the dataSource, Delegate and Outlets etc.
Thanks in Advance for any help in this. I've tried all kinds of things but I just can't seem to get it to work. I'm sure I'm almost there and must be missing something that is very obvious!
All the Best
Dave
Your UINavigationController uses a content view that more or less completely covers your device screen. And this view is used for your main view. If you ask this UINavigationController to push another view, he uses this very same view to swap in the ViewControllerYs view which also covers the complete screen.
To gain the behavior you need, you should create a second "embedded" Navigation Controller instance which is responsible only for that part that is initially by your table view. Display your table view as the main view and then ask this Navigation Controller to swap in your other views into this part of the screen.
After taking a step back and doing a bit more digging, I came up with the answer.
High Level Explanation.
ViewControllerY needs to be of class UIViewController, not UITableViewController. The ViewControllerY : UIViewController definition in the .h file should include the Table View Delegate and the Data Source protocols. A member of the ViewControllerY has to hold the UITableView* - call it mTableView and should be defined as an IBOutlet.
The table view delegate methods should then use self.mTableView to access the table.
In Interface Builder, the UIView Object needs to have an Outlet "view" hooked up to the File's Owner and the Table View inside the UIView needs to have the dataSounce and the Delegate set to File's Owner and the mTableView Outlet also needs to be hooked to the File's Owner.
Low Level Explanation.
in ViewControllerY.h do the following:
#interface ViewControllerY : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
UITableView* mTableView;
}
#property (nonatomic, retain) IBOutlet UITableView* mTableView;
In ViewControllerY.m, in the Table View Delegate methods, access the mTableView like so:
myNewCell = (UITableViewCell*)[self.mTableView dequeueReusableCellWithIdentifier:myCellIdentifier];
(obviously you need to define and handle all the other Table View Methods in the normal way.
ViewControllerY.xib should have the following in it:
File's Owner ViewControllerY
First Responder UIResponder
View UIView
Image View UIImageView
Table View UITableView
Control Drag from the File's Owner to the View and select "view".
Control Drag from the Table View to the File's Owner and select Data Source.
Control Drag from the Table View to the File's Owner and select Deligate.
Control Drag from the File's Owner to the Table View and select mTableView.
That's it! You can then add other UI objects inside the UIView and hook them up as appropriate in the normal way. I'm not sure if this is the only or best solution but is works and I'm happy with it.
Hope this helps someone with the same or similar problems. It's a bit confusing til you get the hang of it.

Very basic problem with Tab Bar Application and Interface Builder

OK, here is how to re-create the problem had:
Create a new project, using the
Tab Bar Application
Add a UILabel within SecondView.xib
Add IBOutlet UILabel* myLabel; to FirstViewController.h
Connect up myLabel in IB.
Build and run.
When I click the second tab the app crashes with:
__TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__
In IB, when using UITabBarController which has multiple UIViewControllers which all separately have their own NIB file assigned, there are two places where you need to set your UIViewController class file.
First, the obvious one was within the NIB file for each UIViewController.
Secondly, where I'd missed it, is withing the NIB file for your UITabBarController. In each UIViewController, not only do you set your NIB file, but also the Class.