The first and foremost thing you should do is to include usage comments in your .h file that explain that this is an immutable class, along with the class's purpose and general usage guidance. Far too often people go to great lengths to try to "enforce" with the compiler what could be achieved by just informing the caller.
You should certainly not provide public setters or readwrite properties if you intend the class to be immutable (but of course you should provide private setters so that you can use accessors within the class; you should always avoid, even internally, messing with ivars directly except in a few places). I guess you could add your accessInstanceVariablesDirectly
override if you saw this as a likely error on the part of the caller.
But the key to understanding Objective-C is to understand and embrace the fact that the caller is not the enemy. The called code does not need to be "protected" from the caller. The caller needs to be protected from likely error. Everyone is on the same side here; caller and called want the program to work.
The caller is the customer and should be treated as such. The customer is not always right, but the customer is always the customer. Sometimes that means protecting the customer from himself if there is an easy mistake he might make. NSAssert()
is particularly useful for that. And providing public setters to an immutable class is almost tricking the caller into making a mistake, so that would be bad for everyone.
In any case, you shouldn't make your class overly complex to try to enforce immutability. The caller can almost (*) always violate encapsulation by accessing the struct directly (object->ivar
). The caller would be foolish to do so, but you would be even more foolish to try to prevent it. Note the immutability, hide your setters and mark your properties readonly, and in almost all cases you should be fine.
(*) Yes, it's possible to even more hide your data by nesting a private struct/object as an ivar, but then the caller can still modify the data with pointer arithmetic so it's still not "enforced." Always ask yourself what problem you're really trying to solve.