The UIView docs say "Manipulations to your application’s user interface must occur on the main thread". Despite this, in my tests so far I have found that repositioning a view using setFrame from a background thread does work.
Can anyone confirm whether setFrame is thread safe?
All UI updating code ( including setFrame ) must be done on the main thread. I think you already know the answer to this :)
It may work in a background thread, but it doesn't mean it's safe.
To answer the question more directly, Apple pretty much says UIView code is not thread safe.
If you need to update the UI from a different thread, invoke it on the main thread using Grand Central Dispatch.
Here's a kind of similar question # stackoverflow
Related
OK, normally I know it's not ok. But what if I know I'll never attach that view to the actual UI hierarchy - it's only used to generate a snapshot, or compute something, or whatever.
If it IS ok, how do I silence the Main Thread Checker: UI API called on a background thread console dump? (that console output is the reason I'm paranoid about doing this in the first place, now).
But what if I know I'll never attach that view to the actual UI hierarchy
I don’t think it matters what you know. The main thread checker presumably knows more. In the interface or not, UIKit interface objects are inherently not threadsafe. Do this on the main thread.
I'm working to improve the performance of images displayed to the user. I have removed alpha blending and am assigning a scaled/correctly sized image to the UIImageView already along with some caching. However, also as a part of this I am thinking of moving setHiglightedImage: call to background thread.
ImageView is wrapped in UIKit which says that any modification to layouts should be done on main thread. However while assigning an image with a highlightedImage we're not triggering any layout changes or invoking any constraints. Would this be a valid change that doesn't violate UIKit rules? Are there going to be any exceptions thrown because of this?
I don't see any problems or warnings by debugger while running this so far on background thread. Also the apple's official documentation (here and here) around UIImageView doesn't specify anything about this being on background thread. I tried searching more online about doing this, but couldn't really find anything helpful
Is there any reason for [UIImageView setHighlightedImage:] to not be on background thread? Will it have any performance benefits?
setHighlightedImage is changing the user interface . You can not run it on a background thread.
In a Cocoa application, the main thread runs the user interface, that
is, all drawing and all events are handled on the main thread. If your
application performs any lengthy synchronous operations on that
thread, your user interface can become unresponsive and trigger the
spinning cursor. To avoid this, you should shorten the amount of time
consumed by those operations, defer their execution, or move them to
secondary threads.
Apple Documentation
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.
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.
I have written a little define called ensureInMainThread (and I use it quite a bit). However, I'm not sure exactly which user interface methods require being called on the main thread. What about setNeedsDisplay and setNeedsLayout? What is the rule of thumb for methods that need to be called on the main thread in iOS 5.x?
These questions are related (some low quality questions and answers, and some very case specific), but I would like a comprehensive, single good answer:
UIView setNeedsDisplay Not on main thread?
Does UIView's -drawRect: have to be called on the main thread?
Make UIImage From UIView but NOT in the main thread
As of iOS 4.0, some user interface updates can be performed on a background thread:
Drawing to a graphics context in UIKit is now thread-safe. Specifically:
The routines used to access and manipulate the graphics context can now correctly handle contexts residing on different threads.
String and image drawing is now thread-safe.
Using color and font objects in multiple threads is now safe to do.
David Duncan confirms this in his comments here.
Beyond that, pretty much everything else regarding UIKit is not considered threadsafe, so you should make sure you are interacting with it on the main thread in those cases.
As an aside, I do prefer my block-based implementation of a "always run on the main thread" function over the macro you link to, because I like the explicit wrapping of code that needs to be run on the main thread.
Rule of thumb: Anything that updates the interface must be on the main thread.
With iOS 12, if you call setNeedsDisplay from a background thread, you get the following assert:
Main Thread Checker: UI API called on a background thread: -[UIView setNeedsDisplay]