Cocoa replaceSubview for nib loaded from storyboard - ios

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.

Related

If I'm using Storyboards and want to present one view atop all my others occasionally, how do I build it?

I have my normal view controller, but once in awhile I'll present something of an options screen atop the view controller. I don't know how to set this up in a Storyboard though, as if I had it on top and then set hidden to true, it would obstruct all the other views and be rather annoying to fiddle around with.
What should I be doing in this case?
You can create the view in a separate XIB file, and then load the view from your view controller programmatically. If this view is showed often you can keep the view in a property, otherwise you can just load it from the XIB every time. To load a view contained in a XIB:
UIView *view = [[[NSBundle mainBundle] loadNibNamed:#"View" owner:self options:nil] firstObject];
[self.view addSubview:rootView];
If this view is something like a settings, I'd recommend to use a separate view controller. You could use a Storyboard and then programmatically add it as a child view controller.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateInitialViewController];
[self addChildViewController:vc];
content.view.frame = self.view; // here you set the frame of your view
content.view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
Are you trying to create a view that is smaller than the view controller?
If that's the case then you can create one programmatically by sub classing UIView.
But if it will cover your entire view controller then you can create a view controller with a .xib file. You can then draw everything on it using IB and then call that view controller morally.

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.

UIViewControllerHierarchyInconsistency when trying to present a modal view controller

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)

IOS Switch view and storyboard not works

I have a problem with switching views. I'm using a simulator with xcode 4.2
Storyboard contains:
NavigationController (initial view controller)
UIViewController which has relationship with the navigation controller
UIViewController (paired with my custom class: ViewEntryImageController) which hasn't got any relationship. Contains a button, a bottom toolbar with some toolbar button.
User come into the UIViewController, where he can see a ScrollView and in ScrollView some images.
Images has a gesture:
UITapGestureRecognizer *recognizer=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(openEntryImage)];
[image addGestureRecognizer:recognizer];
[recognizer release];
The openEntryImage function:
(IBAction)openEntryImage
{
ViewEntryImageController *controller=[[ViewEntryImageController alloc]initWithNibName:nil bundle:nil];
controller.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:controller animated:YES];
[controller release];
}
When I try to tap the image, the openEntryImage works as well (the effect is correct), but I don't see my ViewEntryImageController view and my buttons, I'm only see a black window.
I try to put a NSLog line into the ViewEntryImageController viewDidLoad function, and it works, so what is the black window and where is my view controller?
When I try to use pushViewController, on the new view I found a navigation toolbar with a back button, but no other controls.
I tried another version, I created a UIViewController class, but now with a xib file. I used it instead of ViewEntryImageController and it works. Why?
I want to use this controller in storyboard too.
The ViewEntryImageController class by itself has no information about how to build the dialog. But you can instantiate your view controller on your own from the storyboard:
UIStoryboard *myStoryboard = [UIStoryboard storyboardWithName:#"StoryboardFileName" bundle:nil];
ViewEntryImageController *controller = (ViewEntryImageController *)[myStoryboard instantiateViewControllerWithIdentifier:#"ViewEntryImage"];
This assumes a storyboard name of StoryboardFileName and that the view entry image controller has an identifier of ViewEntryImage set in the view properties (Attributes inspector, section "View Controller").
Try it like this :
ViewEntryImageController *controller=[[ViewEntryImageController alloc]initWithNibName:#"ViewEntryImageController" bundle:nil];
If you don't use .nib names but rather use storyboards, it's a bit harder. Create a segue from the controller to the ViewEntryImageController controller by holding ctrl and dragging from one view to the other. Click this segue and give it an identifier.
Then use the [self performSegue:#"identifier"]; function to present the next view.

Resources