Exposing/Synthesizing iVar properties in Objective c

可紊 提交于 2019-12-01 19:27:31

Ok, so here's the solution I found...ended up being pretty simple once you knew what to do. First overwrite '- (id) forwardingTargetForSelector:(SEL)aSelector' and return the iVar:

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

When the runtime is looking for a method and cannot find one, it will call this method to see if there is another object to forward the message to. Note that this method normally returns nil and if you return nil here, your program will crash (which is the appropriate behavior).

The second part of the problem is to shush the compiler errors/warnings you'll get when you try to send a message that's not declared. This is easily done by declaring a category you don't implement.

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

As long as you don't put in an implementation anywhere, aka @implementation Class (category), the compiler won't complain (it'll assume that the implementation is somewhere....).

Now the only drawback I see is if you change any of the properties in the interface of the iVar Class, you need to make sure you update all other classes that use the method described above, otherwise you'll crash when another class tries to send what is now the wrong method (and the compiler won't warn you beforehand). However, this can be gotten around. You can declare protocols in a category. So instead you create a separate protocol for the iVar class and move the methods/properties you wish out of the iVar class into the protocol.

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

Add that protocol to the iVar subclass so it has those methods declared through the protocol now.

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

Finally, simply add the protocol to the category. So instead of the aforementioned category with explicit declarations you'll have:

@interface Class (iVarClassMethods) <iVarClassProtocol>
@end

Now, if you need to change any of the to-be-fowarded properties/methods, you change them in the protocol. The compiler will then warn you when you try to send the wrong method to the forwarding class.

I think you can forward the messages to the 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;
}

Then you have to hide or fake the type of your object, for example by casting to id, otherwise the compiler will complain that your class does not implement those methods. Of course it would be best if you could come up with some better design that would do without such tricks.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!