`applicationDidFinishLaunching` not called in iOS project - ios

applicationDidFinishLaunching is never called in the running of my app(tested on real device and simulator) despite the fact that applicationDidBecomeActive is called. I can only find macOS solutions to this problem(here, here, and here)
In my info.plist file, I have Main storyboard file base name set correctly. I have a Storyboard entry point hooked up to my initial view controller. The app launches and I see everything I should, but applicationDidFinishLaunching is never called and I use that method to handle on-startup configuration and construction.
Based on the macOS posts, I tried dragging an object(yellow cube) into the IB hierarchy of the initial view controller, set its class as my app delegate class, and set it as the initial view controller's delegate. But applicationDidFinishLaunching is still never called.
The method signature is correct (I know this is a common issue for Swift projects)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationDidFinishLaunching:(UIApplication *)application{
//code
}

In the documentation for applicationDidFinishLaunching: it says:
Although not formally deprecated, do not use this method in your apps.
Use the application:willFinishLaunchingWithOptions: and
application:didFinishLaunchingWithOptions: methods instead.
If you use application:didFinishLaunchingWithOptions: then applicationDidFinishLaunching: will not be called.

Related

Correct place to programmatically launch view controller: willFinishLaunching vs didFinishLaunching?

This probably has very little impact on performance, but I noticed that a lot of posts and tutorials simply instantiate and set the root view controller in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
However, there is actually a method that is not included in the default AppDelegate template file that gets fired off first:
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Is there any difference between instantiating your view controller's in either of these? Just preference or laziness?
The major difference between these involves state restoration (using application:shouldSaveApplicationState and application:shouldRestoreApplicationState. The Apple documentation for application:willFinishLaunchingWithOptions notes: "If your app relies on the state restoration machinery to restore its view controllers, always show your app’s window from this method." If you're not doing anything with state restoration, it probably doesn't make any real difference which one you use.

Detect when iOS breadcrumbs are used to return to app

I can't find information about how to detect when the iOS breadcrumbs are used to return to the app. I am looking to call a function on the controller when the view is active again specifically when this breadcrumb is used (Our use case being when location has been enabled externally).
I have tried using viewDidAppear but this isn't called. Is it possible? I find it unusual that this isn't called.
To be clear the breadcrumbs I am talking about are
I think you can use this method on Appdelegate
- (void)applicationDidBecomeActive:(UIApplication *)application {
}
then send a notification to your viewcontroller you want to handler.

"Application windows are expected to have a root view controller" message when adding view immediately after launch, iOS 9 only

My app sends a request at startup and displays a brief message to users when it succeeds, by means of MTStatusBarOverlay. Unfortunately, my current implementation seems to run afoul of iOS 9's view life cycle paradigms. I get the message
Application windows are expected to have a root view controller at the end of application launch
and the app crashes. The app works fine on iOS 7 & 8.
From searching around online, it seems like this might occur when trying to add the message view to the view hierarchy before the root view controller is established for the app's UIWindow, but that doesn't seem to be the case here, see below.
Here is an excerpt of the UIApplicationDelegate implementation:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[...]
self.window.rootViewController = [[MyViewController alloc] init];
[...]
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[MyDataManager sendRequestWithCompletion:^{
// Displays a message with MTStatusBarOverlay
[self showSuccessOverlay];
}];
}
application:didFinishLaunchingWithOptions: is called before applicationDidBecomeActive: so it seems like there should never be an issue with rootViewController being established.
Why is this happening? What's different about iOS 9 that's causing the app to break?
MTStatusBarOverlay is a subclass of UIWindow, so instantiating one during app launch adds that UIWindow to the list that iOS checks for a populated rootViewController when launch completes.
I was able to work around the issue by instantiating and assigning a dummy controller before using the overlay, like so:
[MTStatusBarOverlay sharedInstance].rootViewController = [UIViewController new];
[[MTStatusBarOverlay sharedInstance] postMessage:#"Message"];

iOS equivalent to Android registerActivityLifecycleCallbacks

I developed an Android app where I used the application.registerActivityLifecycleCallbacks (http://developer.android.com/reference/android/app/Application.html) to know when each Activity is started and stopped and record it for analytics purposes. I am now developing the iOS version and I cannot find an equivalent to this method to monitor the UIViewControllers or UIView displayed by the app.
Anybody has an idea ? I am a beginner on iOS so I may not be taking the right approach, feel free to suggest other ideas.
Edit
After the first answer I felt I should be more precise.
I am actually developing a SDK for other developers to include in their apps so I want the impact of the SDK on their code to be as small as possible.
I first thought about doing a BaseActivity/BaseUIViewController that developers would have to extend in all the Activity/UIViewController but it felt heavy and since both language don't allow multiple inheritance this would greatly impact their code. This is why the registerActivityLifecycleCallbacks method is great in Android because they only have to give me an Application or Activity object.
Is there a solution for iOS or I will have to create a BaseController ?
Thank you in advance.
I've not run into anything that specific as the application.registerActivityLifecycleCallbacks in iOS, but you could always implement your own using the methods that exist within the AppDelegate and each class.
From the AppDelegate, you are provided the methods to determine the state of the overall application such as determining when the application finished loading, when it enters the background, and so forth. Details on these states can be found in the UIApplicationDelegate Protocol Reference page.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSLog("Application did finish launching with options: %#", launchOptions);
return YES;
}
For each view controller, you can add your implementation to the individual view controller lifecycle methods within each file. Methods such as viewDidLoad, viewWillAppear, viewDidAppear, and viewDidLayoutSubviews are available.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"View %# did load", self);
}

Every time my app launches (whether from cold launch or background) I want to have it do something, how do I accomplish this?

I want to check every time the app launches whether or not there's a URL in the clipboard, and if so, do something with it. Which method fires that I can override whenever the app launches, whether from a cold launch (it was killed in the background for instance) or if I just press the home button, copy a URL and jump back in.
Is it one of these?
- (void)applicationDidBecomeActive:(UIApplication *)application
- (void)applicationWillEnterForeground:(UIApplication *)application
- (void)applicationDidBecomeActive
- (void)applicationDidFinishLaunching:(UIApplication *)application
Confused.
As #rmaddy says, the correct method to use once the app launched is applicationWillEnterForeground: from your app delegate.
This method will be called when the user jump backs in, but NOT in other circumstances you don't need to respond to (such as the user receiving a text message and dismissing it).
However, from my testing, applicationWillEnterForeground: is not called when an app is launched from cold; you should catch that in applicationDidFinishLaunchingWithOptions:.
So, basically, your app delegate should include code like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self checkForURL];
...
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[self checkForURL];
...
}
- (void)checkForURL{
//code for checking for URL goes here
}
Hope that helps.
- (void)applicationDidBecomeActive is called when the app is launched or becomes active from the background.
This doc explains everything pretty well: http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
With reference to the UIApplicationDelegate Protocol, the handling of app launches can be handled in 2 methods:
application:willFinishLaunchingWithOptions:
application:didFinishLaunchingWithOptions:
And the handling of app launches from background can be handled with the help of method:
applicationDidBecomeActive:
Based on the above call, you can handle your application.
In your app delegate add it to the methods that the other answers have suggested (applicationDidFinishLaunchingWithOptions:). In your root view controller register for the following notification. This will always be called when your application launches once it has already started running.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(bringingItBack) name:UIApplicationWillEnterForegroundNotification object:nil];
This will cover both the instances when the app launches and when you are just bringing it back from the background.

Resources