Question

I'm trying to add an instance variable and a property to an existing class. I want to do this to extend the base class of an open source library, without modifying the source code (for easier code management).

The documentation says

Unlike regular categories, a class extension can add its own properties and instance variables to a class. If you declare a property in a class extension [...] the compiler will automatically synthesize the relevant accessor methods, as well as an instance variable, inside the primary class implementation.

I tried to do this in a test app. I have an empty class ClassA:

ClassA.h

#import <Foundation/Foundation.h>
@interface ClassA : NSObject
@end

ClassA.m

#import "ClassA.h"    
@implementation ClassA
@end


Then I added an extension:

ClassA+Ext.h

#import "ClassA.h"
@interface ClassA ()

@property (nonatomic) NSString *name;      // <-- this is my new property

@end


Finally in my AppDelegate I simply init a ClassA and try to set and then log the name.

#import "AppDelegate.h"
#import "ClassA.h"
#import "ClassA+Ext.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    ClassA *a = [[ClassA alloc] init];
    a.name = @"test";
    NSLog(@"Name: %@", a.name);
}

@end

This compiles and runs, but I get this error on the console:

2013-05-10 00:58:08.598 Test[53161:303] -[ClassA setName:]: unrecognized selector
sent to instance 0x108a1a630
2013-05-10 00:58:08.600 Test[53161:303] -[ClassA setName:]: unrecognized selector 
sent to instance 0x108a1a630

The name is not logged. And if I set a breakpoint and inspect the ClassA instance, it doesn't have a name ivar. What am I doing wrong? Isn't this actually possible to do?

Was it helpful?

Solution

Your understanding is incorrect. You added a property through a class extension. This property should only be able to be used inside your class. It should not be used as a true "property" for your class in which you can change it through external instantiation. Think of it as a pseudo private instance variable.

I believe what you want to do is simply subclass your Class A.

Another viable solution proposed was:

"You can write a category to wrap it into -[setAssociatedObject:forKey:]" when using objc_setAssociatedObject --> by @Artur

OTHER TIPS

I think class extensions are meant to be put in the class.m files, usually above the @implementation of the class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top