"singleton" for each document

Discussion in 'Mac Programming' started by MrFusion, Jan 3, 2011.

  1. MrFusion macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #1
    Is it possible to have maximum one instance of a custom class for each NSDocument? If so, how would you guarantee such a thing?
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    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.
     
  3. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #3
    "can't subclass NSDocument" makes no sense. NSDocument is an abstract class that merely provides the basic conveniences you need to handle a document-based application. On it's own, it has no useful functionality, you have to subclass it to be able to do anything with it.
     
  4. MrFusion thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #4
    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.
     
  5. Sydde, Jan 8, 2011
    Last edited: Jan 8, 2011

    Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #5
    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).
     
  6. MrFusion thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #6
    Brilliant! I will play around with these suggestions and see what fits best.
     

Share This Page