I have a custom customUIViewController in a UISplitViewController and want to access the instance of the customUiViewController from the detailView (which is another UIViewController inside the UISplitViewController) from another class; how can I do this?
CODE SNIP (Dont worry about the syntax; it is shorten up)
myAppDelegate.m
customViewController *masterView = [[customViewController alloc] init;
UINavigationController *NVC = [[UINavigationController alloc] initWithRootViewController:masterView];
MYViewController *detailView = [[MyViewController alloc] init;
UISplitViewController *mySplit = [...];
mySplit.viewControllers = NSArray[...masterview,detailView,nil];
[window addSubView:mySplit view];
MyViewController.m
-(void) someMethod {
customViewController *myInstance = (customViewController)[self.splitViewController objectAtIndex:0]; ??
// I think this just gets the outter UINavigationController
[myInstance doSomething];
}
customViewController.m
-(void) doSomething {
}
I want to be able to get access to customViewController to call the doSomething method. Both customViewController and myViewController is inside the same UISplitViewController
UIViewControllers have a splitViewController property so try using that to get a reference:
customViewController *myInstance =
(customViewController *)[self.splitViewController.viewControllers
objectAtIndex:0];
Index 0 is the left-side view controller in the split view controller.
Edit:
If the left-side view controller is a UINavigationController, then to get the root view controller of that, do this:
UINavigationController *nc =
(UINavigationController *)[self.splitViewController.viewControllers
objectAtIndex:0];
customViewController *myInstance =
(customViewController *)[nc.viewControllers objectAtIndex:0];
If you're working with the default UISplitView that XCode makes, you need to reference the AppDelegate to get the splitView's ivar:
YourAppDelegate *del = (YourAppDelegate *)[[UIApplication sharedApplication]delegate];
UISplitViewController *split = del.splitViewController;
NSArray *vcArray = split.viewControllers;
//left is objectAtIndex:0, right is objectAtIndex:1
Related
I have a storyboard based Single View App;
I have 3 ViewControllers on my Storyboard linked to 3 ViewController classes in the code;
I browse between ViewControllers by doing this:
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
MenuViewController* mainMenu = [sb instantiateViewControllerWithIdentifier:#"vcMainMenu"];
mainMenu.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:mainMenu animated:YES];
Now I need to access different UIcontrols on the applicationWillResignActive from the current active ViewController, I will access different controls depending of the ViewController, I'm trying to accomplish this by doing:
if ([self.window.rootViewController isKindOfClass:[LowProfileViewController class]])
{
NSLog(#"here!");
}
But it always returns the rootViewController. How Can I get the current displayed rootViewController from applicationWillResignActive?
Please, Incorporate NavigationController is not an option...
thanks
You could try this -
Make An AppDelegate #property (i.e. currentModelViewController)
#property (nonatomic, retain) UIViewController *currentModelViewController;
For each ViewControllers in viewDidAppear or in viewWillAppear
appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.currentModelViewController = self;
Now this will work
if ([self.currentModelViewController isKindOfClass:[LowProfileViewController class]])
{
NSLog(#"here!");
}
I first like to load simple viewController which shows some option and then clicking on some button I would like to load navigationController or tabbarController depending on button click. How can I do this ?
I replace the root view controller on the window when I want to switch the views.
For example in my app I show a loading screen first then I switch the view to a login screen.
To do this you need a reference to your app delegate then you can access the window property and replace the root view controller:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
LoginViewController *loginVC = [[LoginViewController alloc] init];
appDelegate.window.rootViewController = loginVC;
In your simpleViewController :
- (IBAction) yourButtonAction:(id)sender
{
UIViewController *Vc = [[theViewControllerYouWantToShow alloc]init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:Vc];
[self presentModalViewController:nav animated:YES];
}
Edit :
you have three options to show your viewController content :
as the example above using presentModalViewController:
add the viewController view as a subView to the current viewController.
in your case : [simpleViewController.view addSubView:nav.view];
3.or if your simple ViewController is the navigation root viewController you can push other viewControllers to its navigation stack.
in appdelegate.h
#property (strong, nonatomic) id<UIApplicationDelegate>delegate;
in appdelgate.m
#synthesize delegate;
in my first viewController's .h file
AppDelegate *myappDelegate;
-(IBAction)start:(id)sender;
in my first viewController's .m file
-(IBAction)start:(id)sender
{
NSLog(#"Start Button is clicked");
mvc = [[MasterViewController alloc]initWithNibName:#"MasterViewController" bundle:nil];
myappDelegate = [[UIApplication sharedApplication]delegate];
myappDelegate.navigationController = [[UINavigationController alloc]initWithRootViewController:mvc];
myappDelegate.window.rootViewController = myappDelegate.navigationController;
[myappDelegate.window makeKeyAndVisible];
}
I want to use a modal view (UIViewController) as a "normal" view, which can be pushed on the navigation controller stack. Normally, a modal view is presented like this:
LoginViewController *myView = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myView];
[self.navigationController presentModalViewController:navController animated:YES];
[myView release];
myView = nil;
[navController release];
navController = nil;
But I want to do something like this:
[[self navigationController] pushViewController:myView animated:YES];
The problem is that my modal view has a right and a left button. So I would have to check how the view is loaded and present the buttons in another way. The idea behind this is to have the back button. So I can use the same modal view a few times.
Edit:
#petert:
Now I followed your example. My issue is that I'm using a UINavigationBar for the modal view. To get this UINavigationBar I create a navigation controller. I'm using the navigation bar because I have my buttons in it. So checking if parentViewController is of type UINavigationController does not work for me. I'm always getting a modal view. Here is how I do it:
// load modal view
MyViewController *myView = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myView];
[[self navigationController] presentModalViewController:navController animated:YES];
[navController release];
navController = nil;
[myView release];
myView = nil;
// load as normal view
MyViewController *myView = [[MyViewController alloc] init];
[[self navigationController] pushViewController:myView animated:YES];
Good tips in this StackOverflow answer.
I prefer to use UIViewController's property:
#property(nonatomic, readonly) UIViewController *parentViewController
in a view controller's subclass:
Look at the value of the controller's parentViewController property. If it's an instance of UINavigationController, then you're in the navigation stack. If you're being displayed modally, it'll be an instance of your last view controller.
So in -viewDidLoad for example:
- (void)viewDidLoad
{
if ([self.parentViewController isKindOfClass:[UINavigationController class]])
{
// navigation controller
self.title = #"...";
}
else
{
// modal
self.title = #"Modal";
// add cancel and done buttons now...
}
}
Or, a pretty simple solution would be to customize your init method to your MyViewController class to encode your intent for the view controller.
Add the following to the MyViewController header:
#interface MyViewController : UIViewController
{
BOOL modal;
}
- (id)initForModal:(BOOL)isModal;
#end
Now in the implementation file:
#interface MyViewController ()
#property (nonatomic) BOOL modal;
#end
#implementation MyViewController
#synthesize modal;
- (id)initForModal:(BOOL)isModal;
{
if (self = [super initWithNibName:#"MyViewController" bundle:nil])
{
self.modal = isModal;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.modal)
{
// add cancel and done buttons …
}
else
{
// assuming we're presented from a navigation view …
}
}
Now to use this modally:
// load modal view
MyViewController *myView = [[MyViewController alloc] initForModal:YES];
Or not modally:
// load as normal view
MyViewController *myView = [[MyViewController alloc] initForModal:NO];
I'm assuming you're creating the view controller(s) from NIBs, but as always see the View Controller Progamming Guide for iOS and especially the section titled "Defining a Custom View Controller Class".
For clarification: myView isn't modal. You just present it as a modal one.
If you just push it into a UINavigationController hierarchy it will behave like a "normal" one.
You can't push the same view controller onto the navigation stack several times. Just once.
Also see this for how to customize the view:
SO modal question
In my subclass of NSObject I would like to call something like
[[self navController] presentModalViewController:myView animated:YES];
But none of my tries were successful. How can I call a modal view if I'm not in a subclass of UIViewController?
Solution:
#import "myProjectNameAppDelegate.h"
// ...
MyViewController *myView = [[MyViewController alloc] init];
myProjectNameAppDelegate *appDelegate = (myProjectNameAppDelegate *)[[UIApplication sharedApplication] delegate];
[[appDelegate navController] presentModalViewController:myView animated:YES];
better way to call a presentModalViewController is, passing viewcontroller to the NSobject class. call the nsobject function from the uiviewcontroller
Here is the code with mail example
In view Controller //your current view
[nsobjectclassObject OpenMailComposer:self]; //this will take the viewcontroller to NSobject class
In NSObject class //may be sharing class
-(void)OpenMailComposer:(UIViewController*)view
{
viewControllertoShow = view; // viewControllertoShow is UIVIewcontroller object
MFMailComposeViewController *mailView = [[MFMailComposeViewController alloc]init];
mailView.mailComposeDelegate = self;
[mailView setSubject:#"Hey! check this out!"];
[viewControllertoShow presentModalViewController:mailView animated:YES];
}
For dismissing from NSObject class you can do the following
[viewControllertoShow dismissViewControllerAnimated:YES]
I don't see a way to display a modal view without a ViewController. You have to store a reference to a UIViewController in your class so you can access it. Or setup a property in your AppDelegate, which you can get by calling [[UIApplication sharedApplication] delegate];
If you hold the navigationController or some viewController, you can present a modal view controller.
What is your myView? Is it a view, is it a viewController. I hope that it is a viewcontroller otherwise, this is the reason your code doesn't run
I have two view controllers name RootViewController and SecondViewController. In the FirstViewController I have this NSMutableArray
#interface RootViewController : UITableViewController {
NSMutableArray *allClasses;}#property (nonatomic,retain) NSMutableArray *allClasses;
In the RootViewController I populate the UITableView with all the objects within allClasses
In my SecondViewController I have
#interface SecondViewController : UIViewController <UITextFieldDelegate,UIPickerViewDelegate> {
NSMutableArray *arrayStrings;}
I have a method that adds new NSStrings to the arrayStrings. My goal is to be able to pass the arrayStrings to the RootViewController by trying something similar to allClasses = arrayStrings. That way when the RootViewController is loaded it can populate with new information.
How would I got about accomplishing that task?
in RootViewController implement
-(void)viewWillAppear:(BOOL)animated
this delegate method. Inside this method
write
self.allClasses = SecondViewControllerObj.arrayStrings;
SecondViewControllerObj is the object of SecondViewController declared in RootViewController as a member and which is used to navigate to that view
like
if(SecondViewControllerObj == nil)
{
SecondViewControllerObj = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
}
[self.navigationController pushViewController:SecondViewControllerObj animated:YES];
You need to have the reference of root view controller in the second view controller. And there you need to set the allclasses to arrayStrings;
In general you can find reference to any view controller pushed into the stack by the following code.
NSArray *viewConts = [[self navigationController] viewControllers];
for(int i=0;i<[viewConts count];i++)
{
if([[viewConts objectAtIndex:i] isKindOfClass:[RootViewController class]]){
RootViewController *rootController = (RootViewController *)[viewConts objectAtIndex:i];
[rootController setAllClasses:arrayStrings];
}
}
Now in the viewWillAppear of RootViewController you need to reload the contents of your view.
Hope this helps.
Thanks,
Madhup