6

For me the past as Objective-C developer was simple. Every field a class needed to be public was a property and every private field was an instance variable without getter or setter. But much more often I see people using a private interface inside the implementation file to declare private properties. And I have been told that is the way to do things now.

While this works fine it is hard for me to see the advantages. As long I do not need some logic in the getter or setter I would go on still using instance variables for everything not public. I have to admit using a property and then using keyword self make the code a bit more readable. You can see if a property belongs to the class or if it is just a local variable inside a method but that can not be the only reason.

Why or why not use private properties?

TalkingCode
  • 13,407
  • 27
  • 102
  • 147
  • See http://stackoverflow.com/questions/5615695/best-way-of-declaring-private-variables-in-cocoa and http://stackoverflow.com/questions/17575119/private-properties-vs-instance-variables-in-arc – Rob Nov 14 '13 at 16:36

7 Answers7

7

There are a couple of reasons to use (private) properties over ivars.

  • As you said, using properties will allow you to easily use accessor methods that do some additional coding besides just accessing the variable.
  • KVO does not work with ivars.
  • Making a public readonly property readwrite only for the implementation, to have a setter synthesized in addition to the getter (as pointed out by Brad)
  • Personal preference, habituation or laziness (property was public, but was changed to private).
DrummerB
  • 39,814
  • 12
  • 105
  • 142
  • 2
    +1 I'd add to this list that using property also obviates the need to worry about memory semantics, as it's dictated by the setter (e.g. if you have a `copy` property, every time you invoke the setter, it will automatically copy that object for you, rather than needing to remember to explicitly call `copy` every time you set an instance variable). Also, a corollary to your KVC comment, but I think it simplifies conformance with `NSCoding` (e.g. useful if archiving) and `NSCopying` (though, obviously, you don't _need_ properties to implement these protocols). – Rob Nov 14 '13 at 16:50
  • I agree with you about KVO, but what makes you say that *KVC* doesn't work with ivars? – jlehr Nov 14 '13 at 18:03
1

First, if you do not need a private property, do not use a property: unless you want to get some specific behavior from the compiler declaratively, such as forcing NSString copying on assignment, there is no benefit to using properties.

Moreover, you do not necessarily need to use self to access these properties: when a property is synthesized for you, automatically or with a @synthesize keyword, you get a variable that "backs" the property. Assigning that variable is a perfectly legal way of accessing the property, for example, when you want to present it as read-only.

However, it an advantage to making these variables private, i.e. to declaring them in a class extension, like this:

@interface MyClass() { // <<== Note the () -- it's a class extension
   SomeOtherClass *privateIvar;
}

If you declare a variable in a class extension (which goes in .m file instead of a header) you would be able to hide the header for "SomeOtherClass", which is of little importance when you develop a single app, but becomes very useful when you start developing with your own class libraries.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

IMO the OP is asking why put some ivars in the interface and some in the implementation. A side issue is why properties.

  1. The point is encapsulation. Put only those things in the public interface (.h) file that are meant to be used by design outside the class. Put those that are by design to be used only in the implementation inside the implementation (.m) file. That was anything that is not publicly exposed can be changed later without affecting the users of the class.

  2. Properties provide setter/getter methods for the associated ivars. In the current objective-c compiler if there is no @synthesize statement the compiler will auto generate the ivar with the same name as the property prefixed with an underscore (_). The getter/setters also support KVO, that may be a plus depending on your usage. Note that is it possible to declare a property readonly in the interface file and readwrite in the implementation file class extension.

So, the current best practice is to use properties for all ivars and put the property statements either in the interface file if they are designed to be public or in the implementation file in a class extension if they are designed to be private. This provided a clean interface file that only exposes public methods and properties.

zaph
  • 111,848
  • 21
  • 189
  • 228
0

properties in objective-c are not simply instance variables. they are a combination of getter and setter methods backed by an instance variable.

usually when people add properties in the implementation file (private class extension) it is to make a publicly readonly property a readwrite property so they can set it and retain all the property semantics like key-value coding. properties also take care of copy-retain for you.

Its just a method of keeping your public interface separate from the implementation.

Brad Allred
  • 7,323
  • 1
  • 30
  • 49
0

It is just a matter of encapsulation you can have many different levels of privateness...

Originally in Objective-C the runtime didn't support adding actual fields at runtime to the Object, so every iVar had to be listed in the class:

@interface MyClass : NSObject
{
//every ivar that MyClass adds to NSObject must be here
}

This was a simple and good enough system for a while...

even private iVars had to be declared, although the compiler wouldn't let you access them in the wrong scope.

@interface MyClass : NSObject
{
 @private
 id someObj;
}

this visibility specifier limited access like:

//someotherclass.m

 + (void)doSomething
 {
     MyCLass * mc = [MyClass new];
     mc->someObj = [SomeOtherClass new]; // error cant access private variable...
 }

but you could potentially get to it with pointer arithmatic, so to obfuscate you will see things like this in classes:

@interface MyClass : NSObject
{
 @private
 void * __reserved1;
 void * __private1;
}

that is pretty good obfuscation...

But Wait.... THERE HAS TO BE A BETTER WAY!

enter the non fragile ABI

now classes only need to export their super class and public interfaces.

@interface MyClass : NSObject
@property (readonly,retain) id someIVar;

and the rest of the classes contents can be included in the class extension:

@interface MyClass ()
{
 id someObj;
}
@property (readwrite,retain) id someIVar;

beware that this will only work for iPhone and 64bit OS X 32-bit OS X is still the old ABI and libraries that need to work there will need to be the old way.

Grady Player
  • 14,399
  • 2
  • 48
  • 76
  • This has nothing to do with ivars being created at runtime, they are created by the compiler at compile time. – zaph Nov 14 '13 at 16:50
  • They may be created at compile time, but they are created in a way that is dynamic, such that their offset can't be determined. – Grady Player Nov 14 '13 at 17:00
0

Well using properties might be more "convenient" (at least because you do not have to worry about forgetting calling willChange / didChange in case of KVO-able properties) and, no doubt, it's faster to use ivars instead of properties. So I would suggest using properties unless you are really concerned about frames per second. Check out this awesome post if that's the case.

dariaa
  • 6,285
  • 4
  • 42
  • 58
-1

It's really simple.

If you want to use a private @property, add this property inside your .m :

@interface MyViewController ()

@property (nonatomic, strong) NSString *myPrivateStringProperty;

@end

@implementation MyViewController

@end

Here, the property is only accessible in your .m.

If you want to use a public @property, add this property inside your .h :

@interface MyViewController : UIViewController

@property (nonatomic, strong) NSString *myPublicStringProperty;

@end

Here, the property is accessible outside your class.

Jordan Montel
  • 8,227
  • 2
  • 35
  • 40
  • 1
    I don't think the question was "how to do private vs public properties?", but rather "why private property rather than private instance variable?". – Rob Nov 14 '13 at 16:29
  • So, I don't understand sorry :( – Jordan Montel Nov 14 '13 at 16:30
  • 1
    You seem to be describing how to make a property private versus making it public. But I don't believe that was the question. The question was whether there is any advantage to using a private property rather than just defining a private instance variable (with no associated property) and using that private instance variable directly. – Rob Nov 14 '13 at 16:41