使用类扩展将ivar和属性添加到类

时间:2013-05-09 23:01:49

标签: objective-c properties instance-variables objective-c-category class-extensions

我正在尝试将实例变量和属性添加到现有类中。我想这样做是为了扩展开源库的基类,而无需修改源代码(以便于代码管理)。

documentation

  

与常规类别不同,类扩展可以添加自己的类别   属性和类的实例变量。如果你宣布一个   类扩展中的属性[...]编译器将自动执行   合成相关的访问器方法,以及一个实例   变量,在主类实现中。

我尝试在测试应用中执行此操作。我有一个空课ClassA

ClassA.h

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

ClassA.m

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


然后我添加了一个扩展名:

ClassA的+ Ext.h

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

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

@end


最后在我的AppDelegate中,我只需初始化ClassA并尝试设置然后记录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

这会编译并运行,但我在控制台上收到此错误:

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

未记录该名称。如果我设置断点并检查ClassA实例,则它没有name ivar。我究竟做错了什么?这实际上不可能吗?

2 个答案:

答案 0 :(得分:3)

您的理解不正确。您通过类​​扩展添加了属性。此属性应该只能在您的类中使用。它不应该用作您的类的真正“属性”,您可以通过外部实例化来更改它。将其视为伪私有实例变量。

我相信你想要做的只是将你的A类继承。

提出的另一个可行的解决方案是:

“当使用objc_setAssociatedObject - &gt;时,您可以编写一个类别将其包装到 - [setAssociatedObject:forKey:]”中。来自@Artur

答案 1 :(得分:0)

我认为类扩展意味着放在class.m文件中,通常在类的@implementation之上。