6

私が使用しようと考えている特定のアプローチに関するフィードバックをいただければ幸いです。シナリオは以下。

x 座標と y 座標、高さ、幅など、多数のプロパティを持つオブジェクト (MObject と呼びましょう) があります。プロパティは、KVC ガイドライン (MObject.x、MObject.height など) に従って名前が付けられます。次のタスクは、この MObject を記述した XML ファイルを読み込むことです。残念ながら、XML 要素の名前は、X と Y、高さと幅 (大文字に注意してください) とは異なります。

XML 要素が MObject のプロパティと一致することが理想的です。この場合、KVC を使用して、コード全体を回避できます。

for (xmlProperty in xmlElement)
{
    [MObject setValue:xmlProperty.value forKey:xmlProperty.name].
}

これにアプローチする 1 つの方法は、大文字と小文字を区別しないキーを使用することです。どこから始めますか?他のより良い解決策はありますか?

提案は大歓迎です。

4

5 に答える 5

3

上書きしないでください-[NSObject valueForKey:]-[NSObject setValue:forKey:]もしあなたがそれを助けることができれば。

最善の策は、XML ファイルから取得したキーをその場で変換することです。別のメソッドを使用して変換を行い、名前のキャッシュをプロパティ キーに保持することもできるため、各変換を 1 回だけ行う必要があります。

- (NSString *)keyForName:(NSString *)name {
    // _nameToKeyCache is an NSMutableDictionary that caches the key
    // generated for a given name so it's only generated once per name
    NSString *key = [_nameToKeyCache objectForKey:name];
    if (key == nil) {
        // ...generate key...
        [_nameToKeyCache setObject:key forKey:name];
    }
    return key;
}

- (void)foo:xmlElement {
    for (xmlProperty in xmlElement) {
        [myObject setValue:xmlProperty.value forKey:[self keyForName:xmlProperty.name]].
    }
}
于 2008-12-03T03:36:21.347 に答える
3

NSString を使用lowercaseStringして、XML キー名を小文字に変換できます。

于 2008-12-03T00:24:43.527 に答える
3

オーバーライド-valueForUndefinedKey:して-setValue:forUndefinedKey:

大文字と小文字が異なるキーが見つかった場合はそれを使用し、それ以外の場合は に電話してsuperください。

于 2008-12-03T03:21:52.673 に答える
1

そこで私は Chris Hanson の提案を実装し、最終的には次のようになりました。これを Utils クラスに入れました。検索する各クラスの辞書を保持します。おそらく少しリファクタリングを使用する可能性がありますが、これまでのところ非常にうまく機能しています。

static NSMutableDictionary *keyCache;

+ (NSString *)keyForClass:(Class)klass column:(NSString *)column {
    if (!keyCache) { keyCache = [NSMutableDictionary dictionary]; }

    NSString *className = NSStringFromClass(klass);

    NSMutableDictionary *tableKeyCache = [keyCache objectForKey:className];

    if (!tableKeyCache) {
        tableKeyCache = [NSMutableDictionary dictionary];

        unsigned int numMethods = 0;
        Method *methods = class_copyMethodList(klass, &numMethods);
        NSMutableArray * selectors = [NSMutableArray array];
        for (int i = 0; i < numMethods; ++i) {
            SEL selector = method_getName(methods[i]);
            [selectors addObject:NSStringFromSelector(selector)];
        }
        [tableKeyCache setValue:selectors forKey:@"allSelectors"];
        free(methods);
        [keyCache setValue:tableKeyCache forKey:className];
    }

    NSString *keyToReturn = [tableKeyCache valueForKey:column];
    if (!keyToReturn) {
        for (NSString *columnKey in [tableKeyCache valueForKey:@"allSelectors"]) {
            if ( [column caseInsensitiveCompare:columnKey] == NSOrderedSame) {
                [tableKeyCache setValue:columnKey forKey:column];
                keyToReturn = columnKey;
                break;
            }
        }
    }

    if (!keyToReturn) { // Taking a guess here...
        NSLog(@"Selector not found for %@: %@ ", className, column);
        keyToReturn = [Utils keyForClass:[klass superclass] column:column];
    }

    return keyToReturn;
}
于 2012-09-14T17:46:48.620 に答える
1

と をオーバーライド-valueForKey:-setValue:forKey:ます。

おそらく、認識できるキー (要素/属性名) のみを受け入れsuper、他のキーを呼び出す必要があります。

于 2008-12-03T01:40:52.860 に答える