使用NSMutableDictionary作为属性的后备存储 [英] Using NSMutableDictionary as backing store for properties

查看:160
本文介绍了使用NSMutableDictionary作为属性的后备存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种简单的方法来设置我的属性直接NSMutableDictionary是一个实例变量。即:

I am looking for a shorthand way of setting my properties directly to an NSMutableDictionary that is a instance variable. ie:

KVCModle.h:

KVCModle.h:

@interface KVModel : NSObject {
    NSMutableDictionary * data;
}
@property(nonatomic,assign)NSString * string1;
@property(nonatomic,assign)NSString * string2;
@end

KVCModel.m

KVCModel.m

#import "KVModel.h"


@implementation KVModel

-(id)init
{
    self = [super init];
    if(self)
    {
        data = [[NSMutableDictionary alloc] init];
    }
    return self;
}

-(NSString *)string1
{
    return [data objectForKey:@"string1"];
}
-(NSString *)string2
{
    return [data objectForKey:@"string2"];
}
-(void)setString1:(NSString *)_string1
{
    [data setObject:_string1 forKey:@"string1"];
}
-(void)setString2:(NSString *)_string2
{
    [data setObject:_string2 forKey:@"string2"];
}
-(void)dealloc
{
    [data release];
    [super dealloc];
}

@end

我试图覆盖 setValue:ForKey: valueForKey:,但是这些不被调用,它们允许你直接设置属性,属性语法。

I have tried to override setValue:ForKey: and valueForKey:, but those aren't called, they allow you to directly set properties without using the property syntax.

我已经使预处理器宏在过去工作,但我不想打字,而且想避免尽可能多的因为我可以在将来。有没有办法让这个工作,我不熟悉?

I have made preprocessor macros to make this work in the past, but I am not interested in typing at all, and would like to avoid as much of it as I can in the future. Is there a way to make this work that I am not familiar with?

我想过使用NSManagedObject,但我不知道如果我可以得到我想要的的。
修改:
源< a>

I have thought about using NSManagedObject, but I am not sure if I can get what I want out of that. source

推荐答案

如果您尝试使用 foo = obj.foo obj.foo = foo ,这就是为什么它不工作。

If you're trying to access the properties with code like foo = obj.foo and obj.foo = foo, that's why it doesn't work.

属性访问语法与消息语法是同义的;前者与 foo = [obj foo] 完全相同,后者与 [obj setFoo:foo] 。没有KVC代码来拦截。属性在语言级别; KVC是在框架级别。

Property-access syntax is synonymous with message syntax; the former is exactly the same as foo = [obj foo], and the latter is exactly the same as [obj setFoo:foo]. There is no KVC code to intercept. Properties are at the language level; KVC is at the framework level.

您需要拦截访问器消息。请考虑实施 resolveInstanceMethod:类方法,其中解析选择器通过添加一个方法实现到类使用Objective-C运行时API。您可以为许多不同的选择器添加相同的实现。

You'll need to intercept the accessor messages instead. Consider implementing the resolveInstanceMethod: class method, in which you "resolve" the selector by adding a method implementation to the class using the Objective-C runtime API. You can add the same implementation(s) for many different selectors.

出于您的目的,有一个函数或方法检查选择器(使用 NSStringForSelector 和常规NSString检查技术)并返回两个事实:(1)属性名称,和(2)是否是一个getter( foo isFoo )或setter( setFoo:)。然后,有两个方法,一个是动态getter,另一个是动态setter。当选择器命名getter时,使用dynamic-getter方法添加它;当选择器命名一个setter时,用你的dynamic-setter方法添加它。

For your purpose, have a function or method that examines the selector (using NSStringForSelector and regular NSString-examining techniques) and returns two facts: (1) the property name, and (2) whether it's a getter (foo, isFoo) or setter (setFoo:). Then, have two more methods, one a dynamic getter and the other a dynamic setter. When the selector names a getter, add it with your dynamic-getter method; when the selector names a setter, add it with your dynamic-setter method.

那么dynamic-getter和-setter方法如何工作?他们需要知道什么属性动态获取和设置,但他们还需要没有参数(getter)或一个参数(setter,它接受值),以匹配原始的属性访问消息。你可能想知道这些泛型实现如何知道要获取或设置的属性。答案是:它在选择器中!用于发送消息的选择器作为隐藏参数 _cmd 传递给实现,因此检查选择器的方式与之前一样,以提取应动态的属性名称获取或设置。然后,动态getter应该发送 [data objectForKey:keyExtractedFromSelector] ,动态设置器应该发送 [data setObject:newValue forKey:keyExtractedFromSelector]

So how do the dynamic-getter and -setter methods work? They'll need to know what property to dynamically get and set, but they also need to take no arguments (getter) or one argument (setter, which takes the value), in order to match the original property-access message. You might be wondering how these generic implementations can know what property to get or set. The answer is: It's in the selector! The selector used to send the message is passed to the implementation as the hidden argument _cmd, so examine that selector the same way as before to extract the name of the property you should dynamically get or set. Then, the dynamic getter should send [data objectForKey:keyExtractedFromSelector] and the dynamic setter should send [data setObject:newValue forKey:keyExtractedFromSelector].

两个警告:


  1. 从编译器,当你使用属性访问语法访问一个属性,你没有在类的 @interface 中声明。这是正常的和有意的;你真的只应该使用属性访问语法来访问已知的形式属性。你正在做什么,虽然我觉得很有趣,但在技术上是滥用属性访问语法。

  2. 这只会对对象值有效。 KVC为原始值(例如整数)执行装箱和取消装箱;因为KVC不涉及,没有免费拳击和拆箱。如果你已经声明了正式的属性(见1),你需要使用Objective-C运行时API进行内省,然后用你的结果进行打包和取消打包。

  1. You may still get complaints from the compiler when you use the property-access syntax to access a "property" that you have not declared in the class's @interface. This is normal and intentional; you're really only supposed to use property-access syntax to access known formal properties. What you're doing, while I found it fun to solve, is technically an abuse of the property-access syntax.
  2. This will only work for object values. KVC does the boxing and unboxing for primitive values, such as integers; since KVC is not involved, no free boxing and unboxing. If you have declared formal properties (see 1), you'll need to introspect them using the Objective-C runtime API, and do the boxing and unboxing yourself with your findings.

这篇关于使用NSMutableDictionary作为属性的后备存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆