KVO rocks. Now how do I use it asynchronously? - iphone

I am sold on KVO but if used in the obvious way it is synchronous. I would like to use it in a situation where I am firing off many KVO messages in rapid succession and it is causing my app to grind to a halt as the KVO messages are handled. Can someone suggest an approach - perhaps using NSOperation or NSThread - that will work here?
My goal is to retain the decoupled, flexibility of KVO if possible.

KVO is inherently single threaded in that the KVO notifications will be delivered on the same thread as the change.
Of course, UIKit and Cocoa both really only want you to be diddling UI elements on the main thread.
Thus, if you are doing asynchronous operations, you are most likely using threads and, if so, already have a synchronization issue in that you need to get the notifs from some thread to the main thread.
And therein lies the key. Instead of blindly forwarding each change notification as it comes in, you can coalesce the change notifications before passing them on to the main thread.
There are a variety of means via which you can do this. The specific solution is going to be quite unique to your application, most likely.
Personally, I try to avoid coalesce-and-forward of fine grained operations. I find it far simpler to tell the main thread that a particular sub-graph of objects have changed. More likely than not, the drawing code that will then make the changes visible to the user is going to need to redraw related state and, thus, related changes will be automatically reflected.
The key, as you have surmised, is to throttle the notifications so you don't bog down app responsiveness (or destroy the devices battery life).

Use the Receptionist Pattern as recommended by Apple https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/ReceptionistPattern/ReceptionistPattern.html

Check out NSNotification. It's not quite the same thing, but you can fire off notifications on background threads (with a little bit of research and work). You can maintain the nice decoupling and fire-and-forget behavior.

Related

Data driven view iOS app

I am new to objective-c/cocoa programming. I am making an application which is to constantly sync with a server and keep its view updated.
Now in a nutshell, heres what I thought of: Initiate an NSTimer to trigger every second or two, contact the server, if there is a change, update the view. Is this a good way of doing it?
I have read elsewhere that you can have a thread running in the background which monitors the changes and updates the view. I never worked with threads before and I know they can be quite troublesome and you need a good amount of experience with memory management to get most out of them.
I have one month to get this application done. What do you guys recommend? Just use an NSTimer and do it the way I though of...or learn multithreading and get it done that way (but keep in mind my time frame).
Thanks!
I think using separate thread in this case would be too much. You need to use threads when there is some task that runs for considerable amount of time and can freeze your app for some time.
In your case do this:
Create timer and call some method (say update) every N seconds.
in update send asynchronous request to server and check for any changes.
download data using NSURLConnection delegate and parse. Note: if there is probability that you can receive a huge amount of data from server and its processing can take much time (for example parsing of 2Mb of XML data) then you do need to perform that is a separate thread.
update all listeners (appropriate view controllers for example) with processed data.
continue polling using timer.
Think about requirements. The most relevant questions, IMO, are :
does your application have to get new data while running in background?
does your application need to be responsive, that is, not sluggish when it's fetching new data?
I guess the answer to the first question is probably no. If you are updating a view depending on the data, it's only required to fetch the data when the view is visible. You cannot guarantee always fetching data in background anyway, because iOS can always just kill your application. Anyway, in your application's perspective, multithreading is not relevant to this question. Because either you are updating only in foreground or also in background, your application need no more than one thread.
Multithreading is relevant rather to the second question. If your application has to remain responsive while fetching data, then you will have to run your fetching code on a detached thread. What's more important here is, the update on the user interface (like views) must happen on the main thread again.
Learning multithreading in general is something indeed, but iOS SDK provides a lot of help. Learning how to use operation queue (I guess that's the easiest to learn, but not necessarily the easiest to use) wouldn't take many days. In a month period, you can definitely finish the job.
Again, however, think clearly why you would need multithreading.

Running C code in an Objective C (Cocoa) Thread (for iOS)

First of all, I am a a very new Objective C/Cocoa iOS Developer but I've written C/C++ applications before.
So I managed to run the Rabbitmq-c (http://hg.rabbitmq.com/rabbitmq-c/) client inside my iPhone App, and I can connect to Rabbitmq directly from my app and even consume a queue item. So all's good.
Now my problem is, my iPhone app needs to use the rabbitmq-c library to poll for incoming messages in from the server. Probably there will be, an almost infinite while loop.
Do I have to take this to a new thread? Ideally, I want to wrap the rabbitmq-c class as an Async objective C class and use NSNotification (or something similar) to notify my UI. I'm a bit leery of creating a new thread, as I read about stuffs like Runloop etc can solve a lot of problems without using an extra thread.
What is the best way for me to go about this? Any examples of code or directions would be helpful. Please remember, I am not dealing with an Objective C code/Coca rabbitmq library here, I'm using C code inside my iPhone app.
Thanks
Subrat
don't block the main thread with your server polling.
since the operation never ends, create your own thread and run loop for this server polling. you can potentially use the run loop (each thread has one) instead of the infinite while. the alternatives involve regularly spawning threads. it's easiest to just use one thread for this.
once you have an update, post the notification (if you choose NSNotification) from the main thread -- UIKit is meant to operate from the main thread only.
for samples, i'd begin with samples related to NSRunLoop and CFRunLoop.
good luck
You can also create custom delegates for updating the UI, or the stuff related to UIKit.
Notifications might be a little easier to code and offer the advantage that multiple objects can observe one notification. With delegates, such a thing cannot be done without modifying the delegating object (and is unusual).
Some advantages of delegating:
The connection between delegating object and delegate is made clearer, especially if implementing the delegate is mandatory.
If more than one type of message has to be passed from delegatee to delegate, delegating can make this clearer by specifying one delegate method per message.
Or other way is to write method to receive messages. This method can have infinite loop.
Later you can put this method in background thread like this.
[self performSelectorInBackground:#selector(receiveMessages) withObject:nil];

Will the system send an NSWillBecomeMultiThreadedNotification when I create POSIX threads?

I tried it, but I think this notification isn't coming. Is that the normal case?
No, this notification is sent by NSThread. If you're using ordinary pthreads, it won't be sent.
From the docs:
Protecting the Cocoa Frameworks For
multithreaded applications, Cocoa
frameworks use locks and other forms
of internal synchronization to ensure
they behave correctly. To prevent
these locks from degrading performance
in the single-threaded case, however,
Cocoa does not create them until the
application spawns its first new
thread using the NSThread class. If
you spawn threads using only POSIX
thread routines, Cocoa does not
receive the notifications it needs to
know that your application is now
multithreaded. When that happens,
operations involving the Cocoa
frameworks may destabilize or crash
your application.
To let Cocoa know that you intend to
use multiple threads, all you have to
do is spawn a single thread using the
NSThread class and let that thread
immediately exit. Your thread entry
point need not do anything. Just the
act of spawning a thread using
NSThread is enough to ensure that the
locks needed by the Cocoa frameworks
are put in place.
If you are not sure if Cocoa thinks
your application is multithreaded or
not, you can use the isMultiThreaded
method of NSThread to check.
It should also be noted that 'times have changed' since NSWillBecomeMultiThreadedNotification was added to Foundation. Multi-threaded programming is now much, much more common. It's now entirely within the realm of possibility, even likely, that you'll never see this notification posted in an app. Modern apps become multi-threaded very early in their life, possibly before any part of your code is ever executed. Also from the documentation:
If you are developing a Cocoa library,
you can register as an observer for
the
NSWillBecomeMultiThreadedNotification
if you want to be notified when the
application becomes multithreaded. You
should not rely on receiving this
notification, though, as it might be
dispatched before your library code is
ever called.
I'd use [NSThread isMultiThreaded] instead of relying on NSWillBecomeMultiThreadedNotification.

Best practices for Singletons and Notifications on the iPhone

Just to give background for my situation, I have a manager singleton that pulls data from a webserver and provides access to the downloaded data. I have several types of views that will consume this data, but only one view at any time will need to receive events.
I was just wondering what people prefer to use when they need to get events from a singleton. Do you use NSNotificationCenter, Target/Action, or delegate?
Thanks for any help.
Are you really, really sure only one view needs to receive events? For instance, you don't have a master view that would need access to the same update that a subview was notified about?
If you truly have only one view controller needing updates at a time ever, I might use a delegate approach. Here's something to consider - what happens if you are in the middle of receiving an update and the user change screens... is that OK? would you cancel the request?
Anything more than one, or if that in-flight changing delegate scenario has issues, then you may well be better off with a notification that anyone can hook into. It's best to keep the notification light with some kind of reference to the change and have the receiver have to look up the altered data.
If there are going to be a large number of events, then you want to stay away from NSNotifications.
For the least amount of overhead I would go with the delegate pattern, although I don't think that target/action has much more overhead than delegates.
Try your favorite way and if there is a problem profile or try a different approach.
I usually start with the easiest to get implemented. For example I once tried to use notifications for some interface code I had written years ago but with 30-60 updates/second the whole interface bogged down unacceptably so I went with delegates which fixed the problem.

NSNotificationCenter vs delegation( using protocols )?

What are the pros and cons of each of them?
Where should I use them specifically?
The rule of thumb here is how many clients would like to be notified of an event. If it's mainly one object (e.g. to dismiss a view or to act upon a button clicked, or to react to a failed download) then you should use the delegate model.
If the event you emit may be of an interest to many objects at once (e.g. screen rotated, memory usage, user login/logout), then you should use the NSNotificationCenter.
Their purposes are different:
Notification is used to broadcast messages to possibly several recipients unknown from the sender.
Delegation is used to send messages to a single known recipient acting on behalf of the sender.
Notifications are generally better for notifying the UI of changes the occur on other threads as well. Apple's documentation strongly discourages the use of delegates across threads where possible, both for stability and performance reasons. On the Mac, they suggest using Bindings, but since they don't exist on the iPhone, notifications are probably your next best bet.
Considering the performance is a good idea (delegation better for small number of notified objects, notification centre better for larger number of objects, or is it? run a profiler) but I think a more important factor since you are talking about Objective-C and less likely to be talking about the really high performance parts of your code base, which are likely to be written in C, is reducing compile-time dependencies between modules.
There is nothing to stop you having an array of delegates rather than a single delegate.
I might use NSNotificationCenter only for status of any network stack components I make and any custom device status monitoring interfaces. But for most coupling, not to do with global status of the app, I think it is clearer to use normal interface contracts in Objective-C in most cases and easier to folow for the people coming after you than to use NSNotificationCenter. In fact I have never used NotificationCenter for my own custom events and prefer to use delegates for ease of code comprehension by someone else reading my code.
And finally, of course with notifications to/from the standard API you don't have choice and must use whichever of the two methods Apple proscribe for a given event.
Notifications are better for decoupling UI components. It allows you to plug any view without any modification in your controllers or models. Definitely better for loosely-coupled design.
But for the performance between delegation and notification, you need to think about the frequency of the call.
Delegation might be better for more frequent events, notifications are better for less frequent events but more recipients. It's up to project what to pick.
An option in between those two is using the observer pattern, without NSNotificationCenter. Look at my Objective-C implementation here.