Property instead of instance variable?


#1

Hi,

Is it possible to declare “_assets” in the code below as a property?

[code]#import “BNREmployee.h”
#import “BNRAsset.h”

@interface BNREmployee ()
{
NSMutableArray *_assets;
}

@property (nonatomic) unsigned int officeAlarmCode;

@end

@implementation BNREmployee

  • (void)setAssets:(NSArray *)a
    {
    _assets = [a mutableCopy];
    }

  • (NSArray *)assets
    {
    return [_assets copy];
    }

  • (void)addAsset:(BNRAsset *)a
    {
    if (!_assets) {
    _assets = [[NSMutableArray alloc] init];
    }
    [_assets addObject:a];
    }

  • (unsigned int)valueOfAssets
    {
    unsigned int sum = 0;
    for (BNRAsset *a in _assets) {
    sum += [a resaleValue];
    }
    return sum;
    }[/code]

I tried to do it (as shown in the following cod). However, I got an error message for this line:

It says “No visible @interface for ‘NSArray’ declares the selector ‘addObject:’”

[code]#import “BNREmployee.h”
#import “BNRAsset.h”

@interface BNREmployee ()

@property (nonatomic) NSMutableArray *assets;

@property (nonatomic) unsigned int officeAlarmCode;

@end

@implementation BNREmployee

  • (void)setAssets:(NSArray *)a
    {
    self.assets = [a mutableCopy];
    }

  • (NSArray *)assets
    {
    return [self.assets copy];
    }

  • (void)addAsset:(BNRAsset *)a
    {
    if (!self.assets) {
    self.assets = [[NSMutableArray alloc] init];
    }
    [self.assets addObject:a];
    }

  • (unsigned int)valueOfAssets
    {
    unsigned int sum = 0;
    for (BNRAsset *a in self.assets) {
    sum += [a resaleValue];
    }
    return sum;
    }[/code]

I can’t figure out why it isn’t working.


#2

I think I know what I did wrong. Turns out that I already had a NSArray property named “assets” in the header file…

If you can choose between:

and

{ NSMutableArray *assets; }

which one is the best option?

EDIT: Found this: http://blog.bignerdranch.com/4005-should-i-use-a-property-or-an-instance-variable/


#3

I like property because I can go to the getter and override to handle lazy instantiation. This way from one place I can ensure that object being referenced has gone through alloc/init.


#4

I am having trouble understanding why we need to declare NSArray as a property in the header file. If instead I just declared the NSMutableArray as a property in the implementation file, then that handles the “hiding” of the array, allows me to use accessors rather than directly using the ivar (is that not the preferred syntax) and seems simpler.

Secondly, assuming there is a good reason to declare them as shown in the book (which I am sure there is), can you help me understand what is happening? Are we declaring it an Array in the header so at least others have access to the data but can’t change anything. And what is really happening in the implementation file when we declare the ivar a NSMutableArray. Are we “overriding” the type of the ivar created by the @property in the header? Can we only do that because the NSMutableArray is a subclass of NSArray? That then forces us to manipulate the ivar directly which seems to go against the “preferred” coding style that suggest only using accessors, in self.whatever notation?

THANKS!!!