UITableViewController being initialised twice - ios

I was trying to modally present a UINavigationController with a UITableViewController as it's root view but kept crashing the app when pressing the button to present the modal view.
- (IBAction)flipToDefaultsViewController:(id)sender
{
RootTableViewController *controller = [[RootTableViewController alloc] initWithNibName:#"RootTableViewController" bundle:nil];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:controller];
nc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:nc animated:YES];
}
The app crash with the message:
[RootTableViewController numberOfSectionsInTableView:]: message sent to deallocated instance 0x5677b5
When I loaded up Instruments to take a further look it was apparent that two instances of my UITableViewController were created, one with the owner of the UINavigationController and the other by UIKit. The UIKit created instance was the one that was deallocated and causing the crash.
When I changed the initialisation from initWithNibName:bundle: to init the UITableViewController loaded fine (my .xib file was the same name as the class).
My question is why would this happen?
Should you not initialise a UITableViewController this way when adding it to a UINavigationController? I've had a hunt around the documentation with no joy so far.
Using iOS 5 with ARC but target deployment is 4.0.

I haven't worked out why the object was being initialised twice, however I did review the steps that I used to create the .xib file and it looks like there is a problem with copying a view from a Storyboard to Interface Builder. In hindsight this makes sense, but as the view appears to copy without error and everything else seems to look okay it's easily done.
It would appear that similar problems were experienced by others with similar results.
By creating a completely clean subclass of UITableViewController with a nib file (⌘-N) and copying code from the initial class into the new one I'm able to use the initial code above to alloc/init my modal view.
BTW I was mistaken in my opening post about the nib file loading correctly when using init. It wasn't and in fact this behaviour doesn't happen for UITableViewController apparently where as other classes having a class name the same as the .xib file will attempt to load the .xib first.

If this is a button, than you should not initialize anything when the button is pressed. You should initialize beforehand and simply present the modalViewController when the button is pressed.
Is there any reason why the rootViewController and the navigation controller cannot be initialized in the appdelegate didFinishLaunchingWithOptions method?

Related

Contained UIViewControllers - should I use .xib or the storyboard?

I'm making an app that will have a VC doing a similar job as a UITabBarController and I'm using
[self addChildViewController:theViewController];
// [self addSubview ... etc
to put a custom UIViewController's view as a subview of my main (root) VC.
So my question is, which is the correct way to instantiate a VC and not have to build it's UI programatically - from a .xib file, or from a storyboard?
With a xib:
UICustomViewController *controller = [[UICustomViewController alloc] initWithNibName:#"customVC" bundle:nil];
With a storyboard:
UICustomViewController* child = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
I believe .xib files are old stuff and storyboards are the way to go, but I also read this article, which suggests that using a storyboard to do this is a bit hacky. I don't know, any thoughts?
there is nothing any major difference in both way , they are same . but in many other angle storyboard is the straight way, there is nothing any hacky
If you want the child view controller to be present when the app opens, you can do it in a storyboard without any code at all. Add a container view to your root vc, and you will automatically get a view controller embedded in it.

Displaying UIViewController inside a UIPopoverController

I am trying to present a UIViewController inside a UIPopoverController. I've designed a view controller in Interface Builder, gave it a custom class (let's say MyAppTestViewController) and I'm trying to create a popover this way:
MyAppTestViewController *fxViewController = [MyAppTestViewController new];
self.fxPopover = [[UIPopoverController alloc] initWithContentViewController:fxViewController];
self.fxPopover.popoverContentSize = CGSizeMake(1024, 120);
[self.fxPopover presentPopoverFromBarButtonItem:_fxButton permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
When I press the button, a popover is displayed at the correct place with the correct size, but it is empty. I've verified that the MyAppTestViewController's viewDidAppear method is being called (by NSLog), but the Popover's inside is empty:
Am I missing something?
I see that you mentioned in a comment that you're using a storyboard. So why not use a popover segue to your MyAppTestViewController? You could wire the segue directly to the Effects button on your toolbar. (Or, alternatively, call performSegueWithIdentifier: from your presenting view controller.) You might do a quick test by just throwing a UILabel into MyAppTestViewController right on the storyboard and seeing if it displays properly.
I think the problem is here:
MyAppTestViewController *fxViewController = [MyAppTestViewController new];
Generally you would use [[MyViewControllerClass alloc] initWithNibName:nil bundle:nil] (assuming you have a xib file with a matching name). I don't believe I have ever seen a view controller initialized with new. Everything in Objective-C is alloc-init.
Apple Docs: UIViewController Class Reference
Quote:
To initialize your view controller object using a nib, you use the
initWithNibName:bundle: method to specify the nib file used by the
view controller. Then, when the view controller needs to load its
views, it automatically creates and configures the views using the
information stored in the nib file.
EDIT:
Fascinating, well okay. It looks like you are right about the use of the new keyword, here is bit of an explanation of this.
So fine, that's not the problem. Have you tried breaking on the viewDidAppear method and using the debugger to print out the view properties, check its frame, check its superview, and so on, try to understand the problem better? You may already know how to do this, but the commands would be po self.view and so on.
In any case, I also found this, although it only goes into the mechanics of popover presentation and not content view assignment, which you seem to have down.

UIStoryboard UIView controller

In published my app with a UIViewController connected to the main .h file in Storyboard. The controller can not be reached in any way (it is not connected with a segue to any other view controller. My doubt is: Does this controller take up memory? The codes don't run if the controller is not opened, or am I wrong??
When your program is loaded, an instance of UIStoryboard is created, which loads the storyboard file (a flat XML) and parses it. Therefore there is some memory that is associated with your ViewController. However, until the ViewController is not loaded, it is neither allocated nor instantiated.
That said, you can load UIViewController from the storyboard without connecting it with a segue. This is done using the Identifier of the UIViewController with the Method -instantiateViewControllerWithIdentifier: of your UIStoryboard.
If this does not happen in your code, the only memory the definition of the UIViewController causes is associated with the instance of your UIStoryboard.

Not able to modaly push tableView containing Core-Data data

I've managed to create a tableViewController inside a NavigationController (using the CoreDataTableViewController from Stanford University) with data loaded via Core-Data. The user can check some parameters, set defaults, etc. It works pretty well and the user can also save parameters to the DB and so on.
However this is only a small part of the App I'm building. The App starts with a TabBar controller. The first tab contains a UIViewController and inside this view I want to be able to segue modally the tableViewControllers containing all the core-data stuff.
I believe I've been very careful in setting up the AppDelegate, managedObjectContext and everything else. Obviously, however, I'm missing something because I'm getting the following error when trying to display the modal view :
[UINavigationController setManagedObjectContext:]: unrecognized selector sent to instance...
I've been searching and this is an indication that somehow the managedObjectContext is not being passed.
The code on the applicationDidFinishLaunching is like this:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
RotationVC *rotation=[[tabBarController viewControllers] objectAtIndex:0];
rotation.managedObjectContext=self.managedObjectContext;
and the prepareForSegue on the view contained inside the first Tab is like this:
if ([segue.identifier isEqualToString:#"SetCameraFromRotationSegue"])
{
CameraMakerTVC *cameraMaker = segue.destinationViewController;
cameraMaker.managedObjectContext=self.managedObjectContext;
}
it builds Ok and gives no errors nor warnings.
Could anyone give me a hand on this?. I'd really appreciate it!
Thanks in advance!
Probably the issue is here: the "destinationViewController" in the segue is not the CameraMakerTVC (I guess it's the table view controller) but the UINavigationController that contains it. So when you try to do this:
cameraMaker.managedObjectContext=self.managedObjectContext
infact you're trying to call the setter not on a CameraMakerTVC controller but a UINavigationController. You should try to do this:
UINavigationController *nc = segue.destinationViewController;
CameraMakerTVC *cameraMaker = [nc.viewControllers objectAtIndex:0];
cameraMaker.managedObjectContext=self.managedObjectContext;

Adding a XIB / NIB file to iOS after the fact

So initially I thought I wasn't going to need XIB files and can generate my view programatically with loadView, therefore, when I modeled out my classes, I decided not to create the XIB file.
Now I changed my mind and decided I DO want a xib file to my already created classes. So I previously had an HomeViewController.m/h files. In XCode, I went File--> New--> User Interface--> View, and created an HomeViewController.xib file.
In my App Delegate, I tried doing this:
HomeViewController *home = [[HomeViewController alloc] init];
self.window.rootViewController = home;
I also tried this:
HomeViewController *home = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil];
self.window.rootViewController = home;
In both cases, I get a SIGABRT error. If I DON'T add the home UIViewController to the rootViewController, I get no error, but obviously nothing on screen.
Thoughts?
Most probably your nib objects refer to other class..
In you xib file..in the identity inspector..make sure every object has the class name of HomeViewController .
Hope it helps.
Try just creating the HomeViewController in the XIB and link it in IB. You can tell it to load the view from another XIB within IB there, and also set the default interface file in your project's properties

Resources