使用类扩展将ivar和属性添加到类
问题描述:
我试图将实例变量和属性添加到现有类。我想要这样做来扩展开源库的基类,而不修改源代码(为了更容易的代码管理)。使用类扩展将ivar和属性添加到类
不同于常规类,一类扩展可以添加自己的 属性和实例变量的类。如果您在类扩展中声明 属性,编译器将自动合成 合成主类实现内的相关访问器方法以及实例 变量。
我试图在测试应用程序中做到这一点。我有一个空类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
伊娃。我究竟做错了什么?这实际上不可能做到吗?
答
你的理解是不正确的。您通过类扩展添加了一个属性。这个属性应该只能在你的类中使用。它不应该被用作你的类的一个真正的“属性”,你可以通过外部实例化来改变它。把它看作一个伪私有实例变量。
我相信你想要做的就是简单地继承你的A类什么
提出的另一种可行的解决方案是:
“你可以写一个类别,它包装成 - [setAssociatedObject:forKey:]”当使用objc_setAssociatedObject - > by @Artur
答
我认为类扩展应该放在class.m文件中,通常放在类的@implementation之上。
这个错误与一个ivar在那里或没有没有关系。问题在于该属性的setter方法无法识别。注释掉'a.name = ...'这一行并查看在日志语句中是否存在与“getter”有关的问题。 – rmaddy 2013-05-09 23:04:35
如果我这样做,我得到的错误为getter [[ClassA name]] – DrummerB 2013-05-09 23:07:44
正如删除的答案所述,添加到类扩展中的属性对于类是私有的。这就是为什么另一个类无法看到private属性'name'的setter或getter。 – rmaddy 2013-05-09 23:11:12