2

これがどのように機能するかを説明するために最善を尽くしていますが、かなり紛らわしく、長くなります。明確にするためにできることがあれば教えてください。

私は KVC と KVO の概念に固執しています。
エントリ クラス (NSObject) があります。
Entry Class には、値がサーバーから取得されるプライベート変数 objectProperties (NSDictionary) があります。

objectProperties に「price」、「discount」などのキーがあると仮定すると、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 )を作成し、そこにすべての変数を定義してみました。しかし、その値をそこに設定するにはどうすればよいですか? そのプロパティを読み取り専用にしたいので。

4

1 に答える 1