I have a MBProgressHUD that shows when data is being pulled on the background asynchronously. Sometimes when the network is slow this will take forever. So as of now I am just hiding it after 30 seconds if it hasn't been dismissed. What is a good way to dismiss this HUD for a slow network connection?
I would say that the best solution is probably to keep the HUD up the whole time the data is loading so that the user knows that something is happening, and perhaps give them an option to cancel it if that is appropriate for your app. Alternatively, if it is possible for you to load and display the data piecemeal (i.e. before you have the entire set of data), then you should just display the HUD until you have enough data that you can start displaying something in the UI that the user can interact with.
Basically, what you want to avoid is a situation where it could appear to the user that nothing is happening and the UI is essentially blank with nothing for them to do.
Implement MBProgressHUD delegate
it will be called every time whether if it is fast or slow network connection,In case of slow network connection there will be a time out and this delegate will be fired,remove the hud from the superview in this delegate
-(void)hudWasHidden
{
[HUD removeFromSuperview];
}
Related
I've made a custom activity indicator (actually just an imageView)
When user clicks something and I expect it will take a bit long to process(alloc a UIViewController and push on to navigation stack),
I alloc the indicator and add it as subview of current view just before the lengthy process starts.
Strange thing is, indicator doesn't show up until the push (left-right) animation starts.
Is it because the lengthy job takes the system, and ui drawing for activity indicator is delayed?
Am I doing something wrong here?
Thank you
Edit
Looks like I can do the "push" in background.. i'm trying it now
IPhone SDK - Leaking Memory with performSelectorInBackground
Is your job synchrone or asynchrone ?
If it's the first case, then it can be the problem.
Check all the method like :
[ self performSelector:<#(SEL)aSelector#> ];
You can thread this to avoid your [potential] problem.
Good luck.
You should process your lengthy tasks in the background. The UI won't update if you block the main thread.
So you have to refactor your app, the alloc and push of the viewController should happen within the blink of an eye, because you can't do this in the background.
But you can do the processing (downloading data I guess) in the background.
There is plenty information available about background processing. The way to go varies heavily on what you want to do exactly.
I allow the user to manage records on other views. I set a flag if certain changes are made.
Then on the flag (where the data changes will have an impact) I run some methods / queries which create the data which is used in my table view(s). This workload currently happens in viewWillAppear(s).
This could take a few seconds and I'd like to show my progress indicator view which I wrote today, it uses a transparent view with a activity indicator in the center of the view.
[self performSelectorInBackground:#selector(startupStuff) withObject:sender];
However, viewWillAppear won't wait while I run the the work in the background.
Ideally I'm looking for a quick fix to work around this problem.
Any ideas ?
However, viewWillAppear won't wait while I run the the work in the background.
That's the whole point of it, isn't it? At the end of your startupStuff method, you should call another method on the main thread (with performSelectorOnMainThread:...) that is used to (a) inform the controller that your data is ready, (b) reload the table view and (c) dismiss your progress indicator view.
I have a subview where there is an uitableview that gets data from an online server (title, subtitle and image). When I click the button that shows the subview it takes a little time to get there using WiFi connection, but under 3G network it takes longer, so that you really feel the gap between loading the view and having pressed the button
what I'd like to do, is to display an uiactivityindicatorview when you press the button and after loading the view, and when it has loaded stop the activity indicator
how can I check that the uitableview has finished loading ?
do you have other suggestions ?
Thanks in advance
Use asynchronious requests or threading (take a look at NSOperation)
Look into doing network operations asynchronously, rather than blocking the main UI's thread. ASIHTTPRequest is a really good library for this: http://allseeing-i.com/ASIHTTPRequest/
As the others said, if you are not using an asynchronous approach to this, I strongly suggest you to do so, because otherwise you will block your application for as long as the data is being downloaded.
With that said, you could show the activity indicator while the data is being loaded, and that is until the delegate method
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
is called. Then, your table should be populated with the data and the indicator would dissapear.
I hope this helped you a bit
I have an iphone app that has one view that needs to fetch a lot of data off of a variety of internet sites. Therefore, the amount of time required for it to load is unacceptable. I was wondering if there is any way to load the view during the 'applicationDidFinishLaunching' method so the delay is at the startup of the app instead of midway through navigation.
Thank you very much!
You want to load the view as quickly as possible, and then launch a background thread or asynch request to pull the data down.
Making your application sleep during initial load isn't advisable. I believe SpringBoard will terminate any application which takes longer than 30 seconds to finish loading.
It's a bad user experience to have the app do something without visible feedback to the user (animated UIActivityView for example)
Have you already considered loading the data asynchronously? While it's loading, the UI doesn't get blocked. For example you can show a nice loading-wheel when your app is loading the data. This is how all good apps do this.
If the initial view has a separate viewController than your 'data' view, you could add a reference to the dataView to the appDelegate and then do something like:
if (self.curAccountManager == nil) {
self.curAccountManager = [[accountManagerController alloc] initWithNibName:#"accountManager" bundle:[NSBundle mainBundle]];
if (![self.curAccountManager isViewLoaded]) {
UIView *tmpView = self.curAccountManager.view;
tmpView = nil;
}
}
This will load the view. But if it's doing a lot of loading, when the user switches to it, it might not respond well. I would suggest you follow the suggestion above and in your data view load the data asynchronously so you can at least show the user status or partial results.
I am working on a an application which is very simple
a navigation controller with a table view
when the user clicks a row, he is directed to the details view.
However, the details view pulls data from Core Data. i am pulling a relatively large amount of data that takes about three seconds to load.
I wanted to add that UIActivityIndicatorView to show progress.
I tried to start the animation once the user clicks the row, so i set it to animate in didSelectRowAtIndexPath
For some reason, the Activity Indicator doesn't start before the pushing of the details view.
Any idea why? or the best way to implement such an idea?
~Adham
Because you start the animation and then start a large operation in the same thread. Consider running that 3 second operation in a new thread. Look at NSOperationQueue and then create a NSOperation to run that procedure. It will work this way.
The UI doesn't update until the end of your run loop. You are, in sequence, displaying the activity monitor, then pushing the new table view, and then the UI updates. You need to change this order.
You can either move something to a different thread, or you could perhaps delay the loading of the new table view by calling performSelector:afterDelay: with a delay of 0. That will delay the loading of the new table view until after the activity indicator appears in the UI. Now, it's still all on the same thread, so you will be blocked from doing anything, but if the animation is threaded in the activity monitor, it would make for a quick and easy solution.
Call method in thread:
[NSThread detachNewThreadSelector: #selector(loadMethod) toTarget:self withObject:nil];
See following for more details:
http://iphone.zcentric.com/?s=UIActivityIndicatorView