I'm using storyboard to develop my app, and the initial view controller is a Tab Bar Controller. At the AppDelegate I did some thing work to get the jsonData from my website. It will take 10-20 seconds . You know, I want to do something to notice user is loading, not just showing a default.png picture. How can I do it?
Well, you can have your rootViewController have a loading state (maybe an UIActivityIndicatorView on top of the other views and some public methods like showLoading and hideLoading.
Steps :
In the AppDelegate application:didFinishLaunchingWithOptions: method, build your rootView controller as usual and call your method that loads the JSON files.
Call the showLoading method when you're starting the request
Call the hideLoading method when you receive the response.
Also, remember to use asynchronous request or make it in a different thread to prevent blocking the main thread.
Related
I am making an IOS app where i am calling an API in viewDidLoad method of view controller. Now i want to reload the same view controller with the data that comes from server. How many ways are there to do this task and what would be the best way?? Please help me.
Thanks!!
viewDidLoad method is called first time when UIViewController is first loaded and when it pop and then you reenter in it at that time viewDidLoad is called. So if you want to load the API only once then viewDidLoad is the best place to call an API.
viewWillAppear called every time when you enter in that UIViewController and it is the place load the API when you want to get refreshed data (updated data).
viewDidAppear also called like viewWillAppear but bit late called than viewWillAppear so if you want to call the API every time than the best place is viewWillAppear method.
Because viewDidAppear method called late from viewWillAppear method and you are just requesting the API so the response of API may be late and If your UI change based on API response then it will stuck the application UI so there is a best place to call API either viewDidLoad & viewWillAppear methods.
viewDidLoad is called once. If you use navigation controller and do back and forth ou view controller this viewDidLoad method will never be called. Until you create this ViewController again (i.e [navContoller pushViewController]). If your api data will never changed the life cycle of this View Controller the this is the better place to call your API. But if your api data need to call frequently [i.e. back and push.forth this view controller] then you should not call api here.
viewWillAppear: before a view controller shows.If you call you api
inside this method you UI will stack until the data loading finish. which looks odd.before load the view of viewController this "viewWillAppear" method is called. This is the reason, it's name is "viewWillAppear". That means this view will load some time later (i.e some micro second later). If you call your api here after what will happen lets analyze. Say, your api return response after 10 sec. Then UI will freeze/stuck for 10 sec and you will see after this 10 sec later your view will called.
viewDidAppear: after finished a view controller showing.So, you need to called your loading API inside this method.
viewDidAppear is definitely not the one you want to use, it will 'pause' the view from responding while you're loading the data.
Normally viewDidLoad is the one you want to place it.
If we stay in the same ViewController,the three method viewdidload,viewwillappear,viewdidappear will not called again.So we stay in the same view controller, we get the data from the server,we should call the reload method after get the data.
Hope this answer can help you.
I think viewWillAppear is best place for loading data from API. Because viewDidLoad called once when the view is being loaded, but viewWillAppear will called when it loaded from its parent view or child view.
You don't need to call API every time you navigate to view controller, you need to call it one time.
If you have a TableView with Cell and this cell get from API and will open new ViewController when you press on it.
So here you will not add your API in :
viewWillAppear()
viewDidAppear()
You will add it one time in viewDidLoad() while we need to minimize num of requests as many as we can.
Example like this: navigation controller:
suppose Fruits and Cars will present from API.
when you click on the fruits cell you will navigate to below viewController:
So when you want to go back to the first view controller, clearly you dont need to reload api while it is already exist.
In this case we use viewDidLoad() to handle API request
I would like to know which is the best way to do the next:
In my AppDelegate.swift file I had the entry point of the app, register the instance, but before the instance is registered, the main function(inside viewDidLoad()) of the MainViewController is called and I would like to know how to do to wait the MainViewController viewDidLoad() function until the instance register will be completed.
You should add extra view controller and show that view controller initially until your required task got completed. You can show loader or activity indicator or some ui that shows like getting data or etc. After you completed your process move to main viewcontroller so your viewDidload will be called when you want!
ViewDidLoad is Async by design, so is a non-sense waiting for it.
When called you are certain UI is up, it was written for this scope.
I think is better you read carefully iOS event loop and app lifecycle, to fully undestand Apple design.
You can use sleep() function for wait to load viewcontrollers view
I am making an IOS app where i am calling an API in viewDidLoad method of view controller. Now i want to reload the same view controller with the data that comes from server. How many ways are there to do this task and what would be the best way?? Please help me.
Thanks!!
viewDidLoad method is called first time when UIViewController is first loaded and when it pop and then you reenter in it at that time viewDidLoad is called. So if you want to load the API only once then viewDidLoad is the best place to call an API.
viewWillAppear called every time when you enter in that UIViewController and it is the place load the API when you want to get refreshed data (updated data).
viewDidAppear also called like viewWillAppear but bit late called than viewWillAppear so if you want to call the API every time than the best place is viewWillAppear method.
Because viewDidAppear method called late from viewWillAppear method and you are just requesting the API so the response of API may be late and If your UI change based on API response then it will stuck the application UI so there is a best place to call API either viewDidLoad & viewWillAppear methods.
viewDidLoad is called once. If you use navigation controller and do back and forth ou view controller this viewDidLoad method will never be called. Until you create this ViewController again (i.e [navContoller pushViewController]). If your api data will never changed the life cycle of this View Controller the this is the better place to call your API. But if your api data need to call frequently [i.e. back and push.forth this view controller] then you should not call api here.
viewWillAppear: before a view controller shows.If you call you api
inside this method you UI will stack until the data loading finish. which looks odd.before load the view of viewController this "viewWillAppear" method is called. This is the reason, it's name is "viewWillAppear". That means this view will load some time later (i.e some micro second later). If you call your api here after what will happen lets analyze. Say, your api return response after 10 sec. Then UI will freeze/stuck for 10 sec and you will see after this 10 sec later your view will called.
viewDidAppear: after finished a view controller showing.So, you need to called your loading API inside this method.
viewDidAppear is definitely not the one you want to use, it will 'pause' the view from responding while you're loading the data.
Normally viewDidLoad is the one you want to place it.
If we stay in the same ViewController,the three method viewdidload,viewwillappear,viewdidappear will not called again.So we stay in the same view controller, we get the data from the server,we should call the reload method after get the data.
Hope this answer can help you.
I think viewWillAppear is best place for loading data from API. Because viewDidLoad called once when the view is being loaded, but viewWillAppear will called when it loaded from its parent view or child view.
You don't need to call API every time you navigate to view controller, you need to call it one time.
If you have a TableView with Cell and this cell get from API and will open new ViewController when you press on it.
So here you will not add your API in :
viewWillAppear()
viewDidAppear()
You will add it one time in viewDidLoad() while we need to minimize num of requests as many as we can.
Example like this: navigation controller:
suppose Fruits and Cars will present from API.
when you click on the fruits cell you will navigate to below viewController:
So when you want to go back to the first view controller, clearly you dont need to reload api while it is already exist.
In this case we use viewDidLoad() to handle API request
I try to explain my problem. In appdelegate I have to select a rootViewController depending on the result of an asynchronous request (I'm using AFNetworking framework). In fact, I need to know if my user is profiled or not: if he is profiled I can show him app's Home, if he is not I have to show him a profilation view.
In storyboard I set the Home view as the designated entry point, but in this way this view is always shown until the asynchronous request is completed. Is there a way to make appdelegate wait for the response?
I think there is't good solution to let app delegate wait for the response because if the network connection will be poor the app loading time will be very long and OS could kill your app or user can turn it off.
You can add some loading view controller (with animation so user will know that the app is doing something) instead of home one and when you receive the response present appropriate view to the user (modal segue could do the job).
Hope this help
A better solution is to use splash screens. That is when your app gets loaded in AppDelegate, create and push a splash view controller. Which would just contain a single UIImageView covering whole screen showing your application splash image. Upon asynchronous call completion, pop that splash view controller and push your required view Controller.
Many apps use this way to download necessary asynchronous data before showing the app. So that user don't see empty screens or garbage data.
If something gets failed like internet connectivity failure or server response error, etc., Show error to user and perform error handling according to your app logic.
You can programatically navigate to the root view controller as
[self.navigationController popToRootViewControllerAnimated:YES];
This code can be put in the condition of result.
Or in your way, I think you are created a segue for navigation to the rootViewController. You can programatically perform a segue using
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender
If you are using the AFNetworking, just add a method in the success block and pass the response to that method in a parameter of dictionary. Check your response in the method and choose the controller which you want to make make the root view controller from that method.
I have a MFMessageComposeViewController in my app, and sometimes the recipient count can get up to 200 or so. When testing on a 4S, it takes up to 10 seconds (!!) to load the sms view after I click my button. I imagine it could be even longer with older devices.
This is obviously too long for a blocking call without a loading view, but I can't put a loading view up if I have no callback when the view actually loads! There's only 1 callback in the MFMessageComposeViewControllerDelegate protocol, but that only calls back after the sms view is dismissed, not when it loads. Any ideas?
I'm thinking maybe grabbing callbacks from somewhere else in the modal view loading logic, or last resort I could just put a 5-10 second loading screen and hope it's up by then.
MFMessageComposeViewController is a subclass of UINavigationController. Have you tried implementing any of UINavigationControllerDelegate's methods. Specifically:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
After some more digging, I found out that I was using an older version of UIViewController's presentViewController:animated:completion: so I didn't have the "completion" part implemented. This is definitely the best option for my purposes to just dismiss my loading view in the completion block, but it does only work on iOS 5.0 and up. If you have to support lower than 5.0 maybe Edwin's answer would help.
UPDATE: Using my above method actually didn't work in practice. If I threw up a progress view and then called presentViewController:animated:completion: on the MFMessageComposeViewController, it would still make the blocking call before the progress view even showed up. I'm assuming it was something to do with the run loop not completing before the blocking call started so no UI changes would come up.
Instead I just had my progress view make a callback when it actually showed up, and then in the callback I would start loading up the MFMessageComposeViewController. Then, when the MFMessageComposeViewController callback was fired I would dismiss my progress view as well as the MFMessageComposeViewController. Success!