iPhone didFinishLaunchingWithOptions Method - iphone

So i'm trying to use this method to load a certain theme based on what the user chose in the settings bundle. When I insert NSLog it will load the default them (Modern Theme), but it will never change to the Pink Theme.
Is this method loaded every time the app is launched, even if the app is still running in the background.
Otherwise, where else could I do this, if I want to use the settings bundle.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *userDefaultsDefaults = [NSDictionary dictionaryWithObjectsAndKeys: #"Modern Theme", #"theme", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsDefaults];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
theme =[defaults objectForKey:#"theme"];
NSLog(#"%#", theme);
if ([theme isEqualToString:#"Modern Theme"]) {
viewController = [[viewTwo alloc] initWithNibName:#"viewTwo" bundle:nil];
}
else {
viewController = [[viewOne alloc] initWithNibName:#"viewOne" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

Have you tried putting your code in applicationDidBecomeActive:? That one is guaranteed to be called whether on the initial launch or resuming from the background.
Reference docs.

The method
- (void)applicationWillResignActive:(UIApplication *)application
is fired when the app is resumed from the background.
I'd nearly load the theme in the ViewController's
-(void)viewDidAppear:(BOOL)animated
method.

Related

Root View Controller not changing on BOOL

I am trying to change the Root View controller if the application has been opened once. Here is what im doing. The boolean is fully functional and i know because it prints 'Welcome Back'. Here is what im trying to do.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
// App Already launched
RootMenuController *viewController = [[RootMenuController alloc] init];
[UIApplication sharedApplication].keyWindow.rootViewController = viewController;
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
// This is the first launch ever
}
[self.window makeKeyAndVisible];
return YES;
}
It seems like you are not setting/updating application window properly. I have created an sample project which might help. https://github.com/deepthit/UpdateRootViewController.git

iOS : is it possible to open previous viewController after crashing and re-launch app?

How to achieve this stuff below? Please give me some guidance for it. I describe my issue below.
When I tap home button and remove app from tray and while I am opening app I get the login screen. I know how to use NSUserDefaults well.
But my issue is that when I navigate 3rd or 4th viewController and I press Home Button and remove app from tray, Then whenever I open app than I want to open with last open viewController.
Also same when my app is Crashing and I am opening it again then I want to open app with last open viewController state.
So I just want to know that is that possible or not? If yes, then please guide me how to achieve this stuff.
Thank you
Yes, both cases are possible.
On crash, you can use UncaughtExceptionHandler to perform some code. In you app delegate, register you handler like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// Other didFinishLaunchingWithOptions code
And add your handler method to the same .m file
void uncaughtExceptionHandler(NSException *exception)
{
// App crashed, save last selected tabbar index to the to the NSUserDefaults
[[NSUserDefaults standardUserDefaults] setInteger:tabBarController.selectedIndex forKey:#"LastSelectedTabbarIndex"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
While app runs, to keep track of last selected tab bar controller, use UITabBarControllerDelegate and save newly selected tabbar's index to NSUserDefaults. Short example:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
NSUInteger tabIndex = [[tabBarController viewControllers] indexOfObject:viewController];
// I have newly selected index, now save it to the NSUserDefaults
}
This code will save last selected tabbar's index to the NSUserDefaults every time tabbar's selected index changes.
Finally, when you app starts (in your didFinishLaunchingWithOptions), read last saved tabbar index from NSUserDefaults and set tabbar's selected index accordingly
self.tabBarController.selectedIndex = lastSelectedIndexFromDefaults;
Edit:
If you also need to restore UINavigationControllers controllers stack, its pretty difficult task. I give you just a quick overview what comes to my mind.
There are 2 cases:
You have custom view controllers initializers and need to pass custom object to those controllers - In this case, its almost impossible (in some reasonable time) implement this
You use only -init or -initWithNibName...: to initialize view controllers in navigation stack. You could enumerate controllers from the root UINavigationController of the tab, get their classes names using NSStringFromClass and save them to NSUserDefaults. On apps start, you would reverse procedure (initialize controllers using their names strings read from NSUserDefaults using something like this: UIViewController *vc = [[NSClassFromString(#"aa") alloc] init];).
I understand you are ok with the code part so i will just give my suggestion
on viewDidLoad of every view controller set a nsuserdefault value of the top most object on navigation array.
if their are not too many branches then you can manage the push at root view controller easily
This is not the proper answer but you can use it for Navigating view after launching.
In AppDelegate file use below codes:---
#import "NewSAppDelegate.h"
#import "NewSViewController.h"
static NewSAppDelegate *globalSelf;
#implementation NewSAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[NewSViewController alloc] initWithNibName:#"NewSViewController" bundle:nil];
self.navController=[[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
globalSelf=self;
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
return YES;
}
void uncaughtExceptionHandler(NSException *exception)
{
UIViewController *currentVC = globalSelf.navController.visibleViewController;
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromClass(currentVC.class) forKey:#"lastVC"];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIViewController *currentVC = self.navController.visibleViewController;
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromClass(currentVC.class) forKey:#"lastVC"];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"appDidBecomeActive" object:nil];
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
In your login viewController's init method add an observer for notification and in notification method , you can apply if conditions for viewController's name received.and push to that viewController on launching LoginView controller as:---
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(openLastVC)
name:#"appDidBecomeActive"
object:nil];
// Custom initialization
}
return self;
}
-(void)openLastVC
{
NSLog(#"val ==%#",[[NSUserDefaults standardUserDefaults] valueForKey:#"lastVC"]);
if ([[[NSUserDefaults standardUserDefaults] valueForKey:#"lastVC"] isEqualToString:#"GhachakViewController"]) {
GhachakViewController *gvc=[[GhachakViewController alloc] initWithNibName:#"GhachakViewController" bundle:nil];
[self.navigationController pushViewController:gvc animated:NO];
}
}
May this help you....

App crashes when didFinishLaunchingWithOptions is called

I have an the app when notification is fired i get a notification bar when the app is in background ,when i tap on that bar it navigates into tableview of the notification set . When i quit the app from background i am receiving notification but when tap on the notification bar the app is getting crashed since its not getting indexpath of the tableview.
When the app is quit in background and reloading the app should enter didfinishlaunching.
In appDidFinishLaunching i am calling the method which navigates into tableview
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[PPViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil] ;
UILocalNotification *notification = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
{
int remedyID = [[notification.userInfo objectForKey:kRemindMeNotificationRemedyIDKey] intValue];
NSDictionary *reminderDetails =[NSDictionary dictionaryWithObjectsAndKeys:notification.userInfo,#"kRemindMeNotificationDataKey",[NSNumber numberWithInt:remedyID],kRemindMeNotificationRemedyIDKey,nil];
[_viewController goToReminder:reminderDetails showNotification:YES];
}
[application setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
self.viewController = [[PPViewController alloc] initWithNibName:#"PPViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
**This is the code which navigates into tableview in another viewcontroller**
- (void)goToReminder:(NSMutableDictionary *)reminderDictionary showNotification:(BOOL)shouldShowNotification
{
NSIndexPath *selectedSymptIP = [NSIndexPath indexPathForRow:selectedSymptomIndex inSection:keyIndexNumber];
[self tableView:symptomsTableView didSelectRowAtIndexPath:selectedSymptIP];
}
When you quit the app and your app starts again, your viewController is not yet set up. When launching from a notification, you need to check if you are resuming from the background, or launching normally.
Look at applicationWillEnterForeground and applicationDidBecomeActive in the UIApplicationDelegate protocol reference for how to handle resuming your app from various states. Also see: http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW3
I was able to solve the problem ..the crash was occurring since wrong xib file was loaded .

How to Redirect to home tab after login Iphone App?

In my AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
//Get uer ID from user defaults
NSString *userid = [defaults objectForKey:#"UserId"];
if([userid isEqualToString:#""]){
login = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[window addSubview:login.view];
} else {
[window addSubview:[rootTabBarController view]];
}
[self.window makeKeyAndVisible];
return YES;
}
and after login success i have this code
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:serverOutput forKey:#"UserId"];
//show tabbar app
NewClassMoonAppDelegate * appsDelegate =[[UIApplication sharedApplication] delegate];
[appsDelegate.window addSubview:[appsDelegate.rootTabBarController view]];
so the question is how can i redirect to specific tab [Home tab FOR EXAMBLE]?
[appDelegate.rootTabBarController setSelectedIndex:GiveIndexOfTab]; // give index of home tab for ex. 0
If you want to jump to a specific tab without intercepting the tabBar, rather than the first default tab
use
[appsDelegate.rootTabBarController setSelectedIndex:2]; // 2 is a pseudo index i have assigned
For tabbar controller,
SelectedIndex propery helps you to manage its behavior.
Use
setSelectedIndex:Index
method. It'll solve your purpose.
Thanks.

How to run something once when the app is launched?

I'm trying to play an intro movie when my app is getting launch, but am totally driven crazy already, I did a lot of testing in my code, along with trying to use this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
NSLog(#"App started to launch");
[self.window makeKeyAndVisible];
[self.window addSubview:_intro.view];
return YES;
}
but that's make my video run, even if I'm coming from the background.
If like pressing the middle button, then double pressing the middle button and pressing app icon, I get the movie to play again.
I forget to mention that this is my ViewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL launchedBefore = [userDefaults boolForKey:#"hasRunBefore"];
NSLog(#"value of hasRunBefore is %d",launchedBefore);
if(!launchedBefore)
{
[userDefaults setBool:1 forKey:#"hasRunBefore"];
launchedBefore = [userDefaults boolForKey:#"hasRunBefore"];
NSLog(#"value of hasRunBefore is %d",launchedBefore);
[self playvideo];
}
}
NSUserDefaults does not commit the changes to disk until you send the synchronize message.
Try adding doing this:
[userDefaults setBool:YES forKey:#"hasRunBefore"];
[userDefaults synchronize];