How do I observe the creation/destruction of an object instance? - objective-c

I am smitten by KVC/KVO. Super powerful. There is one problem though. I'm trying to be true the the MVC etho but I see no way to use an observation pattern to monitor the allocation or deallocation of an Objective-C class instance.
This is actually important as I have a model with fine-grained internal messaging that I want to observe from a controller (or delegate). The stumbling block for me is I don't see how, external to the model, I can remove an observer for a sub-component that is about to be deallocated without the controller knowing about the internal logic of the model which would compromise encapsulation.
Can someone suggest an approach for this scenario.
Thanks,
Doug

Doug - there really isn't enough information in your description to know what it is you are doing and how to best (or if it is appropriate at all) apply KVO to the problem.
KVO is all about observing properties on objects. You typically shouldn't care when they are created or destroyed except insofar as you must stop observing them before they are destroyed.
You should instead start and stop observing objects when those objects become interesting to you. Consider a graphics drawing package where a document has an ordered array of shapes, and you are interested in observing the backgroundColor property of each shape.
We wouldn't try to observe the instantiation and deallocation of the Shape instance, but instead we observe the "shapes" property on the document. Through that observer, we can determine when a shape is added to, or removed from, the document. When a shape is added to the document, we start observing it. When it is removed from the document, we stop observing it. (Note that it may be removed from the document but not deallocated, if it is on the undo stack, etc.)
In the object graph for your model, to use KVO you'll want to add and remove the objects from your object graph in a KVO compliant way so you can observe the relationship mutations, and in that observer, start and stop property observers on the related objects.

I think you'll have to post the notifications yourself, unless you use something like CoreData. If you're using CoreData, NSManagedObject (the root class of all stored CoreData objects) has an -awakeFromInsert method that gets called after the object has been created and inserted into the ManagedObjectContext.
As for destruction, you could probably just post a notification right as you enter the -dealloc method.

I'm not sure exactly what you're trying to achieve, so a little more explanation would be good.
If you just want to remove an observer before the observed object gets deallocated, then don't worry, because KVO will handle it. Even if you're using notifications it won't cause a problem, you just won't receive any notifications from the object.
If you're trying to observe multiple objects (e.g. an array of Widgets), and would like to know when an object is added or deleted, KVO can handle that too. You just have to make the array a key on your model object, and observe it with KVO. You also have to modify the array in a KVO compliant way (e.g. mutableArrayForKey:, or use your own willChangeValueForKey and didChangeValueForKey).

Related

When to use NSNotificationCenter

I want to have multiple observers on multiple events of a single object (1-to-N relationship).
A mechanism to achieve this task is provided by the NSNotificationCenter. The mechanism looks pretty overkill when used for my problem.
How I would do it manually without the use of NSNotificationCenter:
- (void)addDelegate:(id<DelegateProtocol>)delegate;
- (void)removeDelegate:(id<DelegateProtocol>)delegate;
to add and remove observers from my object.
- (void)someEventFired:(NSObject<NSCopying> *)eventData
{
for (id delegate in delegates) {
NSObject *data = [eventData copy];
[delegate someEventFired:data];
}
}
This mechanism is straight-forward and simple to implement without the objects having to share additional strings.
Is there an official pattern for 1-to-N delegates (like C# events) in an iOS framework besides the NSNotificationCenter?
When should the NSNotificationCenter be used and when not?
When should an implementation like the one I am suggesting here be used and when not?
By convention, delegates should probably only be used for 1:1 relationships. If you really need 1:N relationships for this type of functionality, you have two options:
As you mentioned, NSNotificationCenter.
Key-Value Observing (also known as KVO).
KVO is appropriate if you only care about when a particular property of an object changes. Otherwise, you should really just consider using NSNotificationCenter. You can even be notified only when a specific object posts that notification by passing that object into the addObserver:selector:name:object: method.
Apple uses NSNotification in similar scenarios (like the notifications defined for UITextField, including UITextFieldTextDidBeginEditingNotification, UITextFieldTextDidChangeNotification, and UITextFieldTextDidEndEditingNotification).
using notifications is broadcasting: 1 sender just sends an information and who ever tuned in, receives it. Petty much like a radio station, there is no channel back (lets for the moment forget about telephones)
delegation is something different. Th object, that asks a deleagte to do something, usually needs a result of that request, there fore delegation is a 1-to-1 communication, that is always initiated by the object, not the delegate (while the object can have methods that can be called to inform the object to initiate the communication, ie [tableView reloadData]).
So if the sender needs to get data back, it is delegation. If the sender doesn't care about anything after broadcasting, go with notifications.
If you run into the situation, that you need delegation, but several objects should implement the protocol. you should have 1 delegate, that hold references to the other objects and calls the methods on the senders behalf — or you could go with blocks.
NSNotificationCenter is not overkill for what you are suggesting, it is exactly the right solution. It prevents the observed object having to know or care about its observers, making your code more loosely coupled and cleaner.
Sharing strings for notification names is trivial and they can be defined in either a shared constants file or in the header of the observed object, if your observers need to import this header to do their jobs.
Your proposed solution is neither simpler than using NSNotificationCenter nor is it thread safe.
To make your solution thread safe, you would need to provide a mechanism to prevent the delegates array from changing while the event dispatch for loop is running.
Your solution also requires that you maintain the delegates array in your class. With the NotificationCenter you can simply use the default center and you don't need to implement the add/remove methods in your class. Instead, instances can register themselves to receive notifications as they see best fit (selector/block, queue, source). Your source class doesn't have to worry about those details. It only needs to register itself as a source of notifications of a specified type. Using blocks to handle notifications is really convenient.
An alternative to the notification center is to use Key-Value-Observing if that meets the needs of your use case.
Ultimately, the mechanism you decide to use depends on how best it applies to your specific use case.
A 1-to-N delegate relationship doesn't make sense. Have a look at
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
for example. What if this object really had n delegates? How should it decide which of the n views it gets back from all its delegates should be used? Delegates are exactly this 1-to-1 principle.
The NSNotificationCenter is the right approach. Simply use
addObserver:selector:name:object:
respectively
postNotification:
This is definitely not too much code. And it's very easy for you as the center handles all calls.
You don't want to use NSNotificationCenter for anything other than system-wide events (e.g. the appearance of the keyboard or some similar event). The reason is that it is completely not type-safe, can make everything dependent on everything and that you get no compile time checks or usage search results anymore.
KVO in my opinion should not be used to observe changes outside of the object you're listening to since it has similar down sides (no compile time checks, crashes if you don't remove listeners properly or register them twice).
The addDelegate/removeDelegate pattern that you pose is completely the right path in my opinion since that has the advantage of maintaining type-safety and compiler checks and makes dependencies explicit. The only problem is that Apple doesn't supply an out-of-the-box solution for this pattern, since you need a collection type that weakly retains its elements to avoid retain cycles.
However, see code from my BMCommons framework which solves this problem neatly using BMNullableArray and macros. See the BMCore.h header for a definition of those macros:
BM_LISTENER_METHOD_DECLARATION(protocol)
BM_LISTENER_METHOD_IMPLEMENTATION(protocol)
The implementation ensures that the same listener will never be added twice and also that listeners are weakly retained, not causing any crash even if they forget to deregister themselves upon deallocation (although I prefer to catch this condition with an assert since it is a programming mistake).
I say NSNotificationCenter should ALWAYS be used, over the delegate model, except in situations where you query a delegate on information (e.g. -webView:shouldLoadRequest:). It is more stable, easier to implement, and results in cleaner code then trying to use a delegate. The other alternative is blocks, which can be good, but they can be a pain when it comes to memory-managment.
In the end, it's up to you, but I think that NSNotificationCenter is the best way to go in almost any situation, if only for the multiple observer functionality.

Is there a way to tell when KVO starts/ends for a particular value?

I have some values that are computed over collections, and may or may not be displayed (and thus may or may not have an observer) at any given time. I would rather not have to track all the members of the collection if nobody is observing my computed values.
Can I tell if anyone is currently observing a value, and can I tell when they start observing?
I know for a given object foo I can use [foo observationInfo] to get a list of observers with key paths registered with a root at foo, but that doesn't automatically get all paths TO foo (in fact it only gets ones registered to observe foo's self key).
That’s not a good idea from the design point of view. If you really insist on not updating the contents when nobody needs them (which could be a legitimate case, for example if the updates are expensive), you can introduce methods to start/stop the updates:
- (void) beginUpdatingContents;
- (void) endUpdatingContents;
These should be tied to a counter inside the class and if the counter is > 0, you know somebody wants to keep the contents updated. This solution is explicit and therefore better than silent magic with KVO.
If you want more magic, how about overriding addObserver:forKeyPath:options:context: and removeObserver:forKeyPath: and tracking what is still observing you?
The way I've actually done this in the past is by making wrapper objects (I called them bindings) which set up KVO and also register themselves with the target. So, a user would call MyBinding *binding = [targetObject bindKeyPath:#"foo" ...] and then later [binding detach]. You then have the binding use KVO under the hood and keep a list of themselves so you know when it's empty.

KVC array: getters vs indexed accessors?

I'm confused by this: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/AccessorConventions.html#//apple_ref/doc/uid/20002174-178830-BAJEDEFB
Supposing
#interface Office : NSObject {
NSMutableArray *employees;
}
What is the benefit of implementing the collection accessors?
How is [anOffice countOfEmployees] better than [[anOffice employees] count]?
Do bindings depend on the collection accessors or can I forego them completely?
They seem redundant to me since I'm using a true array object. I can understand how they would be needed if employees wasn't an NSMutableArray and didn't implement something like a count method itself.
I'm also absolutely stumped by why would would use mutableArrayValueForKey:#"employees" for fetching the employees property instead for simply valueForKey:#"employees".
Thanks!
You can forego the collection accessors; they aren't required. But they make things a lot easier.
One reason to have them, including countOfEmployees, is efficiency: The employees method may return a copy of the array object (particularly since the Office's copy is mutable, so the Office would not want other objects mutating the array out from under it), but if you only need to know the count or to access one object at a specific index, you don't need a copy.
The other reason is when the sender wants to mutate the property.
valueForKey: will call employees, which will ordinarily return an immutable copy.
Returning a mutable copy would not help, since mutating that array would be mutating the copy, not the original through the property.
Returning the original array will not enable the sender to cause KVO notifications for its changes, so nothing observing the property will know about those changes. This means the values shown in your UI will go stale (not be updated).
mutableArrayValueForKey: returns a fake array that sends mutation messages (or, if nothing else, employees and setEmployees: messages) back to the original object. Accessor messages do cause KVO notifications, so anything observing the property will follow along with these changes, so your UI keeps up to date.
Of course, you could just send the accessor messages yourself. mutableArrayValueForKey: is mainly for if you want to make changes to a property that isn't known at compile time; NSArrayController is, presumably, one user of this method. You aren't likely to need to use mutableArrayValueForKey: in a regular application, and sending accessor messages yourself is, in my opinion, easier to read.
All of this goes for the Office as well, when it mutates its own array. It could just talk to its array object directly, but that wouldn't cause KVO notifications, so nothing else would know the value of the property had changed. You could post the KVO notifications yourself around each change, but that's a hassle and easy to forget. Collection accessors and mutableArrayValueForKey: are two solutions to these problems: Each access is a single line of code that will cause KVO notifications.

In ObjC, how to describe balance between alloc/copy/retain and auto-/release, in terms of location

As is common knowledge, calls to alloc/copy/retain in Objective-C imply ownership and need to be balanced by a call to autorelease/release. How do you succinctly describe where this should happen? The word "succinct" is key. I can usually use intuition to guide me, but would like an explicit principle in case intuition fails and that can be use in discussions.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
Sometimes the release should be in the same block. Other times the alloc/copy/retain happens in one method, which has a corresponding method where the release should occur (e.g. -init and -dealloc). It's this pairing of methods (where a method may be paired with itself) that seems to be key, but how can that be put into words? Also, what cases does the method-pairing notion miss? It doesn't seem to cover where you release properties, as setters are self-paired and -dealloc releases objects that aren't alloc/copy/retained in -init.
It feels like the object model is involved with my difficulty. There doesn't seem to be an element of the model that I can attach retain/release pairing to. Methods transform objects from valid state to valid state and send messages to other objects. The only natural pairings I see are object creation/destruction and method enter/exit.
Background:
This question was inspired by: "NSMutableDictionary does not get added into NSMutableArray". The asker of that question was releasing objects, but in such a way that might cause memory leaks. The alloc/copy/retain calls were generally balanced by releases, but in such a way that could cause memory leaks. The class was a delegate; some members were created in a delegate method (-parser:didStartElement:...) and released in -dealloc rather than in the corresponding (-parser:didEndElement:...) method. In this instance, properties seemed a good solution, but the question still remained of how to handle releasing when properties weren't involved.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
This is a misunderstanding of the history of properties. While properties are new, accessors have always been a key part of ObjC. Properties just made it easier to write accessors. If you always use accessors, and you should, than most of these questions go away.
Before we had properties, we used Xcode's built-in accessor-writer (in the Script>Code menu), or with useful tools like Accessorizer to simplify the job (Accessorizer still simplifies property code). Or we just typed a lot of getters and setters by hand.
The question isn't where it should happen, it's when.
Release or autorelease an object if you have created it with +alloc, +new or -copy, or if you have sent it a -retain message.
Send -release when you don't care if the object continues to exist. Send -autorelease if you want to return it from the method you're in, but you don't care what happens to it after that.
I wouldn't say that dealloc is where you would call autorelease. And unless your object, whatever it may be, is linked to the life of a class, it doesn't necessarily need to be kept around for a retain in dealloc.
Here are my rules of thumb. You may do things in other ways.
I use release if the life of the
object I am using is limited to the
routine I am in now. Thus the object
gets created and released in that
routine. This is also the preferred
way if I am creating a lot of objects
in a routine, such as in a loop, and
I might want to release each object
before the next one is created in the
loop.
If the object I created in a method
needs to be passed back to the
caller, but I assume that the use of
the object will be transient and
limited to this run of the runloop, I
use autorelease. Here, I am trying to mimic many of Apple's convenience routines. (Want a quick string to use for a short period? Here you go, don't worry about owning it and it will get disposed appropriately.)
If I believe the object is to be kept
on a semi-permanent basis (like
longer than this run of the runloop),
I use create/new/copy in my method
name so the caller knows that they
are the owner of the object and will
have to release the object.
Any objects that are created by a
class and kept as a property with
retain (whether through the property
declaration or not), I release those
in dealloc (or in viewDidUnload as
appropriate).
Try not to let all this memory management overwhelm you. It is a lot easier than it sounds, and looking at a bunch of Apple's samples, and writing your own (and suffering bugs) will make you understand it better.

Releasing Managed Objects in Objective-C

Okay, PLEASE bear with my description of my situation:
I have a Core Data model that (in a simplified description) includes a GridManager object. The GridManager holds a set of Grid objects (via a to-many relationship). The Grid object contains a set of Cell objects (via a to-many relationship).
In my app, I have a GridView that contains a series of sub-views (of type CellView). The GridView has a representedGrid property and the CellView has a representedCell property (both nonatomic, retain). In the setRepresentedGrid method of GridView, I set the representedCell property of each CellView (subviews of the GridView) to one of the cells in the representedGrid.
NOW, I have two questions:
First, since the cells and the grid are Managed objects, do I still need to release the representedGrid and representedCell properties of the GridView and CellView classes when they dealoc? I figure I do (just as with any retained property), but at one point I thought this was causing a problem with my app--hmmm... just thought, since I write my own setters, and I don't actually retain the grid/cell, perhaps I DON'T need to release them?
Second, only one grid from the gridManager is active at a time. When I switch the gridView.representedGrid from one grid to another, how do I "release" the first grid (and it's associated cells) so that it isn't needlessly taking up memory (given that we're talking about managed objects).
Thanks SO much!
As I understand it you should and can avoid custom getters and setters and then you can leave core data to do it's thing and not worry about retain/release.
As for reducing memory overhead you can ask core data to turn your object to fault using this method: refreshObject:mergeChanges:
Check out the Apple documentation here: http://gemma.apple.com/mac/library/documentation/Cocoa/Conceptual/CoreData/index.html. It's all there and hopefully I've been able to give you the right terms to look for.
Hope that's some help.
If your setters are retaining the managed objects then you need to release them to match the retain/release. However you may not need to retain the managed objects depending on how the application is designed.
Without seeing all of the code it is difficult to give solid advice but you can use the analyzer to check for leaks, use instruments to make sure your memory is not increasing out of control, etc. And last but not least you can turn off retains, switch them to assigns and see if it crashes. Since the NSManagedObjectContext will retain the objects there is a fair chance that your views do not need to retain the NSManagedObject instances at all.
Yes, you need to release your representedGrid and representedCell properties in your dealloc method. If you didn't, the retain/release methods would not be balanced- your setter would be retaining the object, and with no corresponding release, the object will never be deallocated.
When written properly, a retain setter will release its old value and retain the new value. So there is no need to release the old grid when setting gridView.representedGrid.
Why are you writing your own setters, out of curiosity?