Lets say a user starts async request in PageViewController flow then dismisses. If they quickly bring back PageViewController it won't navigate to the correct page because an async request (that determines the next logical page to show) is underway. Is it standard to prevent the user from dismissing controller or asking them not to? If not, how do I manage background tasks, so I know to keep loading screen up and wait to navigate pages until last request completes and changes state/server side data?
Related
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.
I have implemented Push notifications and deep link in my app in traditional method using lot of switch cases and creating controller objects and redirecting to that controller but now code is getting unmaintainable because of lot of new scenario.
So I want to know how to handle deep link with push notifications, can URL Schemes work in my case and if URL schemes can work what payload should I send in the push message.
I just did this for my app. It all hinges on how your app is architected, i.e. how you navigate. Our app has a set of "home" pages, i.e. the top level things you can do. We already had the ability to navigate from anywhere back to a home page (by popping the current VC stack and closing any/all modals and then going to the new home page). To that, we added that as each VC loads, it checks state and sees if there is something it should do (configure itself, or push another VC). Once a VC has acted on state which applies to it, it clears that state.
Once you have built your mechanism to navigate to a particular spot, when you receive a push you just set your state and call whatever function navigates you back to the home page. Then that page checks state, does the right thing, and so on.
I have a blackberry application in which i want to show a "please wait" modal screen(which is a FullScreen push as modal screen) while sending a server request and if the user hitting the device back button , pop the modal screen and current active screen.This works fine.
My problem is that : I used a callback for server request in the active screen.But the callback executed even after popped up the screen.
Exactly whats happening while calling popScreen()? How can i remove all callbacks and refresh the screen if the user pressing back button while server request happens?
Thanks in Advance
There are several solutions to this problem of course. I guess the server request is sent asynchronously.
The simplest way I think out is having a flag and when the callback
is triggered check whether the user cancelled the action (pressing
the back button).
Another solution, perhaps not that nice is to check whether the
Loading Screen is still in the display stack.
What I think would be a proper solution is to have a stack of
cancelled http operations, so you can stop requests at any time. Then
if the request to the server has been sent, before calling the
callbacks you can check if the operation has been cancelled.
Otherwise, you just avoid sending the request to the server.
When you call popScreen, the screen which is on top of the display stack (the screen in the foreground) is removed from the stack and the Screen is refreshed (a paint event is triggered) to reflect the changes. Make sure you execute Screen.pop() on the UiThread:
UiApplication.getUiApplication().invokeLater(runnable)
In your scenario, how is the callback handled? Is it a delegate you passed along with the request or is a listener you register?
When I refer to delegate I mean something like the following:
Server.sendRequest(request, objectWithCallbacks)
and callbacks of the objectWithCallbacks (and only objectWithCallbacks) will be called accordingly. On the other hand, a listener would be something like:
Server.addListener(objectWithCallbacks, request)
Server.sendRequest(request);
this way, all the objects listening to "eventName" will get their callbacks triggered accordingly.
As far as I see, your callback will be always executed but in the callback itself you can check if the screen is currently displayed.
if( this.isDisplayed() ) {
// Do the magic
}else{
// Do nothing
}
Good Luck
I have an app that needs to fetch some remote configuration files before it starts or after it has been idle for some time in the background. I use a loader view controller to do the job while displaying a splash screen with a loading indicator.
What would be the best way to display the loader (assuming I also want to refresh the whole app after idle time in background):
Display as a modal view controller and dismiss when finished
Set the loader as root view controller and set back the original root when the loader finish (this method triggers a dealloc for the original root and creates it from scratch)
Go with option 1. I've used it many times and it works brilliantly. The best thing about using a modal view controller is that you can smoothly transition when you dismiss it, and you can just present it un-animated on applicationDidFinishLaunch so that it's there instantly for the user to see.
Display as a modal view controller and dismiss when finished.
This option will be more feasible when your app will starts from background state. You can show this with no animation show it will feel like splash and you can fetch remote configuration files.
I am trying to display a new view in IOS after login in my application. I also want to display this view when I start the application if the user is already logged in this app.
Now, if I start the application the first time I have the login view and I can write my user name and my password. when I press send button(login) the next controller starts. I would like to set for 2 or 3 seconds one view while I am downloading the information from the web service. I don't care if the information comes faster than the two seconds because I want to wait this time. I save the user information in NSUserdefaults.
Next time I start the app I already have the information and I go directly to the next viewcontroller without see any login view. So I want to watch the loading view.
I use AFNetworking to consume my web services.
You have two options, it seems a little arbitrary to show it for 2 seconds, but you can present the view and then:
[myView performSelector:#selector(setHidden:) withObject:[NSNumber numberWithBool:YES] afterDelay:3.0];
Or what you probably should do is hide the view or set it to nil within the completion block of your AFNetworking Call, that way if the call takes longer than 2-3 seconds, the view won't disappear
You can call the method for hiding view after delay using this:
[self performSelector:#selector(hideView) withObject:nil afterDelay:3.0];
Here is an idea, using GCD:
Store the login information into keychain (NSUserDefaults are just plain unsafe for passwords!) and dismiss the login window immediately after it is saved.
When the loding view is shown, create a dispatch group and submit your login and download logic there. (com.example.login thread)
Use NSTimer (or any appropriate logic) to wait for 3 seconds, then spawn another thread in GCD (com.example.login-wait thread), call dispatch_group_wait to block that thread until the com.example.login thread is done, and submit a block back to the main queue to switch views.
I used this login in multiple applications and it looked fantastic.