在Objective c中公开/合成iVar属性

时间:2012-02-23 15:13:09

标签: objective-c properties instance-variables ivar

我有一个类,它基本上作为另一个类的轻量级包装类。它认为其他类作为iVar。我希望能够暴露iVar的某些属性(实际上有很多),但为了这样做,我必须写出每个属性访问器,如下所示:

- (void) setProperty:(Class *)value{
    _iVar.property = value;
}
- (Class *) property{
    return  _iVar.property;
}

当然,我必须为每一个属性做这个,这是一个痛苦(大约有30个)。我希望能够合成这个,但我无法弄清楚如何。

是否可以合成?

另外,我不能继承....好吧,我可能会,但它真的不推荐。 iVar类非常重(它实现了CoreText)。我宁愿手工写出这些方法。

2 个答案:

答案 0 :(得分:4)

好的,所以这里是我找到的解决方案......一旦你知道该做什么,最终变得非常简单。首先覆盖' - (id)forwardingTargetForSelector:(SEL)aSelector'并返回iVar:

- (id) forwardingTargetForSelector:(SEL)aSelector{
    return iVar;
}

当运行时查找方法但找不到方法时,它将调用此方法以查看是否有另一个对象将消息转发到。请注意,此方法通常返回nil,如果此处返回nil,则程序将崩溃(这是适当的行为)。

问题的第二部分是当您尝试发送未声明的消息时,会扼杀编译器错误/警告。通过声明未实现的类别可以轻松完成此操作。

@interface Class (iVarClassMethods)
@propoperty (strong) Class *property1;
......more properties
@end

只要您不在任何地方(即@implementation Class (category))放置实现,编译器就不会抱怨(它会假设实现某处...... )。

现在唯一的缺点是,如果你更改了iVar类接口中的任何属性,你需要确保更新所有其他使用上述方法的类,否则你会在另一个类时崩溃尝试发送现在错误的方法(编译器不会事先警告你)。但是,这个可以得到。您可以在类别中声明协议。因此,您可以为iVar类创建单独的协议,并将您希望的方法/属性从iVar类移动到协议中。

@protocol iVarClassProtocol
@propoperty (strong) Class *property1;
......more properties
@end

将该协议添加到iVar子类中,以便它现在具有通过协议声明的那些方法。

@interface iVarClass <iVarClassProtocol>
....other methods/properties you don't need forwarded
@end

最后,只需将协议添加到类别中即可。因此,您将拥有明确的声明,而不是前面提到的类别:

@interface Class (iVarClassMethods) <iVarClassProtocol>
@end

现在,如果您需要更改任何要转发的属性/方法,请在协议中更改它们。当您尝试将错误的方法发送到转发类时,编译器将发出警告。

答案 1 :(得分:2)

我认为您可以将消息转发给ivar:

- (void) forwardInvocation: (NSInvocation*) invocation
{
    [invocation invokeWithTarget:ivar];
}

- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector
{
    NSMethodSignature *our = [super methodSignatureForSelector:selector];
    NSMethodSignature *ivars = [ivar methodSignatureForSelector:selector];
    return our ? our : ivars;
}

然后你必须隐藏或伪造你的对象的类型,例如通过强制转换为id,否则编译器会抱怨你的类没有实现这些方法。 当然,如果你能想出一些没有这些技巧的更好的设计,那将是最好的。