objective-cvisibilitycategoriesivar

Can a category access instance variables defined in the class it extends?


I know it's not a great idea to try and place properties in a category. Can I access a class' instance variables from within a category that extends it? Or is it necessary to expose an accessor on the class being extended?

For example, let's say I have a class called "Person" and its implementation looks like this:

#import "Person.h"

@interface Person()
{
    NSMutableArray *_friends;
}
@end

@implementation Person

- (instancetype)init
{
    self = [super init];
    if (self) {
        _friends = [NSMutableArray array];
    }
    return self;
}

-(instancetype)initWithFirstname:(NSString *)firstName lastname:(NSString *)lastName
{
    self = [self init];
    if (self) {
        _firstName = firstName;
        _lastName = lastName;
    }
    return self;
}

-(NSString *)getFullName{
    return [NSString stringWithFormat:@"%@ %@", _firstName, _lastName];
}

@end

Notice the ivar _friends. Let's say (for some reason or other) I wanted to segregate all operations dealing with a person's friends into a category, like so:

#import "Person.h"

@interface Person (Friends)
-(NSArray *)getFriends;
-(void)addFriend:(Person *)person;
-(void)removeFriend:(Person *)person;
@end

In the category, Person(Friends), the compiler will not know about Person's ivar _friends.

i.e.

//Person.h 

@interface Person
@property(nonatomic, strong) NSMutableArray *friends;
...
@end

It would be preferable to not expose this.


Solution

  • In general, categories can't access ivars; synthesized ivars and ivars from class extensions are private and invisible outside the main implementation.

    You can, however, do what you want by declaring the ivar in an extension which is in its own private header, and importing that header into the category's implmentation file. Be sure to also import the private header into the class's main implementation file.