Presenting a UIViewController after local notification - iphone

In application:didFinishLaunchingWithOptions: I initialize a UINavigationController. Later, I add the UINavigationController to the window:
[self.window addSubview:navigationController.view]
This all works fine. Now I added local notifications to my app and when the user responds to one, I would like to present a UIViewController. So I thought I could override application:didReceiveLocalNotification: and in there, use my navigationController:
[navigationController pushViewController:someVC animated:YES];
However, this does not work. I did some debugging and noticed that while navigationController is not nil, navigationController.view has no superview, so I assume it is not being displayed.
So, my question is: where should I push my UIViewController so that it gets displayed?

In your AppDelegate.h add this:
//Under where you have <UIKit/UIKit.h>
extern NSString *localReceived;
In your AppDelegate.m add this:
//All the way on top where you import your viewControllers
NSString *localReceived = #"localReceived";
In your AppDelegate.m in the - (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)localNotification;
method add this:
[[NSNotificationCenter defaultCenter] postNotificationName:localReceived object:self];
Make sure that your viewController is a navigationController
If it's not, do the following -- Add this piece of code to your - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions:
UINavigationController *nvcontrol = [[UINavigationController alloc] initWithRootViewController:viewController];
[window addSubview:nvcontrol.view];
[window makeKeyAndVisible];
Now -- in your viewController.m add this to your -viewDidLoad function
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(localAction) name:localReceived object:nil];
Make a -(void) localAction and in that method add your navigationController code to push to the next View Controller!
Hope that works for you. Works like a charm for me

So here it is, another solution with a different approach. It worked like a charm for me. check it out:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)localNotification{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
CustomViewController *cvc = (CustomViewController *)[storyboard instantiateViewControllerWithIdentifier:#"CustomVC"];
AnotherViewController *avc = (AnotherViewController *)[storyboard instantiateViewControllerWithIdentifier:#"AnotherVC"];
avc.someValue = #"Passing a value"; //Optional
UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
nav.viewControllers = [NSArray arrayWithObjects:cvc,avc, nil];
[(UINavigationController *)self.window.rootViewController popToViewController:avc animated:TRUE];
[[UIApplication sharedApplication] cancelLocalNotification:localNotification];
//Cancel Just for not showing it anymore on the notifications list...
}

Related

Application will enter background -> go to root view menu

I am developing an application which has about 8 views and use navigation controller to navigate through. The first view is a main menu.
What i want is (of each view) to pop to the main view if the user press the home button (App did enter background).
I know the AppDelegate methods applicationDidEnterBackground and applicationWillEnterForeground.
And i know the method popToRootViewControllerAnimated called from the navigation controller.
I have tried to use popToRootViewControllerAnimated in applicationDidEnterBackground.
Like:
[self.window.rootViewController.navigationController popToRootViewControllerAnimated:YES];
But this does not work.
Can you please let me know what is the best option for this job?
i think you try NSNotificationCenter like this:
inside applicationDidEnterBackground and applicationWillEnterForeground put this
[[NSNotificationCenter defaultCenter] postNotificationName:#"popToRoot" object:nil];
and in your rootViewController's viewDidLoad (that always appears on app launch) add this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(popToRootViewControllerAnimated) name:#"popToRoot" object:nil];
Then create a method in your rootViewController:
- (void)popToRootViewControllerAnimated
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
Whenever the application will start first time, NSNotificationCenter will initialize for name popToRoot and prepare a method popToRootViewControllerAnimated for this.
And when application will go to background, NSNotificationCenter will pass a massage #"popToRoot" to rootViewController's popToRootViewControllerAnimated method and viewcontroller will pop to rootview
have you tries it like this :-
[self.navigationController popToRootViewControllerAnimated:YES];
replace your navigationController name with navigationController here.
Edit:-
in AppDelegate.h file
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UINavigationController *navMain;
}
#property (nonatomic, retain) UINavigationController *navMain;
in AppDelegate.m file
#synthesize navMain;
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil] autorelease];
self.navMain = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navMain;
[self.window makeKeyAndVisible];
return YES;
}
-(void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"applicationDidEnterBackground");
[self.navMain popToRootViewControllerAnimated:YES];
}
try edited anwser
crate a propery for UINavigationController in your AppDelegate class. In applicationDidEnterBackground: method call the popToRootViewController method by using the UINavigationController Property. For Suppose your propery name is navigationController then
[self.navigationController popToRootViewControllerAnimated:YES];
First: you should check wether the rootviewcontroller is a navigationController. Because self.window.rootViewController.navigationController is often nil.
Why?
Because the navigationController of a navigationController is 'nil'. Mostly, I set my rootViewController to be a navigationController
Secondly:
You shouldn't do animated stuff when your application is about to quit. You should do it not-animated
popToRootViewControllerAnimated:NO

xcode pushviewcontroller with custom init data

I am pushing viewControllerB from A as,
if(!self.controller2){
self.controller2 = [[viewControllerB alloc] initWithNibName:#"viewControllerB" bundle:nil anUser:self.idUser aidioma:self.idioma];
}
[[self navigationController] pushViewController:self.controller2 animated:NO];
Then, I pop B to A. Now need to push A again but initializing again B or calling function on B in order to pass new vars. Following options could be valid but I've got no success,
Release controller2 and = nil, but IF sentence is not executed because controller2 still active!
Call function on viewControllerB in order to pass new pars without init but function is not called.
What am doing wrong? Thanks.
The following code ensures that every time you navigate from A -> B -> A (via the Nav Controller's back button) -> B, B's init method is called every time (I'm using ARC here... if you aren't, let me know and I'll edit the example):
AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
viewControllerA *vcA = [[viewControllerA alloc] initWithNibName:#"viewControllerA" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vcA];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
}
viewControllerA's button action method:
- (IBAction)moveForward:(id)sender {
// change this line to call your custom init method.
viewControllerB *vc = [[viewControllerB alloc] initWithNibName:#"viewControllerB" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
}
Try to Use NSNotificationCenter check this Link which Describes it Properly.
Send and receive messages through NSNotificationCenter in Objective-C?
use This Code in your Class A viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveTestNotification:)
name:#"TestNotification"
object:nil];
Use the following Code in your Class B pop function.
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:self];

How to I connect Button Action to Tabbar Viewcontrollers

I am new to iPhone development. I am developing a TabBarViewcontroller App (iPhone and iPad) and in that I've created one LoginViewController and a Button Action.
My expectation is after clicking that Button, the control will move from LoginViewController to TabBarViewController. In this TabBarViewcontroller I have 5 Tabbar (items) ViewControllers.
Is it possible?
If you can, please share your ideas.
First of all, take UINavigationController and UITabbarController in your MainWindow.xib and bind IBOutlet to respective fields.. ans set LoginViewController as rootViewController of your UINavigationController..
Then in didFinishLaunchingWithOptions method write this..
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.window setRootViewController:navController];
[self.window makeKeyAndVisible];
return YES;
}
Now create other method in AppDelegate.m like this..
-(void)loadApplication
{
[navController pushViewController:tabbarController animated:NO];
}
On your Login button action.. call this method as follows..
-(IBAction)btnLoginTapped:(id)sender
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate loadApplication];
}
So in button action try following codes
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = tabBarController;
use this method to add tabbar from any other view..
-(void)addTabBarControllerInwindow
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.window cache:YES];
[self.navigationController.view removeFromSuperview];
[self.window addSubview:tabBarController.view];
[UIView commitAnimations];
}
put this method in AppDelegate.m file and in any viewController e.g. in LoginView Controller
when you want to add tabbar then declare object of delegate and call this method like bellow..
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate addTabBarControllerInwindow];
I think you might be looking for multiple VC in a single project. So declare and initialise a VC for loginVC and otherVCs(for tabbar) in appDelegate and after login successful call the following function.
On launch make LoginVC as RootViewController
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{// declare LoginVC and make it rootViewController
self.window.rootViewController = self._loginVCObj;
[self.window makeKeyAndVisible];
}
#pragma mark- Continue to next screen after successful Login
-(void) continueToNextView
{ // Handle UI after Login like.
[_loginVCObj._indicator stopAnimating];
[_loginVCObj._loginButton setEnabled:YES];
//add the VC to the tabbar
self._tabBarController.viewControllers = [NSArray arrayWithObjects:self.navigationControllerList,_favItemListNavObj, _toDoHereVC, _settingNavObj, nil];
// make tabbar as rootViewController
self.window.rootViewController = self._tabBarController;
}

How to launch view controller from alarm notification action in iOS?

In my app i am using alarm functionality. It working fine. When i click the right button it launches my app. But i want to launch View Controller which is not an rootViewController. I am tried in searching in Google and SO but i couldn't get any idea or example.
I am looking for any example to achieve this.?
Thanks for your help guys.
EDIT
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Add the view controller's view to the window and display.
[self.window addSubview:alarmViewController.view];
[self.window makeKeyAndVisible];
application.applicationIconBadgeNumber = 0;
// Handle launching from a notification
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) {
NSLog(#"Recieved Notification %#",localNotif);
window = [[UIApplication sharedApplication] keyWindow];
UIViewController *rootViewController = [window rootViewController];
[rootViewController presentModalViewController:receipeViewController animated:YES];
}
// Override point for customization after application launch.
return YES;
}
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
// Handle the notificaton when the app is running
NSLog(#"Recieved Notification %#",notif);
//Called here as well
window = [[UIApplication sharedApplication] keyWindow];
UIViewController *rootViewController = [window rootViewController];
[rootViewController presentModalViewController:receipeViewController animated:YES];
}
Finally Here's how I did it.
In didFinishLaunchingWithOptions:
//save the root view controller
[[self window] makeKeyAndVisible];
UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController;
rootController = [[navigationController viewControllers] objectAtIndex:0];
Somewhere else in the app delegate:
[rootController performSegueWithIdentifier:#"destinationSegue" sender:self];
Then, in the storyboard, create a segue from the view that gets assigned to "rootController" to the desired optional view, and give that new segue the id destinationSegue. It takes some debugging to make sure the rootController variable gets assigned to the correct view.
You do not need to create a segue.You only need to assign an id in the storyboard for the ViewController.
[[self window] makeKeyAndVisible];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LensOverviewViewController *editLensViewController = [storyboard instantiateViewControllerWithIdentifier:#"lensOverView"];
UINavigationController *yourViewController = [[UINavigationController alloc] initWithRootViewController:editLensViewController];
[self.window.rootViewController presentViewController:yourViewController animated:NO completion:nil];
Normally [[self window] makeKeyAndVisible]; does not reside in the didFinishLaunchingWithOptions function but it needs to be called explicity to make the rootviewcontroller visible.
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIViewcontroller *rootViewController = [window rootViewController];
[rootViewController presentModalViewController:alarmViewController animated:YES];
When your application is launched, look for the UIApplicationLaunchOptionsLocalNotificationKey on the launchOptions dictionary on the following method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
This will let you know if your application is being launched because of a local notification (the one you use for the alarm).
You can also do something similar on:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
Once you determine that you actually received a notification, just find the root view controller from the window and present the view controller you want to present modally.

Navigation to another view in iphone

here is my code , i am trying to get from one view to another without any memory leaks.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
firstviewcontroller *first = [[firstviewcontroller alloc] init];
[window addSubview:first.view];
[self.window makeKeyAndVisible];
return YES;
}
-(IBAction)gotosecondview:(id)sender
{
secondviewcontroller *second = [[secondviewcontroller alloc] init];
[self.view addSubview:second.view];
[second release];
}
-(IBAction)gotofirstview:(id)sender
{
[self.view removeFromSuperview];
}
to make the above code work without crashing , all i have to do is remove [second release].
if I remove it I get memory errors (build and analyze) . how can i solve this problem. and i dont want to use [self.navigationController pushViewController:second animated:YES];
all i am trying to do i navigating from one view to another and vice versa WITHOUT using navigation controller. my firstviewcontroller and secondviewcontroller are of type UIViewController.
Thanks in advance.
You need to keep the current view controller alive while its view is showing (so it can process the user input, etc.).
In your code, you can achieve that in several ways:
Keep an instance of firstviewcontroller and secondviewcontroller as instance variables, and release them on the dealloc method.
Keep an instance variable with the currently in use UIViewController and release it when you switch to another view.
The code for the second option would look something like this:
#interface
UIViewController *currentViewController;
#end
#implementation
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
firstviewcontroller *first = [[[firstviewcontroller alloc] init] autorelease];
[self switchToViewController:first];
[self.window makeKeyAndVisible];
return YES;
}
- (void)switchToViewController:(UIViewController *)aViewController {
[currentViewController.view removeFromSuperview];
[currentViewController release];
currentViewController = [aViewController retain];
[self.window addSubview:currentViewController.view];
}
-(IBAction)gotosecondview:(id)sender {
[self switchToViewController:[[[secondviewcontroller alloc] init] autorelease]];
}
#end
Here, all the logic for maintaining a single UIViewController alive lies in the switchToViewController method, which also handles the logic for switching from one view to another. As an added bonus, you can quickly add support for animations by adding a couple of lines in switchToViewController.
You can not release view in the call.
There is only one thing you can do in such conditions. use Autorelease,
The reason [second release] is crashing your code is likely because you're releasing your view controller which in turn releases the second view. The iPhone cookbook has some sample code on switching/swapping views if that's all that you're trying to accomplish. Here's the link. Hope this helps!
link text