2

What is difference of these three cases (all of them are used like private fields):

1.

@interface APLParseOperation : NSOperation

@property (copy, readonly) NSData *earthquakeData;

@end

2.

@interface APLParseOperation () <NSXMLParserDelegate>

@property (nonatomic) APLEarthquake *currentEarthquakeObject;
@property (nonatomic) NSMutableArray *currentParseBatch;
@property (nonatomic) NSMutableString *currentParsedCharacterData;

@end

3.

@implementation APLParseOperation
{
    NSDateFormatter *_dateFormatter;
    BOOL _accumulatingParsedCharacterData;
    BOOL _didAbortParsing;
    NSUInteger _parsedEarthquakesCounter;
}

It's a good practice or smthing else?

pvllnspk
  • 5,667
  • 12
  • 59
  • 97
  • 1. the property is public and readonly, it cannot be changed from outside of the class but can be read its value anytime, 2. it is still readable from outside and can be overridden from outside of the class too, 3. those internal ivars are not visible from outside of the class. – holex Jun 24 '14 at 16:27

4 Answers4

2

I'm going to go through each example you gave, and describe them. I was just having trouble with this yesterday so I feel your pain.

1.

@interface APLParseOperation : NSOperation

@property (copy, readonly) NSData *earthquakeData;

@end

By using the @property keyword, the compiler automatically synthesizes your accessor methods for you, and also a backing instance variable. However, because you are using the readonly property attribute, the compiler is only synthesizing a getter method for you.

2.

@interface APLParseOperation () <NSXMLParserDelegate>

@property (nonatomic) APLEarthquake *currentEarthquakeObject;
@property (nonatomic) NSMutableArray *currentParseBatch;
@property (nonatomic) NSMutableString *currentParsedCharacterData;

@end

This second example is very similar to the first. However, because none of them have the readonly property attribute, they will all have getters and setter methods synthesized for them, as well as the backing instance variable.

3.

@implementation APLParseOperation
{
    NSDateFormatter *_dateFormatter;
    BOOL _accumulatingParsedCharacterData;
    BOOL _didAbortParsing;
    NSUInteger _parsedEarthquakesCounter;
}

For this last example, you are just declaring instance variables. These are also private to your implementation file, where as the other 2 examples had declarations being made in your classes interface file.

No setter or getter methods are being synthesized for you by the compiler. You are simply declaring some instance variables.

In terms of private and public, your first and second examples both provide declarations that will be visible to other classes, as long as they import the current class's header file. The first example however, only provides a way to "get" the property and read it, there is no setter method because you used the readonly property attribute. With the second example, outside classes will be able to access your getter and setter methods for your property, so they can read and write.

For the third example, these are just instance variables and they are private to your class's implementation file. Basically, no outside classes will even know that they exist.

user3344977
  • 3,584
  • 4
  • 32
  • 88
1
  1. This is not private. It is still readable by outside classes, though it can't be written.
  2. Private properties. It can be useful if you want to write custom getters and setters. If you are not using ARC, it can be helpful for memory management.
  3. Private members. This is my favorite. It's easy to read and easy to write.
Neal Ehardt
  • 10,334
  • 9
  • 41
  • 51
1

Case 1. is not private. It's a public read-only property: Reading is public, writing is only possible only in the private scope via the underlying ivar (thanks for pointing it out @mah).

Case 2. (if in a .m file) is extending the class by adding 3 private properties and making the protocol conformance private too.

Case 3. is declaring 4 private instance variables that can be used in all the implementation scope.

Objective-C best practice for private properties is case 2., as case 1. is not private at all, just read-only, and case 3. uses instance variables (aka ivar) which is less conventional than properties. More on that here: Reason to use ivars vs properties in objective c

Hope this helps,

Community
  • 1
  • 1
Zedenem
  • 2,479
  • 21
  • 23
  • writing the case 1 properties via the property is impossible but the backing value is still writable. I.e., assuming no custom naming synthesis, an object of the _APLParseOperation_ class can run a method that performs "_earthquakeData = [[NSData alloc] init....];" and it will change the value read from that property. – mah Jun 24 '14 at 16:31
  • _writing is impossible, even in a private scope._ that is not true at all like this, because the property can be modified bypassing the _setter_. which is possible fro inside the class. – holex Jun 24 '14 at 16:34
  • You are right, I modified my answer to reflect that. Even if, in terms of conventions and best practices, you should use ivars as less as possible... – Zedenem Jun 24 '14 at 16:36
1
  1. defines a public property visible to all users of the APLParseOperation class.
  2. defines properties through an extension, making them available only to the implementation methods.
  3. defines instance variables which are implicitly private.

Number 1 is used when you want to make your properties public. Numbers 2 and 3 are for private properties and instance variables. You can also declare instance variables in class extensions, like this:

@interface APLParseOperation () <NSXMLParserDelegate>
{
    NSDateFormatter *_dateFormatter;
    BOOL _accumulatingParsedCharacterData;
    BOOL _didAbortParsing;
    NSUInteger _parsedEarthquakesCounter;
}
@end

There is not much difference between that and the number 3. It is a good idea to pick one style, and stick to it in all your code.

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