UIViewControllerHierarchyInconsistency when trying to present a modal view controller - ios

Trying to present a modal view controller with the following code
MapViewController *mapView = [[MapViewController alloc] initWithNibName:#"MapViewController" bundle:nil];
mapView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController presentModalViewController:mapView animated:YES];
[mapView release];
Keep getting the following error..
'UIViewControllerHierarchyInconsistency', reason: 'A view can only be associated with at most one view controller at a time! View <UIView: 0x1ed815a0; frame = (0 20; 320 460); autoresize = W+H; layer = <CALayer: 0x1ed81600>> is associated with <UIViewController: 0x1ed835a0>. Clear this association before associating this view with <MapViewController: 0x1dd947c0>.'
This is an old project that I havent touched in months, wonder what could cause such an error?

This happened to me already twice in the newest Xcode release.
In both cases I needed to make changes to the UIViewController's XIB file (In you case it would be MapViewController.xib:
BEFORE:
Move main View out of View Controller's children:
Remove View Controller from the XIB (it is not necessary since File's Owner should be of its Class already):
AFTER:

I had this problem when running Apple's example audio app MixerHost on the iOS 6 simulator.
The equivalent of the above fix, namely to edit the supplied MixerHostViewController.xib by dragging the View object to the top level, and discarding the now-empty ViewController that used to contain it, worked perfectly (though not before I'd spent hours working out what the underlying problem was, so I'm feeling done-over by Apple at the moment - seems they tightened something up but didn't bother to check if it broke their sample apps).

I had this problem when my Nib had a UIViewController in the file at top level. So loading from Nib created that UIViewController, then I tried to use it from my class, which was in the position of MapViewController in your code.
In my case the solution was simply to remove the UIViewController from my Nib file.

You should do it like this..
MapViewController *mapView = [[MapViewController alloc] initWithNibName:#"MapViewController" bundle:nil];
UINavigationController *navCntrlr = [[UINavigationController alloc] initWithRootViewController:mapView];
mapView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
//hide navigation bar if needed
[self.navigationController presentModalViewController:navCntrlr animated:YES];
[mapView release];

Maybe in some cases it is better to take another approach and not delete the UIViewController from the NIB, because, for one thing, by removing the view controller from the NIB's hierarchy, you lose the Auto Layout margins.
Why not just leave the UIViewController in your nib (.xib) and create an outlet for it in the file owner class? Then, rather than instantiate the view controller directly in you code, load the nib with the UINib class, and, at the optimal time (from the memory/resource usage standpoint), invoke the nib instance's instantiateWithOwner() method to unarchive NIB and connect the nib objects to the owner class's outlets.
#IBOutlet var myViewController: myViewController?
var nib : UINib?
nib = UINib(nibName: "TheNib", bundle: nil)
if (nib == nil) {
println("could not load nib: TheNib.xib")
}
nib!.instantiateWithOwner(self, options: nil)

Related

Cocoa replaceSubview for nib loaded from storyboard

I've got a .storyboard that loads a .nib into it's view controller using:
NSViewController* vc = [[otherView alloc] initWithNibName:#"otherView" bundle:nil];
[[[self window] contentView] addSubView:[vc view]];
This works fine for loading in the initial NSView, however, the .nib contains several other views I would like to be able to replace with a different view when a button is clicked.
How do I specify which view in the .nib I would like to replace with another?
You have to connect other view as outlet to the NSViewController and you can call replace.

Xcode 6 subclasses

I want to put a view controller inside a scroll view.
I think I can do it with something like:
MyViewController *vc = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
[scrollView addSubview:vc];
What I don't understand is how to specify my nib name correctly, because I have an interface built which I want to use but it is one of multiple views appearing in my main storyboard.
You cannot add a viewController as a subview. You can add a childViewController and the viewController's view as a subview. But you should probably read up more on how Objective-C and iOS works.

UIView in nib not connecting to IBOutlets

I am adding on screen a UIView in this way:
ViewController2 *detailViewController = [[ViewController2 alloc] initWithNibName:#"MJDetailViewController" bundle:nil];
[self presentPopupViewController:detailViewController animationType:MJPopupViewAnimationFade];
since MJDetailViewController is a nib and holds a UIView, I have created a custom class of UIView and selected it as class for the view in the inspector. When the window is loaded, the UIButtons do actions in the class that has been created, but the IBOutlets don't work. Even if I decided to add a UIButton programmably, it doesn't appear on screen. Why is this?
I thought of changing the UIView to a UIViewController, but it won't work because you can't present it with an animation.
I suspect you haven't set up the nib objects correctly.
In addition to setting the class of your UIView subclass you need to configure the 'File's Owner' and connect the views to it. You do this by selecting the file owner and setting its' class (this is done the same as setting the view's class). In your case the class of the file owner should be ViewController2.
Hopefully this screenshot explains this better:
Also you can simplify things a bit by using UIViewController nib naming conventions. If you give your nib the same file name as the view controller then you can specify nil as the nibName:. For example, if you name your nib ViewController2.xib then you can do this:
ViewController2 *detailViewController = [[ViewController2 alloc] initWithNibName:nil bundle:nil];
This approach is preferable as it means that the nib filename becomes an implementation details which calling code does not need to know about.

How to get actions from another UIViewController?

How to get actions from another controller without [self presentModalViewController: ololo animated:YES];?
Can I use just
Tutorial *ololo = [[Tutorial alloc] initWithNibName:nil bundle:nil];
[self.view addSubview:ololo.view];
?
Right now with this code I get EXC BAD ACCESS error, when I'm trying to press button on new view.
May it will be easier to create 2 subclasses of UIView with their own XIBs, or may be I can use NavigateController without navigation bar?
PS Yes, I have Tutorial.h, Tutorial.m, Tutorial.xib. In XIB file there are 2 views (portrait and landscape).
Your question is not clear.
try to pass xibf file name as parameter to initWithNibName,ekse just use int method.hope it wont crash
Make sure that your Tutorial object extends UIViewController
#interface Tutorial : UIViewController {
Also make sure that you have a Tutorial.xib file, which has a view, and the outlet from the view it's linked with the one from the viewcontroller.
as a best practice try this :
Tutorial *ololo = [[[Tutorial alloc] initWithNibName:#"Tutorial" bundle:nil] autorelease];
[self.view addSubview:ololo.view];
Also, if you need 2 views in the same view controller, you can just add 2 views in IB, add an outlet to the second one, and add it as a subview of the main one :
[self.view addSubview:secondView]
this way, both of them are managed by the same viewcontroller, and you can add actions in the same view controller.

Presenting a UIViewController from inside another UIViewController?

I'm pretty new to iOS, and am attempting to present a view controller from within another view controller as described here:
Stack overflow answer (see third answer)
and also here on Apple's site
I start with the Hello World Example code. I open up MyViewController.m and modify the updateString() method, adding this code to the end:
{
// Get the application's "window"
UIWindow *window = [UIApplication sharedApplication].keyWindow;
// Get the window's rootViewController (NOTE: Only works on iOS 4.0 or later!)
UIViewController *rootViewController = window.rootViewController;
// Create our new controller
UIViewController *enterNameController = [[UIViewController alloc] initWithNibName:#"HighScore" bundle:[NSBundle mainBundle]];
if (enterNameController != NULL)
{
printf("\nLoaded UIView controller. Installing as actionSheetController...\n\n");
UINavigationController *navigationController = [[UINavigationController alloc]
initWithRootViewController:enterNameController];
// Present out Enter Name for High Score view as a modal view
// [rootViewController presentViewController:navigationController animated:YES]; // iOS 2.0 and newer
[self presentViewController:navigationController animated:YES completion: nil]; // iOS 5.0 and newer
}
}
I have also created a NIB file called "HighScore.xib" that I put with the other NIB files that came with the HelloWorld, and I also added HighScore.xib to the XCode project, and dragged it into the "Copy Bundle Resources" section.
As-is, I get an error when running and entering text into the edit field:
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle (loaded)' with name 'HighScore''
However if I change the final statement to use "rootViewController" instead of "self" then nothing happens. No exception, but no new view is presented either.
Questions:
1) Why won't my NIB load? I'm obviously doing something wrong here.
2) Why does using "rootViewController" instead of "self" produce different results? Shouldn't the rootViewController find the same class as "self"?
Note that when using "rootViewController" I get a warning in XCode: "MyViewController' may not respond to '-presentViewController:animated:completion"
I solved this problem by:
a) Using the tutorial here:
http://timneill.net/2010/09/modal-view-controller-example-part-1/
b) Right-clicking and doing "Get Info" on the .xib file in the XCode project, and modifying its Type to be "file.xib" instead of "sourcecode.xib". Without this second change, it would not load! Bizarre. But this was ultimately the problem!!

Resources