iOS – Download Facebook data in background with GCD - objective-c

My situation is that every time when my app becomes active I need to sync some data from Facebook. This sync should be made in the background and should not lock the GUI (thus it should not run on the main queue).
So in my - applicationDidBecomeActive: method I have this code:
dispatch_async(dispatch_get_global_queue(0,0), ^{
[[FacebookHelper sharedInstance] syncData];
});
FacebookHelper is a singleton class that takes care of all Facebook handling. In the FacebookHelper class I have implemented the Facebook delegate methods. But for some reason when I run the above code the Facebook delegate method - request:didLoad: (when the Facebook data is finished downloading) is never called. Although if I run the same code with dispatch_sync it will finish (but then the GUI will be blocked).
Edit: Facebook SDK v2

Actually after analyzing the code I noticed it was an internal processing method that was done in the - request:didLoad: delegate method. So I just put that internal processing method inside a dispatch_async block and it performed nicely in the background.
Thanks for your help!

Related

How to run custom code in the main thread of Cocoa applications

I'm a windows developer and I'm having a hard time understanding the right way to run code in the
NSApplication's main thread.
Most of my code is running in a cvdisplaylink thread (it's an opengl app)
THe problem is that I can't call things like NSOpenPanel from it - it crashes the app and warns about only running stuff like this from the main thread.
It's fine, but the main thread is completely opaque as far as I understand, and I can only make it do things with events. The NSApp sendAction method sounded promising - because I could explicitly specify which method to call. But it didn't 'send' any thing, it just called this method directly from the same thread.
Am I understanding this right? Do I have to push some sort of a custom event (perhaps NSEventTypeApplicationDefined) to the main thread queue for this to work properly?
And if so, how to I respond to custom events like that?
Like this:
dispatch_async(dispatch_get_main_queue(), ^{
// do whatever
});
If what you want to do is to call a method of an Obj C object, the old school Cocoa way (which still works) is to use performSelectorOnMainThread:withObject:waitUntilDone:
E.g. to hide a window by calling its "orderOut:" method you would do this.
[theWindow performSelectorOnMainThread:#selector(orderOut:)
withObject:nil
waitUntilDone:NO];

mac in app purchases - receiving store kit responses different thread

I'm testing out in app purchases for my mac app, and I've noticed that the selectors productsRequest:didReceiveResponse: and paymentQueue:updatedTransactions: are getting called on a background thread (not the main/ui thread) when I request products or try to make a purchase.
I haven't seen any documentation warning about this, since that would mean updating UI from within these methods should not be done.
Has anyone else run into this? Should I just be calling performSelectorOnMainThread: within these methods to update the UI?
Ran into the same issue as it appears to behave just like an asynch call using NSURLConnection. I solved my particular issue by using the NSObject method call "performSelectorOnMainThread:withObject:waitUnitlDone:" Probably setting up NSNotification to be caught on the main thread of ViewController or WindowController would work as well.

Interrupted method when user pushes home button?

What happens when a user pushes the home button on the iOS device and the app is currently running a method: Will the method finish running or will the method be interrupted in the middle?
Like Maudicus wrote, applicationWillResignActive: is called on the application delegate, as well as applicationDidEnterBackground:. You should assume that any method that is currently running will be interrupted. If you want to ensure that a particular operation is performed, you should put it in one of the aforementioned methods.

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.

- (void)applicationWillTerminate:(UIApplication *)application

I found this method in a delegate file and inserted some code. The code never gets executed, even when the home button is pressed. When or how does this function get called?
You should use applicationDidEnterBackground method if your app and OS support multitasking.
From applicationWillTerminate docs:
For applications that support background
execution, this method is generally
not called when the user quits the
application because the application
simply moves to the background in that
case. However, this method may be
called in situations where the
application is running in the
background (not suspended) and the
system needs to terminate it for some
reason.