UISegmentedControl setTitle:forSegmentAtIndex:, explicit dispatch to main thread needed? - objective-c

I have a notification which can be posted on a background thread. This notification eventually leads to calling setTitle:forSegmentAtIndex:, which is UISegmentedControl, part of the UIKit.
Should it be assumed that I need to wrap this setTitle:forSegmentAtIndex: call with a async call to main thread, or will some lower lying Cocoa code automatically dispatch anything like setTitle:forSegmentAtIndex: to the main thread?

Always dispatch code that modifies a UI control to the main queue. Always.

Related

Objective C Multi thread NSWindow alternative?

I keep crashing when doing:
[NSWindow orderFront:nil]
From a thread I spawned in my app. Is working with UI elements from thread not possible like GTK+?
Edit:
oh goodness just found this:
https://stackoverflow.com/a/11900929/1828637
So apparently I cant use NSWindow from another thread, so objc is out, is it possible to do multi thread window stuff with CoreFoundation instead? I have to do from thread so Im looking for alternative way
You can only work with UI elements on the main thread.
I use GCD to ensure all UI activities are running on the correct thread:
dispatch_sync(dispatch_get_main_queue(), ^{
// Do your UI updates!
});
See why:
In Cocoa Touch, the UIApplication i.e. the instance of your application is attached to the main thread because this thread is created by UIApplicatioMain(), the entry point function of Cocoa Touch. It sets up main event loop, including the application’s run loop, and begins processing events. Application's main event loop receives all the UI events i.e. touch, gestures etc.
UI interaction always has to be done on the main thread.
You can simply dispatch the code in question with GCD on the main thread:
dispatch_async( dispatch_get_main_queue(), ^(void)
{
[NSWindow orderFront:nil];
});

Suspend a thread from another thread in VB.NET

I have a window which runs from a thread, let's call it MainThread, and a background thread which performs other non-graphical tasks.
Sometimes the background thread will call the MessageBox.Show(...) method (which is modal and stops the background thread). Before this call, I would like to suspend the MainThread and resume it after so that my MainWindow's controls are disabled while the messageBox is shown.
So my questions are:
How do I access the mainThread from the backgroundThread?
How do I suspend/resume it (Considering Thread.suspend is depricated)?
Instead of suspending the main thread, you could use Control.Invoke (Windows Forms) or Dispatcher.Invoke (WPF) to actually show the message box on the main thread, but call it from your background thread.
In addition to providing the behavior you wish, this would also have that advantage of allowing you to parent your message box to the proper Window, which would give the proper modal message box behavior.

performSelectorOnMainThread and waitUntilDone, for NSURLConnection

I am not clear about what does waitUntilDone do, but I found this thread:
What is the significance of WaitUntilDOne in performSelectorOnMainThread?
which makes me a bit clear, however, if I perform some selector which makes NSURLConnection(which is asyncrhonous) and waitUntilDone set to YES, what will happen then? It will wait for the method to execute, but the method actually does some asynchronous operation(ie NSURLConnection), then what is the impact?
Thanks!
NSURLConnection is asynchronous. Your code runs on the main thread, and it makes delegate calls to you as the download progresses. You don't need to, and should not, run an NSURLConnection from a background thread.
If you DO have code that needs to run on a background thread, you can use the preformSelectorOnMainThread method to send messages from your worker thread to the main thread. One common reason to do this is that you can't update the UI from a background thread. You'd invoke a method to update the UI on the main thread.
The flag waitUntilDone controls what happens after the performSelectorOnMainThread call. If waitUntilDone is false, your background thread continues on with the next line without waiting for the code on the main thread to finish.
If waitUntilDone is true, your background thread will block until the main thread finishes performing the selector that you sent it.

Cancelable loading in background thread

I have a window that displays some data in an NSTableView. This data is loaded in the background. The data-loading-thread is started in the windowDidLoad: method. If the window is closed before loading has finished, the background thread should be cancelled. I do this by signalling the thread in the windowWillClose: delegate method and waiting for the background thread to finish.
Now this all works perfectly. But I have one problem: How can I update the data in the table view? I have tried calling reloadData via performSelectorOnMainThread: but this leads to a race condition: The reloadData call is sometimes queued on the main thread after the window close command, and will execute after the window has closed, and everything goes up in flames.
What's the best way to control and communicate with a background thread?
Well, you know, this is exactly what makes the use of threading complex: you always face synchronization issues.
What I suggest is, instead of calling [tableView reloadData] from your thread, simply signal your controller (by calling a method controllerShouldReloadTable) and let your controller do the check if windowWillClose has been called or not. There might be a chance that your controller has been also released by the time controllerShouldReloadTable, and to fix this you will definitely need to retain the controller from the secondary thread.
On a side note, I would cancel the thread in viewDidUnload (for symmetry).
Most important: I would use asynchronous calls and a delegate class so that the whole multithreading issue is solved at its root.
EDIT: Sending asynchronously a request will not block the sending thread waiting for the response. Instead, asynchronous send (for NSURLConnection is called start) immediately returns (so, no blocking) and when the response is received, a delegate method will be called (i.e., connectionDidFinishLoading:) so that you can updated the model and the UI. Take a look at NSURLConnection docs, but as usual, I strongly suggest using [ASIHTTPRequest][2], which has many advantages.

Cocoa - NSThread and First Responder

When I start a 2nd background thread and pause the main thread, will my First Responder still be in action? For example I have an overwriting method called -flagsChanged and was wondering if it would still be active if the main thread is offline.
Thanks,
Kevin
Don’t pause the main thread since the main thread is responsible for handling events and your application UI will become irresponsive. If the main thread is paused, it won’t handle events, hence it won’t dispatch key events to the first responder.
If you think you need to pause the main thread, you probably need to redesign your program so that the behaviour that requires sleeping (if it does require sleeping) is offset to a secondary thread. If you need to update the user interface from a secondary thread, you should use -performSelectorOnMainThread:withObject:waitUntilDone:.