Ok to create UIView on background thread? - ios

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.

Related

UIImageView setHighlightedImage: does it have to be on 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

UIView setFrame thread safety

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

How to schedule an asynchronous task every 'x' seconds when main and background thread need same data?

I have an iOS application that has an NSTimer which fires every 5 seconds. This then posts a notification, telling several controllers that they must now recalculate some data and then update their UI.
When this all happens on the main thread, scrollviews can become jittery as the data is processed.
Using GCD, I have wrapped the code called when a notification is posted:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Code here
dispatch_async(dispatch_get_main_queue(), ^(){
// Reload tableviews and UI
};
};
Unfortunately, this leads in certain cases to several threads accessing the same instance variables. This causes my application to crash as sometimes it ends up mutating an array being enumerated in another thread.
Wrapping the code in a synchronised block prevents this.
When the user scrolls the tableview, several methods are called to calculate the height etc, on the main thread. The code within the background thread is working on the code needed by the main thread. As such, this can usually further cause crashes
I have tried setting the variables to 'atomic', but this doesn't solve the issue. Ideally, I don't want to have the main thread waiting on the background thread, but I am not sure how to best resolve this issue given that they need the same data?
This is pretty classic multithreaded programming issues. There are a number of ways to solve it with basic locks (#synchronized blocks), reader/writer locks, etc but the problem is often that you can't control when the user is going to scroll or take other action. If you #synchronize, you have to do it anywhere that data is touched, including your UITableView data source methods. That can lead to stuttering if the background processing happens to be in the middle of something.**
Personally, I would use an immutable snapshot mechanism.
Have the background thread produce the results, then include just the data the UI needs to display in the notification data as an immutable snapshot (copy). That way the background thread never modifies the data the UI is currently reading for display. How you would implement this is highly dependent on how much data you are talking about and the form it takes, but the safe way would be to have copies of your classes with readonly properties. Alternatively, you can use a "frozen" flag. Make a copy, then set frozen = YES on the copy. The UI thread will only ever see "frozen" or readonly objects coming from the background thread.
The benefit is the UI never causes the background thread to stall and there are no locks required. The downside is increased memory usage, though if the amount of data is large you can use copy-on-write mechanisms to allow the background thread and UI thread to share the data, even though logically the UI thread has a completely separate copy.
** Note: In most applications, you don't have this sort of continuous background processing going on so those apps can use simpler mechanisms. This is typically a form of message passing where the background thread finishes its task and "passes the message" to the UI thread (passes the results). At that point the background work is finished so there is no concurrent modification happening.

How to update the UI in background thread without using mainthread

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.

What Needs To Be on Main Thread?

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]

Resources