I find the Post notification and delegate function are very useful in iOS. Once I finish a task I can notify another piece of code to do something. I am sending out notices for others to do the work.
Post Notification is when you sending notice right away, whereas delegate sometime down the line it will send a notice.
In Android I know there's event Listener, but that's only passive listening. What about me actively sending notices? Does Android have that equivalent?
Handler which can be fired right away or with postDelay() you can fire them later
You could either use a Handler to get notified from a running Thread or the AsyncTask which does run some code and after it's finished it notifies the UI Thread.
You are probably looking for a way to thread your application? Where there are other "worker" threads that do long computations (or do buffered IO stuff). The way you would do this is by creating an AsyncTask. Within an AsyncTask, there is a "doInBackground" method that seems to be what "delegate" is in your question. "onPostExecute" will handle whatever's returned in "doInBackground". More in the AsyncTask documentation.
Another option is to simply use a Handler and use postDelay() for later executions:
Related
I'm building my first CloudKit application, and am using CKFetchRecordZoneChangesOperation on startup to get any new records changed while the current device was offline.
I am also calling CKFetchRecordZoneChangesOperation when I receive a subscription notification of changes.
It is possible the subscription notification could come in before the startup call finishes. I am currently using a lock to prevent the 2nd call from starting until the recordZoneFetchCompletionBlock handler is called, signalling that the first one is done. This works, but it also smells a bit hacky.
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];
I want to know how long does it take from posting a notification to getting the notification.
The reason is that I want to find out if the observer pattern is suitable for me. I don't want that another view controller can change the value before the notification has been sent and processed. I'm afraid that another process (thread?) is faster and the value will be overwritten when it shouldn't.
A notification center delivers messages synchronously, which means that the postNotification: method does not return until all objects registered to receive the notification have processed the notification. In other words, you can think of it as taking no time between posting a notification and receiving the notification.
There are a few extra things you'll need to be aware of:
Notifications are received on the same thread in which they are posted. If you move a notification over to the main thread using performSelectorOnMainThread:withObject:waitUntilDone:, you can break the synchronous behavior if waitUntilDone is set to NO. If waitUntilDone is set to YES, the thread passing the notification will block until the main thread has finished performing the specified action.
There is no guarantee of the order in which a notification will be received by its observers. If a single notification has multiple observers, don't rely on those observers receiving the notification in any particular order.
Given the above, and knowing which thread is posting notifications in your application and which thread needs to process them, you should be able to figure out whether the observer pattern will work for you.
you can use enqueueNotification for finer grained control over the processing of the notifications, but in the end I believe you can run into the same issue you have expressed concern about regardless of a NotificationCenter implementation or not
I am trying to post some data before my application terminates. Iam doing this by genrateing sockets using CFStreamCreatePairWithSocketToCFHost and later on I have the callbacks for reading and writing.
But I am not able to post any data. It goes through all the functions but doesnot enter into callbacks. Does that make sense to anyone?. Is there anyway to get this working?
Thanks,
Sowri
Yes, after applicationWillTerminate is called, there are no more iterations of the run loop. Since CFSocket and CFStream both use the run loop to manage the sockets and to provide data via the callback, this will not work. Also, it's very important to note that the application may be restricted from doing certain things at this stage and that if your application does not terminate, the operating system will terminate the application. It may be a better idea to write a small log to a database and then post that information back the next time the application starts.
My gut feeling is that after the applicationWillTerminate method is done, it will just stop the whole app, without giving any other run loop the chance to execute, let alone do callbacks. So my guess is that calling asynchronous methods in the applicationWillTerminate won't even start. You're just too late at that point to start networking.
The applicationWillTerminate: callback is not the place to do any kind of critical operation because as the name implies, your application will terminate and it won't wait for your code to finish doing something.
What are you trying to post; if you explain why you want to do this we may be able to offer a better solution.
I have some slow internet task to save and load file, I'd like to do those slow tasks in some background thread. I am wondering whether that's doable, and if it is, any sample code?
Then after it is finished, I'd like it to notice back to the main thread, so that I could update the UI.
Take a look at NSURLConnection. It will load an NSURL (using NSURLRequest) in the background, and send delegate methods regarding its status.
Ultimately the device you are running your code on has a single processor and cannot possibly load large quantities (gigabytes) of data. The best route, by is likely that suggested by Ben (NSURLConnection asynchronously) which gives you the added advantage of being able to cleanly cancel and handle error messages. While it isn't technically threaded in the way you probably think you want it to be, it is well integrated with the event loop and is non-blocking. If that is still not enough, I would suggest looking at NSOperation and NSOperationQueue. You can fire off an NSOperation sub-class object and perform the download there (I would still advise doing it asynchronously there so as to enable canceling, pausing, etc).
Log in to the iPhone Developer Center and search for Introduction to Threading Programming. Or, maybe you can log in and use this link:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Multithreading/Introduction/chapter_1_section_1.html#//apple_ref/doc/uid/10000057i-CH1-SW1
If you do decide you need a background thread even after using asynchronous HTTP calls to gather the data, don't forget to wrap the background thread code in a new NSAutoReelasePool and then release it at the end.