I am using the SVProgressHUD progress indicator, and it works very well most of the time.
I am having some issues with it not appearing as expected in certain situations, however.
For example, I would like to show the indicator when I click a button on a view. This button launches a synch call to a web service. At the end of the svc call, the SVProgressHUD indicator window is removed.
What is happening is - the progress window pops up and disappears immediately after the svc call finishes.. even though my code to display the SVProgressHUD window is the first line in my 'buttonPressed' action.
I think there are some UIView concepts I am missing here... any insight?
Thanks
You shouldn't attempt to show user interface elements on a background thread. If you're in a background thread, access the main thread to update your interface.
Related
I have the need for an activity indicator view in my app when different views are loading and when data is being retrieved. The problem is the mainVC (where I would place the indicator) is not always aware of when processing is happening so it can start the indicator but it cannot stop it.
e.g. the mainVC loads and then programatically adds a new VC - this VC in turn asks a model to retrieve - it displays data etc. So this newly added VC actually knows when processing is finished and it does not have access to the indicator view (although the indicator is visible at the top).
I was thinking of using notifications - is this the best way of handling this situation?
I'd recommend looking at the brilliant MBProgressHUD library:
https://github.com/matej/MBProgressHUD
It's a very simple set of classes you can use to display loading and progress views that can be accessed by all view controllers in your app. Basically, you can set it up in your app delegate and add it to your app window.
Every view controller can then access the progress view from the delegate and show/hide it when required. It comes with an example project and code - it's very easy to use and customise.
Notifications are one half of the solution. You have to combine them with a persistent object so that you can also get the current state at all times. E.g., when a view controller is about to appear, it needs to read the initial "downloading" state from somewhere, because the VC might have been created after the "start" or "end" notification was sent.
Then, while the VC is alive, it can simply respond to notifications to update the indicator.
This design is particulary important for views, which run the risk of getting unloaded/reloaded all the time.
I tried to show activity indicator while heavy UI update.
My initial failed attempt was
show activity indicator at view1
pushViewController (creating view of this viewController takes a long time)
when view1's viewDidDisappear(when pushViewController's push animation
occurs), hide activity indicator
Problem was even though I did call "show activity indicator" before pushViewController, activity indicator wasn't showing because of heavy UI which occurred in creating the view of viewController which was being pushed.
I changed strategy as bellow and it works and I don't get why.
pushViewController
show activity indicator at viewDidLoad of viewController
do the heavy UI loading at viewDidAppear and hide indicator
I was under impression the reason that the indicator didn't show up with the first method was due to heavy UI process.
Please refer to the discussion at link.
(iphone) showing activity indicator before heavy ui updating
If too much UI update on queue caused delayed UI update(indicator not showing up), why the 2nd method makes a difference?
I know that viewDidLoad gets called only when view gets created.
And viewDidAppear gets called when view actually shows up on screen.(hence can be called multiple times)
But is there a fundamental difference which would explain why the 2nd approach of using viewDidAppear works in my situation?
And is there a UI update thread apart from the so-called main thread?
Or main thread is the UI update thread?
Thank you
First I want to make sure that you're updating UIKit UI on the main thread. This is a must, you shouldn't have to specify a thread when working with UIKit, unless you say to use the main thread, but I think that would be redundant.
I would start the activity indicator in viewWillAppear. Then load everything else in viewDidLoad.
IPhone SDK - Leaking Memory with performSelectorInBackground
seems to suggest you can actually pushViewController in background thread.
But I get a warning from stackoverflow people that I shouldn't do this.
eg. (iphone) start timer from background thread?
is pushViewController considered "UI updating"?
(because I know that UI updating should be done in main thread only)
If it is so,
when a viewController takes a while to load, and want to show an indicator while loading.
What is my option?
Couple of strategies here.
1) BEFORE you do the push, but at the point you know you are going to do it, bring up a suitable activity view on the current view. I do this in some apps where you click on a row in a table but the pushed view has to do some web comms that takes time, so I leave the table cell highlighted in blue and add a white spinner to the left of the disclosure indicator. Works well.
2) Use lazy loading to get the new view controller on screen quickly, but defer the heavy code until after it has loaded so that the new controller can look after it's own activity view. By lazy loading I mean you should do as little as possible in the init method and make careful use of viewdidload / viewwillappear / viewdidappear etc to spread the work out and get an activity view on screen as soon as you can.
I develop an eclipse plugin, and I created an progress view which indicates where the work runs. Everything works correctly, but I have a question. When I made this view an stop button appeared on it. But I haven't found any listener to control this. But the best should be that if there is an pause button within the view insted of the stop button. Please give me some idea! Thanks!
The Job where you do the work is given an IProgressMonitor when its run method is called. This progress monitor has an #isCanceled() method. I believe that when you click the stop botton in the progress view, then the isCanceled method on your progress monitor should return true.
I want a button in my navbar which lets the user refresh the contents of a tableview. The tableview is already populated and once the user presses the refresh button, I want to show a UIActivityIndicator while I fetch the items to be displayed on the table.
I tried putting a [indicator startAnimating] before calling the method to get the new data of the table (where indicator is of type IBOutlet UIActivityIndicator* and mapped to a control in IB) but the indicator does not show up. Instead, the navbar refresh button is in the pressed position till control returns from this IBAction method.
How can I show the indicator while the method execution completes?
Thanks.
You need to get the new data for the table in the background. That could be an asynchronous network call or a thread depending on what your refresh code does but the UI kind of assumes that button presses are pretty much instantaneous.
You'll note that your whole UI locks up (not just the refresh button), so this is a good thing to do anyway albeit much harder to implement.