1

Apple recommends NOT to use property methods in initializers, however I'm unsure of the protocol to follow if you need to call a method from an initializer that also needs to be called from else where in the program after the object is initialized. For instance, you have:

- (id) init
{
    self = [super init];

    if (self)
    {
           [self someMethod];
    }

    return self;

}

- (void) someMethod
{
    _x = 0; \\ or self.x = 0 when this method is not called from initializer
}

someMethod contains a bunch of ivars in it. Problem is, it also needs to be called else where in the code later on after the object is initialized. I'd like for the accessors to not be accessed in the initializer when its called from there, but I'd also like for them to be accessed when someMethod is called from else where. Is there a neat way around this pattern? When using NSObject? When using UIView? When using UIViewController?

Ser Pounce
  • 14,196
  • 18
  • 84
  • 169
  • 1
    This is not a mandatory rule, but a suggestion. If you understand what you are doing then it is perfectly fine to set the backing property variable directly. The only harm comes from doing it without thinking. – borrrden Mar 18 '13 at 07:30
  • 4
    If you don't have setters that process other instance variables simply ignore the recommendation. – Matthias Bauch Mar 18 '13 at 07:31
  • As borrrden says, it's just a suggestion. There is no problem to use them inside an init. The problem would arise if you use KVO, usually you don't want to trigger it during initialization or deallocing. [EDIT] or as Bauch says if you are using custom setter/getter. – Andrea Mar 18 '13 at 07:33
  • Thanks guys. I think the only times I really implement my own setters is with CoreGraphics objects. I'll gladly eliminate any other custom setters I have that reference other instance variables if it enables me to stop using this god forsaken pattern! – Ser Pounce Mar 18 '13 at 07:43

1 Answers1

4

To judge if it's safe to ignore the recommendation you have to understand why this recommendation exists.
The main problem are getters and setters that have side effects because they perform calculations based on instance variables that may not be initialized when you call the setter (or the getter).

Take the following code as example:

- (id)init {
    self = [super init];
    if (self) {
        // don't do this
        self.textColor = [UIColor blackColor];
        self.font = [UIFont boldSystemFontOfSize:17];

        // do this:
        _textColor = [UIColor blackColor];
        _font = [UIFont boldSystemFontOfSize:17];
        [self createLayers];
    }
    return self;
}

- (void)setFont:(UIFont *)font {
    if (font) {
        _font = font;
        [self createLayers];
    }
}

- (void)setTextColor:(UIColor *)textColor {
    if (textColor) {
        _textColor = textColor;
        [self createLayers];
    }
}

- (void)createLayers {
    // calculation that will crash if font or textColor is not set
}

Because createLayers crashes if textColor or font is nil, using the setter in init will crash your code.

Matthias Bauch
  • 89,811
  • 20
  • 225
  • 247