5

The Apple Programming with Objective-C document states that:

You should always access the instance variables directly from within an initialization method because at the time a property is set, the rest of the object may not yet be completely initialized. Even if you don’t provide custom accessor methods or know of any side effects from within your own class, a future subclass may very well override the behavior.

But I don't know what side effects will be in a setter method, please give me a example to explain why I have to access the instance variable directly from within an initialization method

3 Answers 3

4

The answer is simple - it is code smell. Dot notation like self.foobar = something in Objective-C is just a syntactic sugar for messaging. Sending messages to self is normally fine. But there are two cases you need to avoid them:

1. When the object is being created, and

2. When the object is being destroyed.

At these two times, the object is in a strange in-between state. It lacks integrity. Calling methods during these times is a code smell because every method should maintain invariants as it operates on the object.

Sign up to request clarification or add additional context in comments.

Comments

3

If a setter method is overridden by a subclass, you have no guarantee that your instance variable will contain the correct data. If you want to maintain data integrity within your objects during a crucial phase such as initialization, you should do as Apple recommends.

4 Comments

But what if the subclass wants to limit some value. Like making sure an integer is under 1000. The subclass may rely on this and if you directly set the instance variable in the parent's init you could break other functionality in the subclass. You may have no real reason (besides the integer limit) to override the parent's init. If you set the property then you are giving control back to the subclass (who should really have it).
@Firo The subclass should override the superclass' init. Think about this in terms of object lifecycle. Certain methods should be called during certain phases. During initialization, the object cannot, at any point, be thought of as fully initialized; therefore we should not be calling setter methods which are only meant to be called when the object is fully initialized. </endrant>
I guess, it just seems like you would end up having duplicate code (setting the value in the superclass's init, setting and checking it in the child's init, and also checking and setting it in the property setter). Seems weird and redundant to me. Although maybe it is necessary.
If your init method needs logic in the setter to validate state, you've got a whole slew of other problems on your hand...
0

In addition to @JacobRelkin point, side effects can include Key-Value Observing. Other objects can observe changes even during -init* and -dealloc. I've had a KVO -dealloc bug in the past.

It truly is a best practice to setup and tear down the ivars directly.

1 Comment

How could other objects be KVO-ing before the calling context stores the return value from -init?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.