本文介绍了动态Getters和Setter与Objective C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在某种情况下,我想在运行时为一个类动态生成getter和setter(以类似于NSManagedObject在后台的方式)。从我的理解,这是可能使用resolveInstanceMethod:在一个特定的类。此时,您必须使用class_addMethod动态添加基于选择器的方法。我理解这在理论层面,但我没有深入到obj-c运行时,所以我很好奇,如果有任何伟大的例子如何做到这一点。我的大部分知识来自这篇文章:

I am in a situation where I want to dynamically generate getters and setters for a class at runtime (in a similar manner to what NSManagedObject does behind the scenes). From my understanding, this is possible using resolveInstanceMethod: on a specific class. At this point, you would have to use class_addMethod to dynamically add the method based on the selector. I understand this at a theoretical level, but I haven't delved much into the obj-c runtime, so I was curious if there were any great examples of how to do this. Most of my knowledge comes from this article:

任何想法/示例?

推荐答案

Ash的。这不是那么难,实际上。

The only nice discussion I know is at Mike Ash's blog post. It's not that hard, actually.

我曾经需要将一个大的 NSManagedObject 子类拆分为两个,但决定保留实现细节我不必重写我的应用程序的其他部分。所以,我需要合成getter和setter,发送 [self foo] 到 [self.data foo] 。

I once needed to split a big NSManagedObject subclass into two, but decided to keep the fact an implementation detail so that I don't have to rewrite other parts of my app. So, I needed to synthesize getter and setter which sends [self foo] to [self.data foo], automatically.

为此,我做了以下工作:

To achieve that, I did the following:


  1. 新的方法,已经在我的类。

  1. Prepare the new method, already in my class.

- (id)_getter_
{
    return objc_msgSend(self.data, _cmd);
}

- (void)_setter_:(id)value
{
    objc_msgSend(self.data, _cmd,value);
}

注意 _cmd 有选择器。因此,通常, _cmd 是 @selector(_getter _)或 @selector(_setter_) 在这些方法中,但我要插入 _getter _ 的实现作为 foo 。然后, _cmd 包含 @selector(foo),因此调用 self.data '

Note that _cmd has the selector in it. So, usually, _cmd is either @selector(_getter_) or @selector(_setter_) in these methods, but I'm going to plug the implementation of _getter_ as the implementation of foo. Then, _cmd contains @selector(foo), and thus calls self.data's foo.

写一个通用合成方法:

+(void)synthesizeForwarder:(NSString*)getterName
{
    NSString*setterName=[NSString stringWithFormat:@"set%@%@:",
          [[getterName substringToIndex:1] uppercaseString],[getterName substringFromIndex:1]];
    Method getter=class_getInstanceMethod(self, @selector(_getter_));
    class_addMethod(self, NSSelectorFromString(getterName),
                    method_getImplementation(getter), method_getTypeEncoding(getter));
    Method setter=class_getInstanceMethod(self, @selector(_setter_:));
    class_addMethod(self, NSSelectorFromString(setterName),
                    method_getImplementation(setter), method_getTypeEncoding(setter));
}

注意这是一个类方法。因此 self 代表类。还要注意,我没有硬编码类型编码(这告诉Objective-C运行时特定方法的参数)。类型编码的语法是文档化的,但手工构建非常容易出错;我浪费了几天,直到迈克·艾姆告诉我停止它。

Note that this is a class method. So self stands for the class. Note also that I didn't hardcode type encodings (which tells Objective-C runtime what the arguments of the particular method are). The syntax of type encodings is documented, but constructing by hand is very error-prone; I wasted a few days that way until Mike Ash told me to stop it. Generate it using an existing method.

尽早生成转发器:

 +(void)load
 {
     for(NSString*selectorName in [NSArray arrayWithObjects:@"foo", @"bar", @"baz",nil]){
        [self synthesizeForwarder:selectorName];
     }
 }

这会生成 foo , setFoo:, bar , setBar:和 baz , setBaz:。

希望这有助于!

这篇关于动态Getters和Setter与Objective C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 19:34