1

I have a few questions about variable/object declaration in Objective-C, and am hoping to understand a few things better.

  1. I know that giving a variable an @property declaration allows you to access it from other classes, if you don't plan to use it outside of it own class, is there any use in this?

  2. I often see in sample code variables and objects are only declared using @property and not directly in the @interface. Why?

  3. I also see people when using @synthesize, do something like var = _var;. How come?

  4. When referencing objects and variables, is there any reason, for example to do self.var. rather than var.?

halfer
  • 19,824
  • 17
  • 99
  • 186
Josh Kahane
  • 16,765
  • 45
  • 140
  • 253

3 Answers3

3
  1. @property and synthesize, even used privately, give you prebuilt getters and setters. That's why I use them.

  2. In more recent Xcode, you get a synthesize supplied for you, so you can treat @property alone as a pair with @synthesize.

  3. The underscore alias lets you name stack variables the same without ambiguity, e.g....

    // say my class contains a property called foo, alias _foo.
    - (void)initWithFoo:(id)foo {
        self = [self init];
        if (self) {
            _foo = foo;  // assign the param to the instance var
        }
        return self;
    }
    
  4. It's good practice to use getters and setters outside of init and dealloc. The getter's and setters "pinch off" access to the property to a single place where you might want to add behavior. For example, a common practice is to use the getter as a lazy initializer ...

    // this code assumes ARC, otherwise for retained properties without arc, you'll need to add release and retain code here and if you replace the default setter
    - (SomeType *)bar {
        if (!_bar) {
            _bar = [[SomeType alloc] init];
        }
        return _bar;
     }
    
danh
  • 62,181
  • 10
  • 95
  • 136
  • 1
    "// assign the param to the property" isn't quite right -- you're assigning the parameter to the instance variable. It doesn't use the property setter. Also, when not under ARC, it should probably be `_foo = [foo retain]` or `_foo = [foo copy]`, just for the sake of anyone reading. – Chuck Jan 01 '13 at 03:21
  • Thanks, @Chuck - I'll edit the comment. Will also point out that I'm assuming ARC. – danh Jan 01 '13 at 03:29
2
  1. You can also access variables that you don't declare as a property. A property is just a shortcut. A way to tell the compiler to automatically create getter and setter (accessor) methods for that variable. The flags you sometimes see in brackets are additional options that change the actual implementation of the accessor methods.
  2. Because in that case an instance variable will automatically be added to your class at compile time. The name of that variable will be the same as your property, except an additional underscore prefix (_var).
  3. This allows you to change the name of the automatically generated instance variable. Left from the equal sign is the property; the instance variable is on the right side. You an also declare the instance variable yourself and if it's different from the property's name, you have to assign it this way.
  4. Using self.var will use the accessor methods (whether or not they were added automatically, or you implemented them yourself). For instance if you want to load an object lazily, you can implement a getter yourself that checks if the object already exists, creates it if not, and returns it:

    // Assuming you defined  @property (nonatomic) MyClass *var;  in the header
    - (MyClass *)var {
        if (!_var) {
            _var = [[MyClass alloc] init];
        }
        return _var;
    }
    

    Now you can access it using the dot syntax:

    [self.var doSomething];
    

    This will call the getter defined above. If the variable is nil (not used yet), it's initialized first. If you just used the instance variable...

    [_var doSomething];
    

    ... you will get a different result. If _var is nil, the message will simply be ignored (no error, crash). This is because you access the variable directly, not via an accessor method. Of course if you're sure that the object will be initialized, or handle the case when it's nil, then you can use it directly.

DrummerB
  • 39,814
  • 12
  • 105
  • 142
1
  1. When you use @property that is synthesized* you can avoid writing "boilerplate" code, such as copying or locking to make access atomic. The importance of this feature has greatly diminished with the introduction of ARC.
  2. With no need to write @synthesize in the latest Xcode, you can use properties with little or no additional coding. Since properties are more "future proof" than variables because you can perform validation in the setter and calculations in the getter, you have almost no reason to use "plain" variables.
  3. The use of @synthesize is not necessary in the latest Xcode. If you see a lot of @synthesize, chances are that you are reading an "old code" (more than 6 months old).
  4. No, there is no reason to do that with variables. Some shops require programmers to do that anyway, allegedly for clarity. I would not comment on that, because this is a matter of preference. If you decide to do it, you should do it consistently across your entire code base.
    * Either explicitly through @synthesize or implicitly with the latest Xcode.
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523