Having trouble with AppDelegate didFinishLoadingWithOptions execution order/timing - ios

I'm having an issue with this code (I have it in didFinishLaunchingWithOptions). I need it to finish executing the code inside before the app continues because it sets up some critical things in core data. It sends this to the background though and starts running the rest of the app and it doesn't finish quick enough for the data to be usable.
DataManager.getDataWithSuccess { (data) -> Void in
//code to execute here
}
How can I force the app to wait for this code to finish before moving on?

You shouldn't block the didFinishLaunchingWithOptions method from returning so that it can wait on an asynchronous task. It's crucially important to note that iOS applications are only given a limited amount of time to complete launching before the application is killed by the operating system.
An approach I have used in the past when waiting on asynchronous things to happen that need to happen before I really launch my app is to create a LaunchViewController. The interface for this view controller matches perfectly to the app's splash screen. From an end-user perspective, you can't even tell we've left the splash screen.
Here, we do any set up code such as asking your DataManager to get data. Then, when it (and any other set up actions) completes, you simply present the next view controller in much the same way you'd move between any other view controllers.
A huge positive side effect here is that you can have much nice looking animations from your splash screen into the first screen of your application.

Related

How to call Screen Time at settings from my app

Apps set to Screen time are strongly constrained by their behavior.
If the screen time starts while the app is running, the nature of the app causes problems in operation.
Normally, the setting screen is called by the following code, but I do not know how to call Screen Time.
UIApplication.sharedApplication().openURL(settingsURL)
Do you know how to do that? Or tell me if there is another way around it.

Load entire application at start up

I have a tabbed iOS application with each of the tabs having some sort of json request so the view loads ever so slightly slowly. I want to remove that lag completely so I'm wondering if there is a way to call the ViewDidLoad function from each of the classes during the login phase of the application.
if (login == "Success") {
UserDefaults.standard.set(true, forKey: "isUserLoggedIn");
UserDefaults.standard.synchronize();
DispatchQueue.main.async {
// Load all resources here
}
}
I can understand this can be bad practice if the app is very large, but I think in this scenario the app isn't huge, but the lag between the view controllers is enough to be annoying. I would rather have the user wait at the start for 3-5 seconds whilst everything loads, and have a smooth experience once inside. Is there a way to do this?
You shouldn't call the lifecycle functions of the viewcontroller for yourself. The viewDidLoad function will be called when the view has been loaded.
Apple: This method is called after the view controller has loaded its view hierarchy into memory.
So calling let _ = viewController.view will trigger the view creation and the call of this function.
But i think it's much better to have a startup phase instead. Think about a 'startup'-screen that downloads everything you need (with maybe a spinner and a text) and moves automatically to the content (the tabbar controller) when done. That may also fix the problem of a low network connectivity (think about a download that take a minute for example). You may display that screen modally above or as screen before the tabbbar controller.
If you don't like the idea of a startup phase you may also design your ui responsive. Start the download whenever needed / regularly and update your ui according to the results when ready. The ui will be fast then, but uses last known data. The meaningfulness and implementation depends on your content.
Update
On second thought: If you already have a server login screen, why not download the content directly after the successful download as part of the login? Users do not know if you are still checking the login or downloading some necessary data. You may say that login is only successful if server login AND download are finished successfully.

why is iOS launch screen very slow?

My iOS app launch screen takes about 3 - 5 seconds. I have a map that will load after the launch screen. My users have to wait for the launch screen to load and then wait another 3 seconds for the map to load.
Is there a way to minimize launch screen time?
Basically this delay means that you are doing something very wrong during launch. Your job is to launch immediately. Indeed, the WatchDog app will kill you dead if you don't.
There are excellent WWDC videos on this topic, and you should watch them. But in general there are two ways to go wrong:
You must do nothing time-consuming on the main thread. If you have a time-consuming thing to do, like loading your map or networking, you must do that on a background thread. You need to get out of the way so that the runtime can launch your app now.
Just the other way around, you must not touch the interface on any other thread but the main thread. Doing this wrong causes just the kind of delay you are reporting. Do your work on a background thread, but then get back on the main thread to talk to your views, view controllers, etc.
Finally, I should point out that you might be able to get some idea what you're doing wrong by using Instruments. Unfortunately it works rather badly against app launch, but it can be worth a try. Above all, watch those videos!

iOS Launch Screen Animation Time

It seems like the fade animation between the launch screen and my first view is really slow.
I don't think it used to be like that. Is there a way to control the speed of that transitional animation?
I looked at some apps on my phone and the launch screen doesn't fade as slowly as mine. What things could I have done to affect that?
(No I don't have slow animations turned on, only the fade animation is slow)
In WWDC 2012 video iOS App Performance: Responsiveness they enumerate a whole list of issues that have impact on the app startup time, ranging from attaching to unnecessary frameworks, optional linking to frameworks that you really could make required, the use of static initializers, overly complicated initial scenes, too much information stored in preferences, etc.
That video covers a range of topics, like the above, which impact startup time. In the demonstration, they show how one might benchmark the startup time. Unfortunately, in my experience, there's a good chance that you might not be able to do anything to fix this issue (e.g. you need certain features and therefore need certain frameworks), but it's still an illuminating video and it might give you some ideas of things you can try to alleviate the start-up performance issues.
If your app splash screen show more time, so please check following things in your app.
1. AppDelegate.m
in didFinishLaunchingWithOptions method have you called any heavy method which takes more time for finish task if yes then change that method location, basically in appDelegate class don't write any heavy methods.
2. first view of your app.
check viewDidLoad() method, if you call many method or any heavy method from here then your launch image will show still your control not come out from viewDidLoad method, so if you want call any methods at view launch time then call them from viewWillAppear or viewDidAppear method (in viewDidAppear method don't call any UI related methods)
I never figured out what was going on here, but the next day when I started up xCode and the simulator it was back to the normal loading time.

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