2
votes

I am reading "Effective Objective-C 2.0: 52 Specific Ways to Improve Your iOS and OS X Programs". In "Item 6", the author says that using a pointer on a public ivar is a bad idea, because compiled code will have hardcoded pointer offset, and when new ivar will be added to class, then previously used pointers to some ivars can now point on other variable.

@interface Foo
{
    @public
    NSString * string;
    NSArray * arr;
}
@end

@implementation
...
@end

int main()
{
  @autoreleasepool
  {
   Foo *f=[Foo new];
   f->string; //Is it bad idea?
  }

 return 0;
}

But, aren't ivars and properties dynamic (offset is not known at compile-time)? As Cocoa With Love says:

"All ivars are dynamic in the modern runtime: Since this procedure is followed for all ivars, that means that all ivars in the modern Objective-C runtime are dynamic in that their absolute offsets are never known at compile-time."

If that's true, then why is using a pointer on an ivar bad? Please provide as much low-level detail as possible.

2
Question: Is he talking about having a public ivar that is a pointer, or rather talking about taking the address (&) of a public ivar?Hot Licks
Meh, just use properties. Everything sorted.Fogmeister
@HotLicks I updated questionSunrise

2 Answers

7
votes

If that's true, then why is using a pointer on an ivar bad? Please provide as much low-level detail as possible.

Because it breaks encapsulation.

What if class Foo has some custom logic that should be fired when string changes? Or it has to do a calculation? Or Foo wants to make the storage of string unique-ified? Or something else wants to observe changes to said property? Or Foo wants to change the storage semantics later? Or someone wants to subclass Foo and change the behavior there?

2
votes

Not a problem: "All instance variables in 64-bit Objective-C are non-fragile. That is, existing compiled code that uses a class's ivars will not break when the class or a superclass changes its own ivar layout. In particular, framework classes may add new ivars without breaking subclasses compiled against a previous version of the framework." (https://developer.apple.com/LIBRARY/mac/releasenotes/Cocoa/RN-ObjectiveC/index.html)

This also holds for the 32 bit modern runtime, of course.

Apart from the implementation technicalities, it's an exceptionally bad design though, as bbum notes.