i have three view controller with three different XIB, let's say ViewControllerA, ViewControllerB and ViewControllerC and every view controller has UIView variable named view in it's property. so it would be something like this :
#property (readwrite, retain) UIView *view;
first, scene ViewControllerA loaded, then after i touched a button scene of ViewControllerB appears. but i deliberately not removing UIView of ViewControllerA from super view.
Then after i touched a button the scene navigate to ViewControllerC. here, before navigate to ViewControllerC i want remove UIView both of ViewControllerA and ViewControllerB from super view
removing UIView of ViewControllerB is not a problem, i can do something like this in ViewControllerB method :
[self.view removeFromSuperview];
but how can i remove UIView of ViewControllerA?
thanks
If you want totally independent of each other view controllers, you could switch them in appDelegate.window.rootViewController. Only create variable appDelegate that points to UIApplication.
And handle the animations by yourself.
Example:
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
UIViewController *controller1 = [ViewControllerA alloc] initWithNibName:#"ViewControllerA" bundle:nil];
UIViewController *controller2 = [ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:nil];
appDelegate.window.rootViewController = controller1;
appDelegate.window.rootViewController = controller2;
Related
I'm having some difficulty managing a segue. My view controller hierarchy is as follows:
BHGSplitViewController (subclass of UISplitViewController)
UINavigationController
MasterViewController (subclass of UITableViewController)
UINavigationController
DetailViewController (subclass of UIViewController)
These have the following properties:
BHGSplitViewController:
#interface BHGSplitViewController : UISplitViewController
#property (nonatomic, strong) MasterViewController* masterVC;
#end
MasterViewController:
#interface MasterViewController : UITableViewController
#property (strong, nonatomic) MenuDataSource *menuDataSource;
#property (strong, nonatomic) DetailViewController *detailViewController;
#end
DetailViewController:
#interface DetailViewController : UIViewController
#property (strong, nonatomic) NSURL* URL;
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#end
These are related in my main storyboard through relationship segues.
After the initial app launch, I modally display a login view controller. After login, I segue back to my BHGSplitViewController, but I need to set some data. In the loginViewController's prepareForSegue method I attempt the following:
BHGSplitViewController *splitVC = [segue destinationViewController];
splitVC.masterVC.menuDataSource.var = someValue;
But, when debugging, splitVC.masterVC = nil, so obviously attempting to set a value on it is not going to work. How do I set-up and retain those relationships?
I inherited a version of this app that was built with storyboards. I'm guessing that I need to start intializing these properties. What's the best way to do that with storyboards? Do I need to override initWithCoder:? Should I be setting these properties in viewDidLoad?
Edit: Explanation of segue
So, I'm loading up my BHGSplitViewController in my AppDelegate and setting it up to handle collapses, etc. After that, I need to immediately display a modal view for login. I need this to animate in like a push (but Apple won't allow that), so I'm trying to hack my way around that by using a custom segue (which is hacky and I hate it):
Present Segue:
- (void)perform {
UIViewController *srcViewController = (UIViewController *) self.sourceViewController;
UIViewController *destViewController = (UIViewController *) self.destinationViewController;
UIView *prevView = srcViewController.view;
UIView *destView = destViewController.view;
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
[window insertSubview:destView aboveSubview:prevView];
[destView enterLeft:0.1 then:^{
[srcViewController presentViewController:destViewController animated:NO completion:nil];
}];
}
Dismiss Segue:
- (void)perform {
UIViewController *srcViewController = (UIViewController *) self.sourceViewController;
UIViewController *destViewController = self.destinationViewController;
UIView *prevView = srcViewController.view;
UIView *destView = destViewController.view;
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
[window insertSubview:destView aboveSubview:prevView];
[destView enterRight:0.1 then:^{
[srcViewController presentViewController:destViewController animated:NO completion:nil];
}];
}
You can set the properties in viewDidLoad. initWithCoder is definitely too early since the split view controller is instantiated first, and then the other controllers it houses. So, you can do this in viewDidLoad of BHGSplitViewController,
-(void)viewDidLoad {
[super viewDidLoad];
UINavigationController *nav = (UINavigationController *)self.viewControllers.firstObject;
self.masterVC = (MasterViewController *)nav.topViewController;
}
My detailviewcontroller is called myDetailVC , with tableVC which is just a table on the side of myDetailVC.
in myDetailVC, I have a button that is supposed to show a popoverviewcontroller. However, it crashes when I press it.
in my .h file:
#property (strong, nonatomic) UIPopoverController *masterPopOverController;
and .m:
- (IBAction)goToPDF:(id)sender
{
viewPDFViewController *MPPWV =[[viewPDFViewController alloc] initWithNibName:nil bundle:nil];
self.masterPopOverController = [[UIPopoverController alloc] initWithContentViewController:MPPWV];
[self.masterPopOverController presentPopoverFromRect:[sender frame] inView:[sender superview] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[self.masterPopOverController setPopoverContentSize:CGSizeMake(100, 100) animated:NO];
}
Everything is connected fine in my xib, since I tested it by making it push to a viewcontroller instead of a popover. Can someone help me with this?
First, it looks like you're loading it up with a view controller that doesn't have anything in it:
viewPDFViewController *MPPWV =[[viewPDFViewController alloc] initWithNibName:nil bundle:nil];
Try specifying a Nib name, if you have one. It's possible that you don't have a NIB for that view controller. If that's the case you probably have a designated initializer -init method that you should be calling on it. Do that instead of calling -initWithNibName:
Second, it doesn't look like you're retaining the view controller you're loading into the pop over. It's possible that they require strong references. Try retaining it via property (or an ivar):
#property (nonatomic, strong) viewPDFViewController * MMPPWV;
Then when you access it do so via self:
self.MPPWV = [[viewPDFViewController alloc] initWithNibName:nil bundle:nil];
I have a button that open another viewController(familyView) when clicked.
In familyView there is another button which suppose to bring me back to the mainViewController(ViewController.xib) but I don't know how to call the main viewController.
My method to call familyView
UIViewController* familyView = [[UIViewController alloc] initWithNibName:#"familyView" bundle:[NSBundle mainBundle]];
[self.view addSubview:familyView.view];
I hope you could help on how to call the main ViewController ? do I have to use the same method to call it? like this I mean:
UIViewController* mainView = [[UIViewController alloc] initWithNibName:#"viewController" bundle:[NSBundle mainBundle]];
[self.view addSubview:mainView.view];
If yes, is there a better way to implement this? in my demo project, I'm trying to make 7 views full with data and a button to go back and forth.
EDIT:
If I use UIView would that be best for me instead of using different viewControllers with their implementations and interfaces files?
My project will have views, and each view has data on it parsed from a different html page.
There are two method that can be used.
UINavigationController
Delegates
From your question it seems that a UINavigationController is the best option but I will show you both.
UINavigationController
When you load your mainViewController from your app delegate your going to need to wrap it in a nav controller like so:
AppDelegate.h
#property (strong, nonatomic) UINavigationController *navController;
AppDelegate.m
#synthesize navController = _navController;
//in didFinishLaunchingWithOptions:
UIViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.window.rootViewController = nav1;
[self.window makeKeyAndVisible];
Now in your MainViewController you have the convince of UINavigationController.
When you want to push to a child from a parent you can simply do:
ChildViewController *child = [[ChildViewController alloc]...];
[self.navigationController pushViewController:child animated:YES];
If you in your ChildViewController and want to go back simply do:
[self.navigationController popViewControllerAnimated:YES];
This is the "Drill Down" technique.
(I know "Drill Down" has more meaning than simply that but it provides a good frame of reference.)
Delegate
Now the other method that you have is to setup delegates between the classes. So if your in childView and need to call your parent, you will have a channel to do so.
In your MainViewController.h setup it like so:
#import <UIKit/UIKit.h>
//This is our delegate
#protocol TalkToParentDelegate <NSObject>
//This is our delegate method
- (void)helloParent;
#end
#interface MainViewController : UIViewController <TalkToParentDelegate>
...
..
#end
In your MainViewController.m make sure add the delegate method.
- (void)helloParent {
NSLog(#"Hello child, let me do something here");
}
In your ChildViewController.h setup it like so:
#import <UIKit/UIKit.h>
//Add header of class where protocol was defined
#import "MainViewController.h"
#interface ChildViewController : UIViewController
//Create a property we can set to reference back to our parent
#property (strong, nonatomic) id <TalkToParentDelegate> delegate;
#end
Now, in your MainViewController.m , whenever you present your ChildViewController do this:
ChildViewController *child = [[ChildViewController alloc]...];
//Set the delegate reference to parent
child.delegate = self;
//present the view
Last but not least, no when you in your child you can call methods on your parent (MainViewController) like so:
[self.delegate helloParent];
So here are two methods that you can use.
I would like to note however, you can use these together. Say you had a UINavigationController but still needed a child to talk to its parent, you can setup a delegate so that's possible.
Hope this helps.
How do you add a navigation controller on a newly created view controller? i've search everywhere but all the tutorials are from creating a navigation controller project.
Anyone can lead mo to a tutorial that creates a navigation controller using a view controller subclass?
What i'm doing so far:
I created a UIViewController Project, and i have something like this to go to another view controller, with a navigation controller.
NavController *view=[[NavController alloc] initWithNibName:nil bundle:nil];
view.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:view animated:YES];
[view release];
Added a new view controller subclass.
Add > New File > UIViewController subclass with nib
on NavController.h
#import <UIKit/UIKit.h>
#interface NavController : UIViewController {
IBOutlet UIWindow *window;
IBOutlet UINavigationController *navCon;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) UINavigationController *navCon;
#end
on NavController.m
#import "NavController.h"
#implementation NavController
#synthesize window,navCon;
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[window release];
[navCon release];
[super dealloc];
}
#end
i already dragged a Navigation Conrtoller and a Window on my IB, and connected window to window and the Navigation Controller to navcon outlets, but whats next?
If you're using the storyboards select your view controller then in top menu choose "editor" / "embed in" / "navigation controller".
Normally, you have to create an Navigationcontroller object inside your Appdelegate.h (like the existing window object). After that you import the h.File of a ViewController into the Appdelegate.m and init it like in the following example the menuviewcontroller.
stackoverflow
To call another view use following lines of code, so the navigationcontroller will handle everything for you.
#import Viewcontroller
ViewControllerName controllerVarName = [ViewControllerName alloc] init];
[self.navigationcontroller pushViewController:_ViewControllerName animated:YES];
Inside your specific ViewController use this line to set the title the Navigationcontroller will use:
self.title = #"titleName";
I have a view controller, MainViewController in which I have a UIButton as an IBOutlet that is connected up in Interface Builder
In the header I have
#interface MainViewController : UIViewController
{
SettingsViewController *settingsViewController;
UIButton *leftTextButton;
}
#property (nonatomic, retain) IBOutlet UIButton *leftTextButton;
in the .m I have synthesised the property
#synthesize leftTextButton;
I then add a settings subview as follows
SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController"
bundle:nil];
[self.view.superview addSubview:settingsViewController.view];
Within the SettingsViewController I then try to update the title of the UIButton *leftTextButton in the parent view
[ ((MainViewController*) self.parentViewController).leftTextButton setTitle:#"Ahhhhh !!" forState:UIControlStateNormal];
Although this doesn't crash it doesn't work - the title of the button does not change.
Any help would be greatly appreciated
The parentViewController property is nil unless the view controller is presented modally, or is under a UINavigationController or a UITabBarController.
Give your SettingsViewController a mainViewController property:
#interface SettingsViewController
...
#property (assign) MainViewController *mainViewController;
Set it when you create the SettingsViewController:
SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
settingsViewController.mainViewController = self;
Then you can use it to update the button title:
[self.mainViewController.leftTextButton setTitle:#"Ahhhhh !!" forState:UIControlStateNormal];
If you just add the view controller's view in the parent view, the view controller will have no idea of its parent view controller, thus the parentViewController property is nil. You also have to add your SettingsViewController to your MainViewController via addChildViewController: and then notify the SettingsViewController via didMoveToParentViewController: that you have created this hierarchy. Then you should be able to access the parentViewController.
(Note: this is for iOS 5 only, if you're still on iOS 4 see rob mayoff's reply)