Reloading UIViewController from scratch via AppDelegate applicationWillEnterForeground - ios

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];

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.

appdelegate didFinishLaunchingWithOptions, how handle quick action when view is not created yet?

Ok, so in my AppDelegate, I initialise various stuff in didFinishLaunchingWithOptions, however I create my views in applicationDidBecomeActive.
My reasoning behind this was that when the app is executing stuff in the background (push notifications), the didFinishLaunching... will be called so I don't want to create UI stuff there, if the application will not be visible.
This has worked for me, however now with quick actions, say i want to have a quick action that goes to one of my tabs. I can't do it in didFinishLaunchingWithOptions, since the views won't be created until didBecomeActive.
So, my questions are:
Have I misunderstood something regarding the lifecycle and timing of UI and didFinishLaunching.../didBecomeActive? That is, is it good practice to do what i do, create the views to be used in didBecomeActive and not didFinishLaunching...?
I haven't really found any good examples regarding this. I suppose i could store away the UIApplicationShortcutItem in didFinishLaunching... and then use it in didBecomeActive. It seems a bit 'hacky', but i haven't figured out anything else.
Pointers much appreciated.

IOS initial view controller based on condition retrieved from database

An iOS app I'm creating shows a setup screen upon first launch which requires data to be written to the database.
Upon launch, I need to access this value form the database.
If it is set, launch main view controller
Else show setup view controller.
As far as I'm aware theres two ways I can do this, programmatically setting it from the AppDelegate or using an initial View Controller as a splash screen and performing the look up and segue there.
What would be the best way to approach this? Is it wrong to do a database lookup in didFinishLaunchingWithOptions?
Using a splash screen is probably the better option as it provides better scope for modification in the future and allows you to update the user on progress. It is fine for the app delegate to run logic to determine how the app starts but you should endeavour to keep the app delegate minimal and focussed.
I very much doubt that you would get this approved (if your goal is the App Store). Your app delegate needs to create a window, and set a rootViewController to that window before it returns YES in appFinishLaunching:
You simply do not have enough time to check with a server before creating the first viewController and you'll be creating poor interface if you try. I suggest the first ViewController will need to be informing the user that it is checking with the server with an activityIndicator or something. The best :)

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.

iOS: Hiding sensitive information on the screen when app is backgrounded

When a foreground app gets backgrounded (e.g. Home button gets pressed), how can I change elements on the topmost view controller prior to when iOS takes a snapshot of it and starts the animation to show the next screen?
I ask because I'm writing an app requiring HIPAA compliance, and I am concerned that the snapshot that the OS takes in order to do this animation sometimes contains sensitive data which should not be visible even for a split second when the app gets foregrounded later.
I'm aware that view controllers have lifecycle methods such as viewWillDisappear which might be usable, but I have a lot of controllers and I'd rather just have something in my App Delegate to handle this (e.g. by adding an opaque full-screen UIImageView overlay) rather than having to write custom code for this in every last controller.
I tried putting overlay-generating code in applicationWillResignActive, and I've been digging with Apple's docs and Google, but it's not working. I suspect the screenshot gets taken before the app has a chance to update the screen.
Thanks!
Not sure about HIPAA's requirements about backgrounding and possibly leaving the user logged in for someone else to resume, but the safest sounds like it would be to add a key UIApplicationExitsOnSuspend with a boolean value of YES to info.plist.
That will prevent the app from backgrounding entirely, and restarts it (possibly triggering a login procedure) every time you go back to it.
Most (if not all) mobile banking applications I've tested do this for safety reasons.
I believe the answer is to not concern oneself with changing what's on the screen before the backgrounding animation begins, but to simply modify what's displayed on the screen once the app enters the background (i.e. inside of applicationDidEnterBackground: in your App Delegate.) This solved my problem.
My UIImageView overlay idea worked here, although I decided just to pop to the root view controller instead. Simpler that way. My root view doesn't have any sensitive info.
Here's what it looks like:
-(void)applicationDidEnterBackground:(UIApplication *)application {
UINavigationController *navigationController =
(UINavigationController *)self.window.rootViewController;
[navigationController popToRootViewControllerAnimated:NO];
...
}

Resources