Objective-C 中的 class_addMethod 只能在特定实例上工作吗?
我正在尝试编写一些动态代码,用户可以尝试从类的特定实例调用方法并在运行时解析它。检索信息的实现存在,但访问信息的方法不存在,因为它是基于每个实例的。
例如,用户可能想要调用类中不存在的名为“getSomething”的方法:
[someInstance getSomething]
在这种情况下,我想要解决一个实现,它具有仅适用于正在工作的实例的变量返回类型在。我正在考虑使用 class_addMethod 来自 Objective-C,但我不能 100% 确定它的行为。在文档中,它声称这可以用于添加类或实例方法。调用此类是否仅将方法添加到特定实例或类中,以便之后创建的每个实例都将具有该方法?我还读到,一旦添加了方法,就无法删除它。
也许我的方法不正确,所以如果知道任何替代方案,我将不胜感激。我无法使用消息转发,因为没有任何类可以理解已实现的选择器。
I am trying to write some dynamic code where a user can try calling a method from a specific instance of a class and have it be resolved at runtime. The implementation to retrieve the information exists but the method to access it does not because it is on a per instance basis.
For example, a user may want to call a method named "getSomething" which doesn't exist in the class:
[someInstance getSomething]
In this situation, I want to have an implementation resolved which has a variable return type that will only apply to the instance being worked on. I was considering using class_addMethod from the Objective-C but I am not 100% sure of its behavior. On the documentation it claims that this can be used to add class or instance methods. Does calling this class add the method to only the specific instance or to the class so that every instance created afterward will have the method on it? I also read that once a method is added you can't remove it.
Perhaps my approach isn't correct so if any alternatives are known I would appreciate it. I cannot use message forwarding because there is no class that understands the selector already implemented.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
另一种方法是使用动态子类:
执行此操作后,只有
object
将收到重写的方法,因为它将是唯一作为特殊类实例的东西。此外,此代码仅重写实例方法,但修改它以重写类方法并不困难。与往常一样,通常的警告:
objc_allocateClassPair()
无法使用 ARC 进行编译。Another way you could do this is with a dynamic subclass:
After doing this, only
object
will have received the overridden method, because it will be the only thing that's an instance of the special class. Also, this code only overrides instance methods, but it wouldn't be hard to modify it to override class methods.As always, the usual warnings:
objc_allocateClassPair()
cannot be compiled with ARC.class_addMethod()
将实例方法添加到类对象,或将类方法添加到元类对象。换句话说,您永远不能仅向类的一个实例添加一种方法。相反,如果您确实需要这种行为,您可以实现 -forwardInitation:,其中接收对象可以决定是否有足够的信息来履行消息。请注意,
-forwardInitation:
的实现通常需要实现-methodSignatureForSelector: 和 -respondsToSelector: 也是如此。class_addMethod()
adds an instance method to a class object or a class method to a metaclass object. In other words, you can never add a method just to one instance of a class.Instead, if you really need this behavior, you could implement -forwardInvocation:, where the receiving object can decide if it has enough information to fulfill the message. Note that an implementation of
-forwardInvocation:
typically requires implementing -methodSignatureForSelector: and -respondsToSelector: as well.我不熟悉 class_addMethod,但这也许可以帮助您澄清:
请记住,在 Objective-C 中,您不是“调用方法”,而是实际上发送消息。因此,在任何实例化对象上执行 [anyObject anyMethodName] 是安全的。该对象可能会也可能不会响应该消息。
您可以使用 [anyObject respondsToSelector:@selector(@"anyMethodName")] 检查来检查对象是否愿意,如果是,则继续执行 [anyObject anyMethodName] 调用。我无法完全理解您的问题描述,但听起来您有一个充满对象的异构容器,这些对象可能会也可能不会响应调用。对容器中的每个对象进行“respondsToSelector:”检查在 Objective-C 中是完全正常的事情,听起来像是很好的设计。
如果每个对象返回某种不同类型的数据,您可以使用“id”泛型类型来处理它。即 id returnData = [anyObject anyMethodName];然后,您可以对 returnData 使用内省,或者您可以根据“anyObject”的类进行不同的处理,由 [anyObject class] 检查;
就像,
if([anyObject class] == MyGreatClass) // recast data to MyGreatClassCoolReturnType
我希望这有助于回答这个问题
I'm not familiar with class_addMethod, but maybe this can help clarify for you:
Remember that in Objective-C you aren't "calling a method" but you're actually sending a message. So it's safe to do: [anyObject anyMethodName] on any instantiated object. This object may or may not respond to the message.
You can check whether an object will or not by using [anyObject respondsToSelector:@selector(@"anyMethodName")] check, and if that's YES, then go ahead and do [anyObject anyMethodName] call. I can't fully understand your problem description but it sounds like you have a heterogeneous container full of objects that may or may not respond to the call. Doing this "respondsToSelector:" check on each object in the container is a totally normal thing in Objective-C and sounds like good design
If every object returns some different type of data, you can handle that using the 'id' generic type. That is, id returnData = [anyObject anyMethodName]; Then, you can either use introspection on the returnData, or you could handle things differently based on what the class of 'anyObject' is, checked by [anyObject class];
So like,
if([anyObject class] == MyGreatClass) // recast data to MyGreatClassCoolReturnType
I hope this helps answer the question