实例变量的类别扩展

Mar*_*aev 5 iphone objective-c ios

有没有办法以某种方式模拟一个类的类别行为关于它的实例变量,而不是方法?

我有一个ClassA,我希望在用新方法和其他cllass(ClassB)的ivars扩展它之后保留它的名字.当然,我可以继承ClassA,但结果类会有不同的名称.

对于方法添加,这不是问题 - 类别将是一个很好的解决方案.

UPDATE: ClassA用作XIB的文件所有者,这些要扩展的字段是IBOutlets.所以我在构建阶段需要它们.

Ole*_*ann 6

由于iPhone使用现代的Objective-C运行时,您可以使用关联引用将数据添加到实例,而无需声明实例变量.请参阅文档objc_setAssociatedObject等.

如果用标准访问器方法将调用包装到运行时,它将非常容易使用.


Mar*_*aev 3

我研究了这个问题,围绕关联引用(感谢Ole),使用方法静态变量,方法混合,最后得出这个简单的解决方案(没有运行时的东西)。我只是使用“分类”类来返回指向派生类的指针,派生类当然可以包含其他 ivars。这样做我获得了一个意想不到的好处:我可以调用super的类方法,这在通过类别扩展时是不可能的。

类扩展示例(已测试):

A类+B类.h

@protocol _ClassB_Protocol
  @optional // to avoid warnings
- (IBAction) onClick:(id)sender;
  @property (nonatomic, retain) IBOutlet UIButton *aButton;
@end

@interface ClassA (_ClassA_Category) <_ClassB_Protocol>
@end

@interface ClassB: ClassA <_ClassB_Protocol> {
    UIButton *aButton; // _ivar_ to add
}
@end
Run Code Online (Sandbox Code Playgroud)

A类+B类.m

@implementation ClassA (_ClassA_Category)
// this will be called first on [ClassA alloc] or [ClassA allocWithZone:(NSZone *)zone]
+(id) alloc {
    if ([self isEqual: [ClassA class]]) {
        return [ClassB alloc];
    } else {
        return [super alloc];
    }
}
@end


@implementation ClassB: ClassA

@synthesize aButton;

-(void) dealloc {
    [aButton release];

    [super dealloc]; // this is impossible for an ordinary category
}

- (void) onClick:(id)sender {
    // some code here
}

@end
Run Code Online (Sandbox Code Playgroud)

现在我们在同一时间:

  • ClassB“扩展” ClassA(类别方式);
  • ClassB继承ClassAClassB可以调用ClassA方法);
  • ClassBClassA可以通过名称(类别方式)访问