1

I have been fixing a bug and wound up in some pretty old code, and I've found something I don't fully understand

We have are currently initializing an object like this:

MyViewController* myViewController = [MyViewController viewControllerForDocument:(MyDocument*)doc];

and +viewControllerForDocument is a class method:

+ (instancetype)viewControllerForDocument:(MyDocument*)myDocument
{
   MyViewController* result = nil;
   result = [[MyViewController alloc] initWithNibName:@"MyViewController"
                                                        bundle:[NSBundle mainBundle]];

   if ( result )
   {
      [result view];
      [result.myController setDocument:myDocument];
      [myDocument setController:result.myController];
   }
   return result;
}

I know it looks pretty funny, but my question is why would a developer choose to instantiate an object through a class method-- instead of just writing a custom instance initializer? The implementation of the class method contains the instance initializer -initWithNibName anyways.

The reason why this is an issue now, is because [result view] loads the nib which calls -awakeFromNib.

-awakeFromNib needs to be aware of myDocument; but because the initializer is a class method I can't store myDocument into a instance property.

I also can't move [result.myController setDocument:myDocument]; before the [result view] call because myController is loaded through the nib.

Anyways this whole thing just stinks to me, and the fact that it was written in 2010 by an employee that is long gone makes me skeptical.

Can anybody shed some light on possible motivation to implement things this way? I also don't think that manually loading objects through the nib by accessing the view is good either, but I don't really have any reason to say it's bad

A O
  • 5,516
  • 3
  • 33
  • 68
  • Constructor methods like this [are found throughout Cocoa](http://stackoverflow.com/questions/5987969/class-methods-which-create-new-instances/5988016#5988016). It's perfectly valid. – jscs Sep 17 '15 at 20:32
  • 1
    Wow, 2010 is "wound up in some pretty old code"? I just started working on a code base initially started the 1980's and last worked on in 2000. – zaph Sep 17 '15 at 20:33
  • 1
    "`-awakeFromNib` needs to be aware of `myDocument`; but because the initializer is a class method I can't store `myDocument` into a instance property." The document is set on the very next line -- can you not reorder them for some reason? – jscs Sep 17 '15 at 20:36
  • 1
    You're right-- I was confused initially so I definitely phrased my question wrong. It started because I wanted to store it as `self.myDocument`-- when I just needed to instead do `result.myDocument`. Obvious in hindsight – A O Sep 17 '15 at 20:55
  • Also pardon my novice, I only started w/ Objective-C and Cocoa about a year ago. Still learning :) Thanks for the comments guys – A O Sep 17 '15 at 21:08

1 Answers1

2

How is this particularly different than the following from the NSString class method:

+ (instancetype)stringWithUTF8String:(const char *)bytes

Both are class methods, sometimes called convenience initializers.

They were more useful prior to ARC where they avoided the alloc init autorelease pattern:

MyClass *inst = [[[MyClass aloc] init] autorelease];
zaph
  • 111,848
  • 21
  • 189
  • 228
  • 1
    One reason to use them still is when the class caches instances; another is class clusters. It's slightly more convenient than having to destroy the useless passed-in instance in `init...`. – jscs Sep 17 '15 at 20:55