我正在尽力解释它是如何工作的,但这非常令人困惑且冗长。让我知道是否有什么我可以做的澄清。
我陷入了 KVC 和 KVO 概念。
我有一个入口类(NSObject)。
入口类具有私有变量 objectProperties (NSDictionary),其值来自服务器。
假设 objectProperties 有键“价格”、“折扣”等,那么我想在 Entry 类的实例中创建动态属性。
这些键可以根据响应和动态变量而变化。
现在,当用户想要在相同的属性上使用 KVO 时,它们将无法访问。
用于创建动态属性,它是 Getter/Setter:
-(NSString*)propName:(NSString*)name {
name = [name stringByReplacingOccurrencesOfString:@":" withString:@""];
NSRange r;
r.length = name.length -1 ;
r.location = 1;
NSString* firstChar = [name stringByReplacingCharactersInRange:r withString:@""];
if([firstChar isEqualToString:[firstChar lowercaseString]])
{return name;}
r.length = 1;
r.location = 0;
NSString* theRest = [name stringByReplacingCharactersInRange:r withString:@""];
return [NSString stringWithFormat:@"%@%@", [firstChar lowercaseString] , theRest];
}
-(NSString*)setterName:(NSString*)name {
name = [self propName:name];
NSRange r;
r.length = name.length -1 ;
r.location = 1;
NSString* firstChar = [name stringByReplacingCharactersInRange:r withString:@""];
r.length = 1;
r.location = 0;
NSString* theRest = [name stringByReplacingCharactersInRange:r withString:@""];
return [NSString stringWithFormat:@"set%@%@", [firstChar uppercaseString] , theRest];
}
-(NSString*)propNameFromSetterName:(NSString*)name {
NSRange r;
r.length = 3 ;
r.location = 0;
NSString* propName = [name stringByReplacingCharactersInRange:r withString:@""];
return [self propName:propName]; }
-(NSString*)ivarName:(NSString*)name {
NSRange r;
r.length = name.length -1 ;
r.location = 1;
NSString* firstChar = [name stringByReplacingCharactersInRange:r withString:@""].lowercaseString;
if([firstChar isEqualToString:@"_"])
return name;
r.length = 1;
r.location = 0;
NSString* theRest = [name stringByReplacingCharactersInRange:r withString:@""];
return [NSString stringWithFormat:@"_%@%@",firstChar, theRest]; }
NSObject *getter(id self, SEL _cmd)
{
NSString* name = NSStringFromSelector(_cmd);
NSString* ivarName = [self ivarName:name];
Ivar ivar = class_getInstanceVariable([self class], [ivarName UTF8String]);
return object_getIvar(self, ivar);
}
void setter(id self, SEL _cmd, NSObject *newObj)
{
NSString* name = [self propNameFromSetterName:NSStringFromSelector(_cmd)];
NSString* ivarName = [self ivarName:name];
Ivar ivar = class_getInstanceVariable([self class], [ivarName UTF8String]);
id oldObj = object_getIvar(self, ivar);
if (![oldObj isEqual: newObj])
{
object_setIvar(self, ivar, newObj);
[newObj copy];
}
}
-(NSDictionary *)createProperties:(NSArray *)propNames {
NSMutableDictionary* keys = [[NSMutableDictionary alloc]init];
for(NSString* key in propNames)
{
NSString* propName = [self propName: key];
NSString* iVarName = [self ivarName:propName];
class_addIvar([self class], [iVarName UTF8String] , sizeof(NSObject*), log2(sizeof(NSObject*)), @encode(NSObject));
objc_property_attribute_t a1 = { "T", "@\"NSObject\"" };
objc_property_attribute_t a2 = { "&", "" };
objc_property_attribute_t a3 = { "N", "" };
objc_property_attribute_t a4 = { "V", [iVarName UTF8String] };
objc_property_attribute_t attrs[] = { a1, a2, a3, a4};
class_addProperty([self class], [propName UTF8String], attrs, 4);
class_addMethod([self class], NSSelectorFromString(propName), (IMP)getter, "@@:");
class_addMethod([self class], NSSelectorFromString([self setterName:propName]), (IMP)setter, "v@:@");
id val = [self.objectProperties objectForKey:key];
[keys setValue:val forKey:propName];
}
return keys;
}
但是当用户想要观察任何属性时,在用户类中是无法访问的。
我很困惑如何创建动态属性和应用 KVO。
我还尝试通过创建 Entry 类的子类,即(用户在其末尾创建的 myEntry)并在那里定义所有变量。但是我如何在那里设置它的值?因为我希望该属性是只读的。