-[GCKCastDeviceProvider stopDiscovery] must be called on main thread - ios

In react native using the google cast sdk 3 everything we reload the app get crash and the error is -[GCKCastDeviceProvider stopDiscovery] must be called on main thread
We put all the code inside:
dispatch_async(dispatch_get_main_queue(), ^{
// my code block
});
We also check if really on the main thread with this:
if ([NSThread isMainThread]) {
NSLog(#"on main thread");
}

Based from this release note, all methods in CastContext that your app calls must be called from the main thread, otherwise an Exception will be thrown. Also, this documentation stated that all SDK methods must be called from the main thread.

Related

-[UIApplication delegate] must be called from main thread only

This warning leads to a serious problem cause I really can't call the delegate outside of the main thread using Xcode 9 beta 2. Strange thing is that this was working when I was using Xcode 8.3.3.
Also I thought it would only be good practice to call delegates from main thread only, isn't it? So why is this causing the app to crash now?
Just call it from the main thread like this.
Objective-C
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication delegate] fooBar];
});
Swift
DispatchQueue.main.async {
YourUIControlMethod()
}
Reaching out to your app delegate like this, is a hint that your architecture could use a little cleanup.
You can call delegates from any thread you want. You only need to make sure you're on the main thread for UIKit calls.
Or that you're on the correct thread your CoreData objects expect. It all depends on the API contract your objects have.
In Swift, you could also use DispatchQueue.main.async to call the UI controlling method from the main thread
DispatchQueue.main.async {
YourUIControlMethod()
}

iOS - When To Call UI Changing Functions In The Main Thread

Every time I make an API call to my server to get data, I already know that I have to use the following block to execute UI changing commands because my API call executes in the background thread:
dispatch_async(dispatch_get_main_queue(), ^{
//do UI stuff
});
However, what if I have a function that does UI changing stuff outside of the API call block? For example:
-(void)doALotOfUIChanging
{
//do a lot of UI changing
}
In my API call block, do I need to call that UI changing function in the main thread like so?:
[apiObject getDataFromObject:my.Object successCallback:^(Array *data)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self doALotOfUIChanging];
});
}
errorCallback:^(NSString *error)
{
NSLog(#"%#", error);
}];
Or do I not have to call it in the main thread since the function is already outside of the API call block like so?:
[apiObject getDataFromObject:my.Object successCallback:^(Array *data)
{
[self doALotOfUIChanging];
}
errorCallback:^(NSString *error)
{
NSLog(#"%#", error);
}];
I also have functions that perform segues to other view controllers, so I'm also wondering if I should call them in the main thread as well. I'm doing some code clean up and I don't want to have to constantly rewrite the dispatch_async function in situations that I might not have to, so any help or advice would be greatly appreciated. Thanks.
Short answer: Yes you should update your UI on main thread.
Threads and Your User Interface
If your application has a graphical user interface, it is recommended
that you receive user-related events and initiate interface updates
from your application’s main thread. This approach helps avoid
synchronization issues associated with handling user events and
drawing window content. Some frameworks, such as Cocoa, generally
require this behavior, but even for those that do not, keeping this
behavior on the main thread has the advantage of simplifying the logic
for managing your user interface.
There are a few notable exceptions where it is advantageous to perform
graphical operations from other threads. For example, you can use
secondary threads to create and process images and perform other
image-related calculations. Using secondary threads for these
operations can greatly increase performance. If you are not sure about
a particular graphical operation though, plan on doing it from your
main thread.
Reference:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/AboutThreads/AboutThreads.html
First of all you should never use self inside a block . You can use __weak yourClassName *weakSelf = self instead.
Regarding your problem, all UI changes should be done on main thread. So you need to do this :
[apiObject getDataFromObject:my.Object successCallback:^(Array *data)
{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf doALotOfUIChanging];
});
}
Hope it helps. :)

Any way to guarantee a code will always be executed on the main thread?

Excuse me if this question sounds stupid but this is beyond my knowledge of Objective-C.
I am developing some classes that have to always be executed on the main thread.
Ok, I can pollute my code with a bunch of
dispatch_async(dispatch_get_main_queue(),
^{
});
but I would like to know if there is something I can do to prevent the methods of this class from running on other threads that is not the main or to at least warn during debugging, compiling, or whatever if they are used not on the main thread.
thanks
I sprinkle such methods with my BLOCK_UI() macro from https://github.com/gradha/ELHASO-iOS-snippets. At runtime the macro will assert if the method is not running on the main thread. The macro goes away in release builds because I consider calling such an API in the background a programmer error, but if you want to make an API which is permissive with the programmer, you can also check for the main thread and invoke yourself in the main thread if needed. Example:
if ([NSThread isMainThread]) {
[self do_request:url];
} else {
[self performSelectorOnMainThread:#selector(do_request:)
withObject:url waitUntilDone:NO];
}
You can always check via the helpful API "[NSThread isMainThread]"

NSOperation is not happening in background thread

I created an NSOperation subclass to handle some zip archive operations. No matter what, if I override -start or -main this block of code always happens:
if ([NSThread isMainThread]) {
NSLog(#"I am in the main thread");
return;
}
Any idea what's going on?
I've tried adding this block:
- (void) start { //also tried overriding main
if ([NSThread isMainThread]) {
NSLog(#"In main thread, trying again");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self start];
});
return;
//hard working code etc...
//cpu intensive zip operations...
}
But this causes a crash, an EXC_BAD_ACCESS violation pointing at the dispatch_async line.
No matter what, if I override -start or -main this block of code always happens:
The main operation queue runs on the main thread. From the docs for +[NSOperationQueue mainQueue]:
The returned queue executes operations on the main thread. The main
thread’s run loop controls the execution times of these operations.
So, running in another thread is a matter of what queue you add the operation to, not how you write the operation's code. If you want your operation to run on a different operation queue, you'll need to create a queue of your own using
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
You can find an example in Adding Operations to an Operation Queue in the Concurrency Programming Guide.
But this causes a crash, an EXC_BAD_ACCESS violation pointing at the dispatch_async line.
It sounds like -[NSOperation start] probably isn't re-entrant. Your code effectively executes the same method on two different threads. In fact, look at the docs for -start, it's obvious that your code won't work:
You can call this method explicitly if you want to execute your
operations manually. However, it is a programmer error to call this
method on an operation object that is already in an operation queue
or to queue the operation after calling this method. Once you add an
operation object to a queue, the queue assumes all responsibility for
it. [Emphasis added. -Caleb]
In other words, don't do that.

dispatch_async on main_queue?

I have seen this code snippet:
dispatch_async(dispatch_get_main_queue(), ^{
[self doSomeNetworkStuff];
});
This doesn't look like making much sense to me.
EDIT: To clarify the conditions of my question:
The call to dispatch_async is performed from the main thread.
The sent message doSomeNetworkStuff is the heavy lifting worker task.
... and is not only the UI-updating task.
Dispatch, sure, but using the main queue would just pull the dispatched task back to the ui thread and block it.
Please, am I missing something?
Thanks.
dispatch_async lets your app run tasks on many queues, so you can increase performance.
But everything that interacts with the UI must be run on the main thread.
You can run other tasks that don't relate to the UI outside the main thread to increase performance.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Add some method process in global queue - normal for data processing
dispatch_async(dispatch_get_main_queue(), ^(){
//Add method, task you want perform on mainQueue
//Control UIView, IBOutlet all here
});
//Add some method process in global queue - normal for data processing
});
Swift 3:
DispatchQueue.global(attributes: .qosBackground).async {
print("This is run on the background queue")
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
}
}
when you want to do some Webservicecall or something you dispatch a async call like this below:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//Call your webservice here , your app will not freeze at all
});
Now, suppose you want to update or push a ViewController from your dispatched thread, if you directly push viewcontroller from this, app will or may get crashed,as such UI updates should be done in main thread of app,below is the answer for this then.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//Call your webservice here , your app will not freeze at all
//To update UIFrom dispatched Thread:
dispatch_async(dispatch_get_main_queue,^{
//Push view controller here
});
});
for detail visit : blackberrymastercracks.blogspot.in
It depends from where this code is being called. Means if its calling from main queue then it doesn't make sense. (Note: it will not cause a crash but it will just add a task in main queue ).
If this code is written in background thread then this is a converging point for the application. Like you are getting data from web service in background thread then wants to update it on UI then you can call it.
-(void) backgroundThreadFunction {
//Some stuff on background thread.
dispatch_async(dispatch_get_main_queue(), ^{
//Wants to update UI or perform any task on main thread.
[self doSomeNetworkStuff];
});
}
You can find more details over apple documentation https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
or from this answer also https://stackoverflow.com/a/19822753/505735
Do post me if its still unclear. I will write a detailed answer.
You'll usually see that syntax inside of another dispatch_async call that runs on a background thread. This is because all updates to the UI should happen on the main thread, not in the background.
I lost track of this question, but as it still gets traction, I'll post an answer to this (using swift)
Assumptions: I do know that UI work has to be done on the main thread.
//
// We are on the main thread here.
// The following will schedule the closure on the main thread after ALL other
// routines currently scheduled on the main thread are done.
//
DispatchQueue.main.async {
//
// So here we are back on the main thread AFTER all routines on the main
// thread have completed.
//
// If the following call does NOT dispatch onto a background thread
// it will block the UI and it was really bad programming.
//
// Thus, for now and for the benefit of the doubt, let's assume
// `doSomeNetworkStuff()` DOES dispatch to a background thread.
//
// This can only make sense if the the func `doSomeNetworkStuff()`
// relies on results of code paths following this current
// `DispatchQueue.main.async(... we are here ...)`.
//
// If `doSomeNetworkStuff()` does NOT depend on any other code paths:
// Why not directly scheduling it directly on a background thread?
// Which is unnecessary, as as stated above it MUST dispatch on to the
// background anyways.
//
// Moreover, there is few possibility that `doSomeNetworkStuff()` does
// depend on other codepaths, because `self` is already captured by
// the closure.
//
self.doSomeNetworkStuff()
}
Taking all this together IMHO the original code does not make very much sense. It could be replaced with:
// We are on the main thread here
self.doSomeNetworkStuff()
The original async dispatch onto the main thread to then dispatch to background should be wasteful and confusing (obviously).
Unfortunately I am not in the position anymore to try this out with the original code base.
Am I missing an idea here?

Resources