In Objective-C, instance variables can be accessed directly by name in any instance method of the class. AKA an instance can directly access its own iVars by name. I believe this is safe and acceptable. Your situation will not work as described because of the infinite loop you are creating
(-allPossessions calls -fetchPossessionsIfNecessary which calls -allPossessions. Although the two following examples are the same, this is best practice or else BNR wouldn’t have suggested it.
I believe the convention of accessing iVars through setters/getters refers to external “objects” and their quest to obtain specific values from an object’s iVars. I put together a small example that shows what will happen if you try to directly access iVars from a source other than the instance where the iVar is declared. I created a Person class whose interface and implementation are as follows:
@interface Person : NSObject
@property (nonatomic, copy) NSString *firstName;
Next, I created an instance of the Person class in main like so:
int main (int argc, const char * argv)
Person *brian = [[Person alloc] init];
NSLog(@"Using a setter/getter:");
NSLog(@"brian's first name is: %@", [brian firstName]);
NSLog(@"Directly accessing the iVar:");
brian->firstName = @"Brian";
NSLog(@"Direct Access: brian's first name is %@", brian->firstName);
This code would not build. The error I received was “Instance variable ‘firstName’ is protected”. By default, the iVars of objects you create are @protected. You can change this to either @private and @public. @protected means that the iVar can be accessed by name by the class and any subclasses. @private means that only that particular class can access the iVar by name. @public means that any object can access the iVar by name. In order to build this code so you can see the output, I changed the firstName iVar to @public like so:
@interface Person : NSObject
This code would then build and here is the output:
By changing the firstName iVar to @public, main() was able to access the iVar via the “->” operator. Without the @public declaration, the code failed to build. To sum, you should feel safe about accessing the iVar by name in a class where it is declared due to the default @protected nature.
As a side note, I’m not going to argue whether accessors in the -init is right or wrong, however instead of calling accessors in your -init (PRE-ARC), you could do something like this
-(id)initWithPossessionName:(NSString *)name serialNumber:(NSString *)number valueInDollars:(int)value
self = [super init];
possessionName = [name copy];
serialNumber = [number copy];
valueInDollars = value;
dateCreated = [[NSDate date] retain];
Here, the iVar is set directly and through “copy” and “retain” the values are retained by the Possession instance. By creating properties, subsequent setting / getting of the values will result in proper memory management.
ARC changes this so I wouldn’t worry about it. I was merely demonstrating that accessors need not be utilized to access the instance’s own iVars in the -init and/or otherwise. Also, I’m not sure of the overhead of calling an accessor rather than directly accessing an iVar, but I imagine there is a difference albeit minimal in a small application.