Cocoa Controllers - best practice for notifying on completion, for disposal? - cocoa

I have an ObjC controller object.
After alloc/init of the object, I get it to do a job asynchronously:
[myObject doSomeThingsOverTime];
The method sets things in motion, and then returns immediately.
Question: what is the best way to be notified of the result in the future, so that I can release myObject and react to the work having been completed? Should I observe/post notifications? Or supply the object with a method to callback? Or other?

I'm personally a fan of the notification center route. It allows for more than one observer (may or may not be relevant to you).
The delegate route is also valid, and is used quite frequently in the frameworks.
I think it comes down to personal preference. If it's your own code, you should go for what's most readable and simple for your particular situation. I don't think one is more or less valid than the other.

Have you looked at the NSOperation and NSOperationQueue classes? You can observe the isFinished of an NSOperation object so you will get notified when it is completed.

Related

Use PropertyChanged or WeakSubscribe?

What is the best way to track a property change?
I have the following concerns why I can't make a decision.
- PropertyChanged can prevent garbage collection from collecting a ViewModel that uses its own PropertyChanged event?
- Could WeakSubscribe be gone at any moment in time when using to track ViewModels own property changes?
Did anyone test this or just know the answer ?
In general, you won't hit problems if you use PropertyChanged strong subscriptions.... However, there are some cases where this can lead to "leaks" - e.g. if you subscribe on a sub-object which has a longer lifetime than a "normal" ViewModel (e.g. a singleton service).
To be safe, though, you can use WeakSubscribe - as long as you store a reference to the returned token from the WeakSubscribe call in a member field in your view, then this will ensure that the subscription remains active for at least as long as your View is in memory.
Regardless of strong or weak, one additional thing to aim for ... is to try to release the event subscription (either strong or weak) as early as you can. This will help prevent event callbacks being fired after the View has disappeared.

Is ok to duplicate NSURLsession delegate classes iOS

I have multiple classes that use NSURLSession, and they may run at the same time, is OK if I make them all NSURLSession delegates?
Code:
First delegate:
#interface userLoginScreen : UIViewController <UIAlertViewDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate>
Second delegate:
#interface syncDataOperation : NSOperation <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate>
Is it a good practice to do this?
All you're doing in your example there is saying "all these classes implement this interface", which is perfectly fine, and has no real bearing on what actually happens at runtime.
What I think you're getting at is those scenarios where you may want to have a single delegate object receiving delegate messages from multiple objects in an NSURLSession. For example, it's perfectly normal to have a single delegate handle callbacks for multiple NSURLSessionTask objects.
The only real problem might be if you were to have the delegate messages coming in on multiple different threads/queues. However, Apple have designed for that; when you create an NSURLSession object you can provide a specific delegateQueue for the callbacks to be sent on. This is the delegateQueue in sessionWithConfiguration:delegate:delegateQueue, for example.
If you don't provide one, NSURLSession "creates a serial NSOperationQueue object on which to perform all delegate method calls and completion handler calls", which is a very sensible default.
Tasks that you create under one NSURLSession will use that delegate queue for their delegate messages, too.
For example, if you create an NSURLSession without specifying a delegateQueue, it will create a serial queue for its delegate messages. If you then call downloadTaskWithRequest on it to create a NSURLSessionDownloadTask, the download task's delegate methods will use the same queue.
If you create thirty NSURLSessionDownloadTasks on it, all pointing at the same delegate, they'll all use the same queue to send their delegate messages, and because it's a serial queue, your delegate won't ever have two delegate messages arrive simultaneously, so you don't have to worry about coding to cope with that situation. (And all the delegate messages pass pointers to the related NSURLSession/NSURLSessionTask so you can tell which messages came from which tasks.)
Normally all the delegate objects you have to deal with a particular set of tasks will be dealing with tasks created underneath the same NSURLSession object, so everything uses the same delegate queue by default, and if you don't bother passing in a delegateQueue, NSURLSession, as I've said, provides a sensible one for you, so mostly the delegate stuff should Just Work.

Should I prefer NSNotificactionCenter or .NET events when using Monotouch?

When developing in Monotouch, is it "better" to us real .NET events or NSNotificationCenter?
Simple example: I have a UIViewController. It offers an event "CallbackWhenDisappeared". This event is triggred in ViewDidDisappear. Who ever is interested can register to the event.
I could as well post a "MyFancyControllerHasDisappeared" on the NSNotificationCenter and let interested objects subscribe there.
Which version is to be preferred?
The disadvantage with the .NET events I see: the disappearing controller might hold a reference to the subscribing controller (or the other way round?) and might not be garbage collected.
I also like the loose coupling when using NSNotificationCenter compared to the events where the classes really have to know each other.
Is there a wrong or a right way of doing it?
I actually prefer to use TinyMessenger. Unlike NSNotifications it handles the asynchronicity of the calls for you as part of the framework.
Managed objects also allow for better debuggability especially considering that these are usually cross container calls I find this to be very very useful.
var messageHub = new TinyMessengerHub();
// Publishing a message is as simple as calling the "Publish" method.
messageHub.Publish(new MyMessage());
// We can also publish asyncronously if necessary
messageHub.PublishAsync(new MyMessage());
// And we can get a callback when publishing is completed
messageHub.PublishAsync(new MyMessage(), MyCallback);
// MyCallback is executed on completion
https://github.com/grumpydev/TinyMessenger
There is no really right or wrong, but in my opinion it looks so:
NotificationCenter - You don't know which Objects are interested on the "Events", you send it out and any object can receive it
.Net Events - If there is a direct connection between two objects use this, for example like an UIViewController shows an other UIViewcontroller as Modal. The ModalUIViewcontroller fires an event, if it will hide and the UIViewController is Suscribed to it

NSManagedObject subclass woes

Hey guys, I've got a subclass of an NSManagedObject. In awakeFromInsert and awakeFromFetch I'm calling an initialization method which, among other things, starts an NSTimer.
Now i need a place to invalidate the timer. However, dealloc, finalize, didTurnIntoFault, prepareForDeletion and willTurnIntoFault aren't getting called.
According to the documentation, these methods should all get called when the object is cleared from memory. None of them are, however all the data is saved in the persistent store. I'm puzzled as to why or how.
Is there anything i could be doing that could cause these methods to not get called during the objects life cycle?
Core data controls the lifetime of NSManagedObjects. It's not going to flush an object from memory by itself unless you ask it to. Looking at the documentation, there appear to be two ways:
sending refresh:mergeChanges: to the MOC causes the object to turn into a fault.
sending reset to the MOC causes it to reset itself as if it has just been created.
However, any of the above requires explicit action on your part, so you might as well add a method to the object to invalidate its timer and invoke that.
In fact, your problem probably indicates a design issue. An NSTimer is essentially a user interface event. It should probably be controlled by your MVC controller which sends a message to the model object (the NSManagedObject) to do the action.

Auto-save with Cocoa and Core Data

I am working on a non-document-based Core Data application.
I would like changes to be saved as they happen. This is what the user expects in this type of application. It is also what Apple has implemented in iPhoto or iTunes.
A brute force approach would be to set up a timer to save frequently. The method triggered by the saving would then swallow all validation errors so as not to bother the user. Only upon quitting, the user will be bugged to arrange the data so it can save. IMHO, that approach stinks.
So I am thinking, there must be a way to somehow hook saving to something like the NSEditor protocol. Every time the user (or a controller) finishes editing data, the application delegate should somehow be notified an trigger a save operation. Thing is I don't quite know where to look.
I would think that for more complicated operations, which may require some cross-validations to go through, I would present the user with bit of interface tied to a dedicated NSManagedObjectContext.
At the end of each event in an AppKit app, CoreData will run a -processPendingTransactions for you.
One side-effect of this is that if you've registered with your NSManagedObjectContext to receive change notifications, you'll get called at the end of each event.
So, for instance, in your notification handler, you could call just tell the context to save.
However, you might be paranoid about doing a save on a context while in a callback from that same context, so you'd probably feel better if you did a performSelector:#selector(save:) afterDelay: to push the save until after the -processPendingTransactions is done.
You could even do a cancel previous on the -save: selector and have the delay be like 5 seconds, so if the user or app is in the middle of a BUNCH of changes they'll all coalesce into a single save.
And, in fact, that's exactly how Delicious Library 1.0-1.09 worked.
-Wil

Resources