How can I make a good use of didFinishLaunchingWithOptions in Appdelegate - ios

I want to extract some data from the server or database, now I'm confusing if I have to put the extracting code in didFinishLaunchingWithOptions() function or put the code in viewdidload() function in the first viewcontroller. What's the execution efficiency of both methods?

It depends on your requirement. If you want the data before actually going to a viewController then you can extract it in didFinishLaunching WithOptions. But if you want the data for only viewController then its good practise to extract it when you are on that viewController i.e in viewDidLoad of that viewController.

If you fetch data over the network, I'd definitely recommend not to use didFinishLaunchingWithOptions. Any blocking code in this method will prevent the app's UI from loading, so you can't even display a "Please wait" message to the user. Also, iOS will kill your app if didFinishLaunchingWithOptions blocks for too long (I think the timeout is about 10 seconds).
So either perform the loading in your main view controller, or run it asynchronously in a background queue — in this case, you can of course also put the code in didFinishLaunchingWithOptions.

Related

Run Code Every Time App Opens - Better Way?

I need code to run every time the app opens, including if it was only suspended (user hit home button, then returned to app).
I already know that viewDidLoad only loads on the initial VC load, so that doesn't do what I need. And viewWillAppear / viewDidAppear don't do it either. This SO thread has an answer but it's from six years ago and I don't love the answer. Essentially, it says create an observer. However, that seems like a waste of resources and observers create those reference loops that keep things in memory.
If no one gives me a better solution I might try "applicationDidBecomeActive" in the AppDelegate, but I try not to load my appDelegate up with ViewController code.
My question is, in the six years since this SO thread was answered, do Swift/iOS10 now allow for a cleaner solution?
If you don't want to use NSNotificationCenter Than make global object of your Viewcontroller in AppDelegate
and put code in applicationDidBecomeActive with your viewController object
Because applicationDidBecomeActive calls everyTime when you start your application and when you press home button and came from background so you don't need to write your code in viewWillAppear.
As far as I can tell after additional research, there's no new way since that post six years ago. However, the applicationDidBecomeActive approach does work well:
func applicationDidBecomeActive(_ application: UIApplication) {
guard let rvc = self.window?.rootViewController as? firstVCName else { return }
rvc.nameOfMethodYouWantToCall()
}
The above gets a reference to the existing VC (instead of creating a whole new instance). Then it calls the method, without having to load up the appDelegate with code. Very simple and efficient.
I tested this and it's exactly what I needed, code that runs every time the app is opened. It's very consistent.

Does delegate have function which is executed every time app comes from background

I have application with lot of view controllers and on every time when app comes from background I have to make some request to server and reinitialise some global variables. At the moment I am doing this by repeating code in every view controller in didViewLoad but I wonder is there way to this in delegate to avoid repeating on 10 places ? ( I check didFinishLuanchingWithOptions in delegate but it is called only first time not when app comes from background ).
I think you want to look at these two:
applicationDidBecomeActive
And
applicationWillEnterForeground
Check out the documentation for more details.

Reloading UIViewController from scratch via AppDelegate applicationWillEnterForeground

What I'm looking for is a very straightforward solution to the following in my XCode project:
When applicationWillEnterForeground is called, I want my main (and only) viewcontroller to reload as if the app is launching from scratch, the reason being I want it to recalculate a number of things at that point which might have changed while the app was in the background, in response to temporal changes detected when the app is launched. I want this to happen rather than the view just to reappear in its last seen state
The viewcontroller is named TMViewController
I have found answers that tell me simply that I have to reload the viewcontroller in the applicationWillEnterForeground section of the AppDelegate, but not how to do this
I have found answers that explain how to reload various elements, labels, webviews, and data from the net. These are much more complex than I need, and I can't really see the needle for the haystack
All I need to happen is the applicationWillEnterForeground to reload the viewcontroller as if its viewDidLoad had been called (I understand that this in itself is not a good solution, not that I know how to do even that!)
I suppose in a nutshell I'm struggling to understand what needs to go in the h & m files of both the AppDelegate and the viewcontroller files to accomplish this
any help would be greatly appreciated
self.window.rootViewController = [[TMViewController alloc]intWithNibName:#"myNib" bundle:nil];

Synch call on willFinishLaunchingWithOptions (AppDelegate)

I would to do a remote call before the app is started (in AppDelegate, when the splash screen is showed). Then i would to choose which view controller to load based on url response.
Is right to do this on AppDelegate? Or I need a different approach?
I think the best approach is creating a ViewController where you make this choice. Once this VC is loaded you make your remote call while showing in the UI that your app is actually working and waiting for a network response - the best approach is probably showing a message with a UIActivityIndicatorView spinning.
Once you get the response you load the VC that you need. You should also handle errors - what are you going to show if the network request fails? Are you showing an error message?
You should not do any synchronous network calls from willFinishLaunchingWithOptions. If you take more than a few seconds to return that method or (didFinishLaunchingWithOptions, or the other app delegate methods that the system calls in the process of launching your app) then the springboard will terminate your app as unresponsive.
#Tanzolone has the right idea. Have your app display a view controller that shows your app's UI, THEN invoke the network request and decide what second screen to switch to based on the response.

Strategy to launch a task - and avoid race conditions - from the App Delegate

I'm developing a small app on top of core data. At startup, I need to launch a maintenance task - fast but important -. To run this task, the app delegate must open a UIManagedDocument, and perform various checks on it. The app views must not start until the checks are completed. Because opening a UIMD is asynchronous, the app delegate isn't done when the first UIview tries to access the doc. The application then crashes due to a race condition because the app delegate and the view are trying to open the doc at the same time, while the doc state isn't yet finalised.
I'm using a storyboard, so segues are pretty much in control of the OS... Next time, I'll do it all manually..
What would be your recommendations ?
Note:
1)I can not perform the task when the app. goes into background state, because if it is brought back up again, avoiding inconsistent states between the underlying database and what's displayed in the view will be very tedious.
2)For the same reasons, performing the maintenance task during normal execution is not easily done.
3) All views access the UIMD via a singleton, according to the code proposed here
Setting a mutex lock in the UIView isn't my preferred route, because the screen remains black - no data -, while displaying the tab bars, until it is released by the app delegate.
Is there a way to have the app delegate wait for a signal before it hands the control over to the UIViews ? In this case, are there any gotchas ? I suspect this is probably not the recommended way to do, and iOS might kill the app if the delegate stays too long waiting for the maintenance task to complete. What would be "too long" in this case?
You could do it more elegant way. The first view the user will see must be some kind of SplashView - just an image with progress indicator. It should stay on top while your task is going on. It's not too important how you're showing this view. You can set it as the first in your storyboard or just create it manually in applicationDidFinishLaunching message.
Then in your task send a NSNotification when it's about to finish and in the observer in your AppDelegate just hide your SplashView and present your first view with valuable content.
You can even add some visual effects for transition between those views and your app will look really great! :)

Resources