Delegate not being called - cocoa

I have a ContactsViewController which -whenever a row is selected- MessageViewController is opened (using pushViewController). Both the ContactsViewController and the MessageViewController 'register' to receive DatastoreDelegate messages. The weird thing is it all works fine upon loading of my application, but once I navigate to the MessageViewController the delegate methods on my ContactsViewController don't get called anymore. Both these controllers should handle the [messageAdded:(Message *)message] method, but only the MessageViewController keeps receiving the messages after it's been opened once.
Does anyone have any idea on how to make this work?

In Cocoa, every object with a delegate has only one delegate (at any given time). That delegate is the only object that gets the delegate messages. There's no real concept of having "both objects registered to receive delegate messages." My suspicion here is that when you push the MessageViewController, it sets itself as the Datastore's delegate, and then the ContactsViewController never sees those messages again, because it doesn't set itself back.
I don't know how your code is structured, but you could simply hand-off the delegate every time the controllers change view so whichever is active is the current delegate.
In Cocoa, the Notification pattern (see NSNotificationCenter) is used when an object needs to "broadcast" information to multiple other objects. Delegates are really what they sound like: an object that another object optionally relies on to "partner with" it and provide key functionality. It's a more intimate relationship than a notification observer.

Related

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.

Coordination between classes in Cocoa

I have a program with a lot of controllers which need to co - ordinate with each other . I'm confused about which mechanism to use . What are the pro and con of using :
Delegate
Bindings
Notifications
Key Value observing
Specifically is there any problem with using notifications all over place ? I'm planning to do that as it allows a class to just put out some information and not bother about anything else.
Use delegates if you want your object to have knowledge of specific methods to call when it needs to inform an observer of a state change. Notifications are more appropriate when you have multiple observers. Both of these require manual intervention, i.e. you need to explicitly call the delegate methods or post notifications when state changes.
Bindings and KVO work hand-in-hand, and are automatic ways to update state in one object (e.g. UI) when state in another object changes.

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