Is it possible to have maximum one instance of a custom class for each NSDocument? If so, how would you guarantee such a thing?
If you can't subclass NSDocument, then it's harder.
Subclass NSDocument. Give it a read-only property that returns the custom "only-one-per-NSDocument" class. In the getter for the property, only make an instance of the custom class when the ivar supporting it is null. Manage ownership to match the NSDocument instance lifetime.
http://developer.apple.com/library/...ptual/Documents/Tasks/SubclassNSDocument.html
If you can't subclass NSDocument, then it's harder. You have to correlate each NSDocument instance with a single instance of your custom class. An NSMutableDictionary can do the correlation, but you won't be able to use an NSDocument instance as the key, because a copy will be stored as the key. You can use the object-address of the NSDocument to make an NSNumber, and use that as the key. Then you're basically using the object's pointer as a key.
There's probably an NSSomethingOrOther collection class that does this mapping between any-pointer-as-key and any-other-pointer-as-value, but I'm not recalling what the class name is. It would behoove you to read the Collections Programming Guide. It would behoove me to do the same, but I have less vested interest in doing so right now.
Yes, that works provided that I only use "MyDocument" to retrieve an "only-one-per-NSDocument" instance. It doesn't prevent me (or someone else) from using the init method of the "only-one-per-NSDocument" and getting a second instance.
I will have a look at the Collections Programming Guide.
// in the implementation for your custom singleton class
- (id)init {
[COLOR="Blue"]MyDocument[/COLOR] *thisDocument = [[NSDocumentController sharedDocumentController] currentDocument];
if ( ![thisDocument isKindOfClass:[COLOR="blue"]MyDocument[/COLOR]] ) {
// safety check, just in case another kind of document might exist within your application
// probably not needed
[self release];
self = nil;
} else {
if ( [thisDocument [COLOR="blue"]mySingletonClass[/COLOR]] != nil ) {
// the object already exists, return the existing one
[self release];
self = [thisDocument [COLOR="blue"]mySingletonClass[/COLOR]];
} else {
// initialize the new instance
self = [super init];
/* the init code for you class goes here */
}
}
return self;
}
I think it would be as simple as this:
Code:// in the implementation for your custom singleton class - (id)init { [COLOR="Blue"]MyDocument[/COLOR] *thisDocument = [[NSDocumentController sharedDocumentController] currentDocument]; if ( ![thisDocument isKindOfClass:[COLOR="blue"]MyDocument[/COLOR]] ) { // safety check, just in case another kind of document might exist within your application // probably not needed [self release]; self = nil; } else { if ( [thisDocument [COLOR="blue"]mySingletonClass[/COLOR]] != nil ) { // the object already exists, return the existing one [self release]; self = [thisDocument [COLOR="blue"]mySingletonClass[/COLOR]]; } else { // initialize the new instance self = [super init]; /* the init code for you class goes here */ } } return self; }
(substituting your class names, of course)
Alternately (perhaps more effectively) you could write a class method that uses a similar technique, but creates and inits the singleton if it does not yet exist. In that case, the method should include an (id)sender parameter: if the sender is a view type object, the class method would use [[[sender window] windowController] document] instead of currentDocument to handle the possibility that the currentDocument is not what you want (e.g., a drag dropped on a window that is not the top one).