Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 359
Nick Avatar asked Mar 16 '14 19:03

Nick


People also ask

What is difference between category and extension?

Category and extension both are basically made to handle large code base, but category is a way to extend class API in multiple source files while extension is a way to add required methods outside the main interface file.

What is difference between instance variable and class variable?

It has many copies so every object has its own personal copy of the instance variable. It has only one copy of the class variable so it is shared among different objects of the class. It can be accessed directly by calling variable names inside the class. It can be accessed by calling with the class name.

Which one of the keyword Cannot be used with instance variable in Java?

Instance Variable cannot have a Static modifier as it will become a Class level variable. Meaning STATIC is one of the keyword which cannot be used with Instance variable.

Where do I declare instance variables?

Instance variables are declared in a class, but outside a method, constructor or any block. When space is allocated for an object in the heap, a slot for each instance variable value is created.


2 Answers

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.

like image 78
jscs Avatar answered Sep 30 '22 02:09

jscs


Who have told you that the compiler will not know about Person's _friends? It knows. Just declare _friends in the class @interface, not in an extension.

@interface Person : NSObject
{
@protected
      NSMutableArray *_friends;
}
@end

With @protected _friends will not be accessible for other objects.

like image 37
Cy-4AH Avatar answered Sep 30 '22 01:09

Cy-4AH