2010-11-27 7 views
1

Ich habe diese Art von Situation in Objective-C:DRY Meta-Code in Objective-C

[aCoder encodeObject:self.control forKey:@"control"]; 
[aCoder encodeObject:self.command forKey:@"command"]; 
[aCoder encodeObject:self.channel forKey:@"channel"]; 
[aCoder encodeObject:self.data1 forKey:@"data1"]; 

In Ruby oder Groovy Ich kann dies mit Blöcken und ein klein bisschen um von Messing eine Zeile haben anstatt vier. Ich weiß, Objective-C hat viele dynamische Eigenschaften. Wie kann dieser Code destilliert werden? nur der Name dieser Methode als String

Antwort

5

können Sie verwenden performSelector:withObject:

for (NSString *key in arrayOfKeys) { 
    SEL aSelector = NSSelectorFromString(key); 
    id anObject = [self performSelector:aSelector withObject:nil]; 
    [aCoder encodeObject:anObject forKey:key]; 
} 

Dies ist, wie man mit einer Methode zur Laufzeit dynamisch aufrufen. Das Argument withObject: ist ein einzelnes Objekt, das als einzelnes Argument für eine Methode übergeben wird, wenn es eins benötigt.

Wenn es mehr als ein Argument braucht, oder ein Nicht-Objekt-Argument nimmt, müssen Sie in die weit kompliziertere NSInvocation und es ist Buddy NSMethodSignature. Leider sind sie nicht sehr einfach, aber sie ermöglichen eine beeindruckende Dynamik, auch wenn ihre Verwendung kompliziert und hässlich ist.

+0

genial, genau das, was ich brauchte, danke! Wird das mit Blöcken immer besser/besser? –

+1

Der einzige Block, der hier in einer Sprache wie Ruby verwendet würde, wäre, diesen Code an 'Array # each' weiterzuleiten. Aber da ObjC nativ eine For/Each-Style-Schleife unterstützt, brauchen wir das nicht wirklich. Sie könnten natürlich etwas mit Blöcken und einem Iterator machen, aber es würde nichts lösen und der Selektor und das Aufrufen von self, um den Wert einer Eigenschaft zu erhalten, würde von diesem Beispiel überhaupt nicht geändert werden. Blöcke würden das unnötig erschweren. Es sei denn, du hattest einen wirklich guten Grund. –

+0

@Yar, es ist nicht so schön wie Ruby (auf lange Sicht), aber Sie können enumerateObjectsUsingBlock verwenden: um dies sauberer zu machen. –