File's Owner of UITabBarController Subviews - ios

I followed this UITabBarController Tutorial which creates a Tab Bar with according subviews mostly using Interface Builder. The UITabBarController is created there and the Tab's View Controllers are added there too.
Am I correct that creating the UIViewControllers {WelcomeViewController|AboutViewController}.{h|m} is unnecessary?
Who is the real File's Owner of the Subviews {WelcomeViewController|AboutViewController}.xib?
Note that I at first tried to create an IBAction method in WelcomeViewController.h: in Interface Builder at WelcomeViewController.xib, I could connect a button press to that action as it appeared at File's Owner. But at runtime it crashed, as the real File's Owner presumably is not an Object of WelcomeViewController.m. Am I right here? Is it a bug that the IBAction appears in Interface Builder (Xcode 4 here)?
A last question: How/can I still separate code (having IBActions in WelcomeViewController.h for actions that happen only on this subview) when I connect everything up in Interface Builder like in the tutorial?

Am I correct that creating the UIViewControllers {WelcomeViewController|AboutViewController}.{h|m} is unnecessary?
No, both controllers are necessary, since there should be at least (and, optimally, at most) one ViewController per full-screen window to manage your view hierarchy. The TabBarController is only a kind of "dumb" meta-controller managing the display of the sub-controllers it loads - therefore you need controllers for the views which are switched. I would recommend you read this part of the Apple doc.
Who is the real File's Owner of the Subviews {WelcomeViewController|AboutViewController}.xib?
The File's Owner should be the corresponding controller class (in your case, {WelcomeViewController|AboutViewController}.{h|m}) - you can set the class in Interface Builder in the inspector palette when File's Owner is selected. Only the very first window (usually called Main.xib or so) which is opened at application start should have the application delegate as File's Owner. File's Owners own the objects of the XIB/NIB file - object-reference wise, you know what I mean :) I think it should also be possible to load the XIB/NIB file with other controllers (and the other controller automatically becoming the File's Owner), but I'm not sure.
... Am I right here? Is it a bug that the IBAction appears in Interface Builder (Xcode 4 here)?
It may be that you wired up the action the wrong way in Interface Builder, a common mistake. Try holding the Ctrl key, then drag a line from the button onto the File's Owner, and choose the desired method to link to. That should do it.
A last question: How/can I still separate code (having IBActions in WelcomeViewController.h for actions that happen only on this subview) when I connect everything up in Interface Builder like in the tutorial?
I think I answered this in the first paragraph - WelcomeViewController is still there and all you have to do is create IBOutlets and wire them up in IB. Of course, you can also do the wiring programmatically, since the member "view" is automatically populated (via the File's Owner connection), and all subviews are accessible from there.

Related

How do I respond to actions happening in a custom view loaded from xib?

I've followed the instructions in this answer to create a reusable custom UIView laid out with a xib, which I can embed in my Storyboard by referencing the custom class. This works well and I can successfully load the view as advertised. However I want my embedding view controller(s) to be able to connect to IBActions of my embedded view. In the linked example, the custom view receives its own actions but this seems like poor design. I've worked around this by creating a delegate protocol that for custom view, which forwards events to its delegate, but this feels like more work than should be necessary. Additionally, Interface Builder will not allow me to wire up the delegate using references in the UI so I must instead do it programatically.
What I really want is to create a custom IB Action in my custom view, like someActionHappened, then wire that up in the embedding view controller. What is the best way to accomplish this?
A .xib file has a File's Owner, which you can see and select when you're editing it.
When you load the nib, you get to specify the owner.
You can (and must) make the classes of these two things (the File's Owner in the nib and the actual owner at load time) match.
Thus, an action can be hooked from something in the nib to an IBAction in the File's Owner's class, and it will be fulfilled when the nib is loaded. Problem solved.
So:
However I want my embedding view controller(s) to be able to connect to IBActions of my embedded view
So the solution for you is to make your File's Owner (in your nib) and the actual owner (at nib-loading time) be your embedding view controller. Now your embedding view controller is allowed to have an IBAction and you can connect to it in the nib.

Create View Programmatically in Objective-C Xcode 5

How should I go about creating a View for the storyboard programmatically? I want to access the labels from the first ViewController object made(automatically to call the IBAction methods of VC). I know that this first object of VC is the one linked to the view in the storyboard(?) and I need to change a label form another file, besides VC. I'm pretty sure the only way to do so would be to access the VC object that is linked to the view, or create one and not go with the default one that is created. If not, how would I go about accessing the labels of the view from another file?
You don't create storyboard objects programmatically. A storyboard is very basically an XML file Xcode uses to call different view controllers. The biggest advantage of using storyboards over NIBs is you can layout transitions or segues, and the advantage of NIBs or storyboards over initiating view controllers by code is obviously the visual interface. So your question doesn't really make sense.
If you want to reference a particular view controller's label from your storyboard you need to create a pointer to that view controller first, but changing it programmatically doesn't make sense because that's what storyboard is for.
That said you may just need to go look for your class name in your view controller's Identity Inspector in storyboard and then edit your label programmatically through an IBOutlet property.

Utilities Sidebar not functioning properly

I have a XIB file inside of which there are some connections between some objects and the file's owner (a ViewController). I'm getting anything shown in the utilities sidebar that you can pop out from the sidebar in order to do some configuration stuff. It shows as "Not Applicable". I had created the XIB file along with the ViewController file (check marked the option in the New File sheet) so the file's owner was preconfigured to the ViewController by default. I have already made the connections and added the necessary IBAction selector for the UIControl stuff. Its just that whenever i select an object in the view frame, its config doesn't show up in the utilities. I have another XIB file hooked with some other view controller, and don't have the problem. What's up with Utilities sidebar????
I find restarting xCode often fixes this annoying bug.

Present UIViewController from another UIViewController

I have a UIViewController named ViewControllerHome and when the user touches an image on the screen I would like to display a second view which is a Membership Card. I am doing the following from the touch of the image:
membershipCardViewController = [[MembershipCardViewController alloc] initWithNibName:#"MembershipCard" bundle:nil];
[self presentViewController:membershipCardViewController animated:YES completion:nil];
When the code executes an exception is thrown on the presentViewController line.
I have an .xib with a ViewController that contains a view and a UIImageView of the Membership Card. I set the class of the ViewController to my MembershipViewController.
Once that shows up I will dismiss it on a touch.
Can anyone tell me what I am missing? I thought I had all the steps correct to present the view controller.
Thanks for the help.
In the MembershipCardViewController's nib file, its view (what ever view it is controlling) is connected to the view controllers view outlet.
To do this control drag from files owner to the view you want to connect it to (the grey view in this case)
And you should get this:
Files owner should point to your MembershipCardViewController. Every view controller has a pointer to a view. I'm going to guess that you added some custom view after deleting the stock one. Control drag from files owner to that view to make the outlet. (If this outlet returns nil, an exception will be thrown).
To be safe, make sure file's owner (in the nib) is pointing to MembershipCardViewController
(This probably isn't the problem but it sounds like you may have started with an empty nib).
To do this, click on files owner, and select the identity inspector on the right. Make sure the class says MembershipCardViewController
I answered another question before about this Am I right in saying initWithNibName:bundle is used to manually load nib files and that initWithCoder would be used as an alternative?
This explains what is actually going on.
The purpose of your XIB is to archive the view of the controller. Having the controller class set is only part of the required information, you also need to connect any IBOutlet relationships between the controller and the views.
As standard any subclass of UIViewController provides an outlet called view. You need to ensure that it's connected. Otherwise when you load the XIB the view doesn't get set and you get an exception.
There are a number of ways to make the connection. Check this.
See also loaded-nib-but-the-view-outlet-was-not-set-new-to-interfacebuilder.

iOS : Setting actions, datasources and delegates not to the file's owner

Maybe those are two different questions, but they basically ask the same thing.
I have a single view app, on my screen I have a Table View and a Collection View.
1) I want to provide a datasource (and delegate of course) for my tableview and for my collection view, but I don't want it to be in the same (main) ViewController file (in purpose of cleaner code). But the interface builder only allows me declaring as datasource (and delegate) the file's owner, which is the view controller. How can I do this? Is declaring programatically the right way? If so, where should it be done? Or, maybe, separating the datasources (and delegates) from the ViewController isn't the best practice?
2) In my table view's custom cells I have a button I wan't to deal with the button's actions in the same place (file) I deal with row selection (delegate obj). But once again the IB only let's me to connect the action to the custom cell class. How can I connect the action to another place?
Thank you for your answers in advance,
Dan
You should use the Object (the blue cube) from the object library. Drag and drop to the section (Documents outline) where your file's owner is present. Then in the identity inspector set it as the class (say Outsider) you want it to be. This will allow you to set Outsider object as the delegate/datasource and will also allow you to write IBAction's there.
The trick is to make that object(Class) visible in the xib by creating an object inside the xib (which will be done when the nib is loaded ).
And another thing, there is nothing wrong in setting the delegate or datasource programmatically, however through interface builder its much more convenient.
1) Do it programatically. Write your own delegate and assign it in code. Cleaner.
2) Connect the button's action in the ViewController class. That is clean, that's what view controllers are meant for. Turn on assistant editor and drag the "arrow" to the header file.
Question 1:
But the interface builder only allows me declaring as datasource (and
delegate) the file's owner, which is the view controller.
Question 2:
But once again the IB only let's me to connect the action to the
custom cell class. How can I connect the action to another place?
Both have same answer:
You can change the class by selectecing from interface builder.

Resources