Subclasses of a ViewController with a nib - iphone

I have a ViewController that I've set up with outlet and a NIB.
This is my super class view controller.
I now want to create a subclass of this view controller as there is one method I would like to override.
I'm not sure how to go about doing this.
I've tried to do it but at the moment I've just got the functions in the superclass running in place of the actual class I want.
Any pointers?
EDIT
Sorry, I had done it correctly but had a typo in the overridden function.

If you want your super class functions not to run then you must override them. Just write the definition of the method you want to override and that will override it. The rest of the functions will be same as super class.

Related

Custom initialise subview added from storyboard

I have a subclass of UIViewController that I want to add from the storyboard.
So I'm using what seems the standard methodology:
SubViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:#"SubViewControllerID"];
[self addChildViewController:svc];
[self.view addSubview:svc.view];
Which is fine but what if I want to call a custom init method on the subview?
I can do something like:
svc = [svc initWithFoo:#"Hello"];
Which seems to have to go after the addSubview call inorder for it to work.
Is this the best way to do this?
Seems a bit unorthodox. Calling an init method on an object that has already been created seems like its no longer truly an init method.
Maybe I should call it setWithFoo: or something and not have it return anything?
SubViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:#"SubViewControllerID"];
will cause the SubViewController to be inited with it's - (id)initWithCoder:(NSCoder *)decoder {} method.
Override that method (don't forget to call super)
If you want to do additional setup to your view controller after you instantiate it form the storyboard you can create some methods in the view controller's class and call them after the instantiate method fo the storyboard.
But be careful, if you try to make changes on any UI component in those methods, they wont be applied, and probably the app will crash. So use those methods to set params to the View Controller like array of objects, or any kind of data, and apply the UI changes for the view controller's view in viewDidLoad/viewWillAppear/viewDidAppear methods of your view controller.
Essentially I think the answer is that you can't use custom initialisers on ViewControllers added from the storyboard. Instead you have to set properties directly or through a method at the appropriate time in the life cycle as stated above.
Also as mentioned, the VC will be instantiated through initWithCoder, so calling an additional initialiser might be superfluous(?).
I encountered problems trying to use a custom initialiser that contains a call to super if I called it before the subview was added. I would just get a blank view added, I think because the superclass doesn't seem to know about the storyboard at that point. I had more success removing the call to super but that seems wrong.
This case would be more pertinent when adding subviews to a scrollview. For simplicity I left this out of my example.

Best Way to Add Object Via Other Class?

In my iPhone app, I have a custom UIViewController class setup which adds some UIImageViews and things.
How can I access this class via my main UIViewController and, for example, call a method from that outside class and have it add those UIImageViews to the view?
Make property and public methods, after that you can call them in target viewcontroller.
p.s. But I never used this approach because it breaks controller's logic. Instead of I usually use some managers which has all required methods. (DBManager, NetworkManager, etc)

Accessing UIView methods

I have a UIViewController that contains a UITabBarController, which contains a UIViewController, e.g.:
UIViewController1 -> UITabBarController -> UIViewController2
I want to hook up a button in UIViewController2 that will call a method in UIViewController1, but how do I access UIViewController1 from UIViewController2? I know that calling self.parentViewController from UIViewController2 gets me to the UITabBarController, but where do I go from there?
I tried self.parentViewController.parentViewController from UIViewController2, but got null.
Any suggestions?
The self.parent.parent technique often won't work because there may be Apple implementation layers in-between your controllers. Best to create pointers yourself in your own implementation by subclassing and creating instance variables, and setting them at the point of creation.
There are several ways to do this depending on what your actually trying to solve....for example if its a utility like class method then you should put it in a different file and import it into UIViewController2. If its an instance method then you obviously have an instance of UIViewController1 then you need to declare an instance variable of type UIViewController1 that holds a reference to the view controller. Then you can call methods on that instance....what is it that you are trying to accomplish?
Just add the first one as a property and assign it when you instantiate:
viewController1.otherView = viewController2;

Object and view setup and initialization in objective-C

When creating a UIViewController derived class in objective-C, what goes into the init method, what should go into loadView and what into viewDidLoad - and more importantly why, and what benefit (performance?) does this have?
Also, how does this relate to UIView derived classes where the only option you have is the init method?
I know the template code already has comments for what goes into each method, but it unclear to me why each thing goes where they say.
Clarification
I would like to know maybe at a lower level, what is the actual difference between things being done in the 'init', 'loadView' and 'viewDidLoad'. What does the framework do in between these calls that may affect the way/time I set up my views and do other work? How are these methods affected by threading?
You want to know some lower-level stuff.
init: This method gets called on ANY NSObject subclass. It is what sets up the object, which you probably already know. In many model (as in the MVC pattern) classes, init is directly used. As for the UIKit classes, very few requires init to be called directly. It should not be used. In the UIViewController, you initialize it using initWithNibNamed:. You can override this method, but in most cases this is not needed. This method is the VERY first method to EVER get called on the class (before any view setup, or such).
loadView:and viewDidLoad: read this article iPhone SDK: what is the difference between loadView and viewDidLoad? .
The only really important thing to know is that -init is the NSObject standard initialization method. -loadView and -viewDidLoad are UIViewController's methods for initialization.

Automatically Loading XIB for UITableViewController

Ran into something interesting, want to know if I'm doing something wrong or if this is the correct behavior.
I have a custom UITableViewController. I ASSUMED (first mistake) that if you initialize as such:
[[CustomTableController alloc] init];
it would automatically load from a XIB of the same name, CustomTableController.xib, if it is in the same directory and such.
HOWEVER
This does not work; doesn't load the XIB. BUT, if I change the parent class of my controller from 'UITableViewController' to 'UIViewController', EVERYHTING WORKS FINE!
Calling:
[[CustomTableController alloc] init];
loads the controller and view from my xib.
Am I doing something wrong? Is this a bug? Expected behavior?
Most of the classes in Cocoa Touch list a "designated initializer" that you're supposed to call from your init methods when you subclass them. When you create your own custom class, it's a good idea to check the documentation to find the designated initializer for your superclass. When you initialize the class using some other initializer from a more general superclass (which you're doing by calling - [NSObject init] in this case), you rob your direct superclass of its opportunity to properly initialize its state. Sometimes you can get away with this. Often you can't.
UIViewController's documentation states that its designated initializer is -initWithNibName:bundle:. If you call this method with a nil nibName, it will look for a nib that matches your class name. The behavior of -init is undocumented for UIViewController. Based on the behavior you're seeing, it seems like it may be calling [self initWithNibName:nil bundle:nil], but it would be safer to call initWithNibName:bundle: directly rather than relying on this undocumented behavior.
UITableViewController only defines a single initializer, -initWithStyle: (although it doesn't specify this method as the designated initializer). This method initializes your UITableViewController without using a nib, which is usually fine. Since you don't add subviews to a UITableView, there usually isn't much to be gained by configuring your UITableViewController via a nib.
If decide you want to configure your UITableViewController via a nib anyway, the documentation tells us that we can safely bypass -initWithStyle: and call UIViewController's initWithNibName:bundle: method. Here is what the documentation tells us about how our UITableView and its controller will be initialized in each case:
If a nib file is specified via the initWithNibName:bundle: method (which is declared by the superclass UIViewController), UITableViewController loads the table view archived in the nib file. Otherwise, it creates an unconfigured UITableView object with the correct dimensions and autoresize mask. You can access this view through the tableView property.
If a nib file containing the table view is loaded, the data source and delegate become those objects defined in the nib file (if any). If no nib file is specified or if the nib file defines no data source or delegate, UITableViewController sets the data source and the delegate of the table view to self.
In summary, the documentation for most Cocoa Touch classes either specify a single designated initializer or a handful of initializers that you can call safely from your subclasses. Always refer to the documentation for your superclass to figure out which initializer your subclass should call.