I have shown an UIAlertView from a thread, but the UI hangs and then shows UIAlertView after 2-3 seconds.
I can use dispatch_async(dispatch_get_global_queue... or performSelectorOnMainThread to fix this.
I want to know why the UI hangs when we present any UIAlertView on background thread.
On iOS, all UI operations have to performed on the main thread, you can't have UI operations (such as showing an UIAlertView) on a background thread. That's also the explanation why performSelectorOnMainThread: fixes the issue.
Here is a nice blog post on the topic and a link to the docs.
Related
On iOS, its well documented that the UI should never be updated from a background thread. Rather the main thread should be the sole interface to update the UI. My Question is why?
Is it because UIControls are not thread safe and hence there is always the possibility of main thread updating the particular control whilst its being tinkered with in a background thread? Is my understanding right?
Thanks
I think it has more to do with keeping the UI responsive, so iOS just prevents you from putting UI stuff in threads that aren't main.
You know you can use dispatch_async(dispatch_get_main_queue(), ) { //change UI here } from within a background thread to send your UI actions to the main thread.
When using a UIActivityIndicatorView, it is possible to add this view to your view hierarchy and start animating it.
After that you are completely save to block the main thread (not that this is a good approach), there is basically nothing that I know of, that could stop the activity indicator from spinning.
My question is:
How is this done? It seems like UIActivityIndicatorView uses its own thread for rendering.
Is this something that can be achieved with my own views?
I have a CoreAnimation animation that I want to keep playing while the main thread might be blocking for a couple of milliseconds.
How to do that? Thanks for any help or ideas!
//EDIT: To clarify my question: I want to know what Apple does to get UIActivityIndicatorView animating even when you block the main thread. When I trigger my own CoreAnimation and I block the main thread, the animation itself stops. Furthermore to the question what Apple does to achieve that under the hood, I want to know, if I can achieve this myself, with public API.
You best solution is to use a background thread for long processing while keeping the main thread only for display purpose. That way, you will be able to display your view without blocking and run your long precessing at the same time.
You can use Grand Central Dispatch (GCD) dispatch_async to run your long processing code on another thread and then call dispatch_async on the main thread to refresh your UI.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
// Your long processing code
dispatch_async(dispatch_get_main_queue(),
^{
// Refresh UI here
});
});
I have in the past seen a UIAlertView freeze momentarily during its animation, but not have anything else onscreen freeze (such as when deleting apps from a device...the other apps keep on wiggling). In my app right now I've got a UIAlertView freezing for a moment partway through its animation, but the Time Profiler in Instruments doesn't show the kind of CPU usage that would freeze the UI, and I can see other things happening in the UI behind the alert. What could cause this?
Often this type of thing is caused by showing the alertView in the action method of some control. If this is your case, use a dispatch block that shows the UIAlert (which you can prepare in the action routine), and dispatch it async to the main queue.
I am doing one application in which i got one HTML string in background thread. I want to load the webview using that HTML string in background.
If I load that web view on background, the app crashes. I don't want to load webview using main thread because on that i don't want to disturb the main thread. And i did the R&D in internet i got one possibility using GCD.I think that one also involved in main thread. SO please let me know how to update the UI in background.
You can not. UI must always be updated from the main thread. Whatever your reason for not wanting to do it from the main thread, that reason is invalid.
No. You cant update UI in other thread then main.
A UIViewController takes about half a second to load its contents and appear on screen. How can I make them all load in the background and appear when they're ready?
There is a LazyTableImages sample on the Apple developer site.
It shows how to perform the heavy lifting in a background thread and update the UI on the main thread.
PerformSelectorInBackground:withObject: is a possible solution, although a more modern method would be to use asynchronous blocks. You can run code on the main thread from within these blocks to update the UI Safely.
The Concurrency Programming Guide is a good place to find more information and examples of this.
A Background Thread cant update the UI,you can perform all the processing logic in background thread and call the main thread for UI update
Example to load a tableView with Data ,use the background thread to process everything and load the Data, call [tableView reloadData] using the main thread, see Grand central Dispatching to know how to Work with Threads in IOS..
Hope it Helps
Create a GCD queue to process your work in a background thread (read the docs, because my "create" label and options may not be what you want).
You send it to the queue asynchronously, meaning that the call to dispatch_async will make appropriate arrangements for the block of code you give it to run in another thread and it will then return back to you "immediately."
All the work in the block you give it will be executed on a separate thread. Note, at the end, you do another call, this time with the well know main queue. This arranges for that code to run in the main thread, which is mandatory for any UI work.
Also, you really should read the documentation on GCD and especially blocks, because there are memory and cycle considerations. Good luck.
dispatch_queue_t workQ = dispatch_queue_create("bgWorkQ", 0);
dispatch_async(workQ, ^{
// This code is now running in a background thread.
// Do all your loading here...
// When ready to touch the UI, you must do that in the main thread...
disptach_async(dispatch_get_main_queue(), ^{
// Now, this code is running in the main thread.
// Update your UI...
});
});
dispatch_release(workQ);
The easiest way is to use NSObject's - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg You just pass it a selector and it will happy in the background and not block your UI. Be aware however that there are rules to background threads.
You shouldn't update your UI from the background thread. And you need to make sure the methods you're calling are thread safe.