我已经开始在Objective-C中在运行时快速创建动态类,并且遇到了一个我似乎无法解决的问题。经过大量的搜索,我仍然感到困惑。
这里的问题是:
[runtimeClassInstance setValue:age forKey:@"age"];
调用实例化的对象:
id runtimeClassInstance = [[NSClassFromString(@"Employee") alloc] init];
由
创建[NewClassMaker buildClassFromDictionary:@[@"FirstName", @"LastName",\
@"Age", @"Salary"]
withName:@"Employee"];
这与 NSUnknownKeyException有关:这个类与密钥年龄错误不符合键值编码。
如果我使用以下调用方法,事情就可以了:
SEL setAgeSelector = NSSelectorFromString(@"setAge");
NSInvocation *call = [NSInvocation invocationWithMethodSignature:[[NSClassFromString(@"Employee") class] instanceMethodSignatureForSelector:setAgeSelector]];
call.target = runtimeClassInstance;
call.selector = setAgeSelector;
NSNumber *age = @(25);
[call setArgument:&age atIndex:2];
[call invoke];
现在创建类的静态方法是这样的:
+(NSDictionary*)buildClassFromDictionary:(NSArray*)propNames withName:(NSString*)className
{
NSMutableDictionary* keys = [[NSMutableDictionary alloc]init];
Class newClass = NSClassFromString(className);
if(newClass == nil)
{
newClass = objc_allocateClassPair([NSObject class], [className UTF8String], 0);
// For each property name, add a new iVar, getter, and setter method for it.
for(NSString* key in propNames)
{
NSString* propName = [self propName: key];
NSString* iVarName = [self ivarName:propName];
class_addIvar(newClass, [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(newClass, [propName UTF8String], attrs, 4);
class_addMethod(newClass, NSSelectorFromString(propName), (IMP)getter, "@@:");
class_addMethod(newClass, NSSelectorFromString([self setterName:propName]), (IMP)setter, "v@:@");
[keys setValue:key forKey:propName];
}
Class metaClass = object_getClass(newClass);
// This method is returning NO on purpose to find out why there is no key.
class_addMethod(metaClass, @selector(accessInstanceVariablesDirectly), (IMP)accessInstanceVariablesDirectly, "B@:");
// Auxilliary methods added to the new class instance so the accessor dynamic methods above can work.
// Not sure if the initial impl of this class maker class worked.
class_addMethod(newClass, @selector(ivarName:), (IMP)ivarNameForString, "@@:@");
class_addMethod(newClass, @selector(propName:), (IMP)propNameForString, "@@:@");
class_addMethod(newClass, @selector(propNameFromSetterName:), (IMP)propNameFromSetterNameString, "@@:@");
// Add a customized description dynamic method to this class. It will dump out any list of properties added
// to the object during init here.
Method description = class_getInstanceMethod([NSObject class],
@selector(description));
const char *types = method_getTypeEncoding(description);
// now add
class_addMethod(newClass, @selector(description), (IMP)Description, types);
objc_registerClassPair(newClass);
}
return keys;
}
我在这里有三种可能性:
答案 0 :(得分:0)
setter方法名为setAge
。 setValue:forKey:
使用冒号搜索setAge:
。在setter方法名称的末尾添加冒号。在Objective-C中,冒号是方法名称的一部分。