2010-11-27 20 views
1

J'ai ce genre de situation en Objective-C:méta code DRY en 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"]; 

Dans Ruby ou Groovy je pouvais le faire avec des blocs et un tout petit peu de déconner d'avoir une ligne plutôt que quatre. Je sais que Objective-C a beaucoup de caractéristiques dynamiques. Comment ce code peut-il être distillé?

Répondre

5

Vous pouvez utiliser performSelector:withObject:

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

Voici comment vous appelez dynamiquement une méthode à l'exécution avec seulement le nom de cette méthode comme une chaîne. L'argument withObject: est un seul objet transmis comme argument unique pour une méthode, s'il en prend un.

Si cela prend plus d'un argument, ou prend un argument non-objet, vous devez regarder dans le NSInvocation beaucoup plus compliqué et c'est copain NSMethodSignature. Malheureusement, ils ne sont pas très simples mais ils vous permettent d'atteindre un dynamisme impressionnant, même si leur utilisation est compliquée et laide.

+0

génial, juste ce dont j'avais besoin, merci! Est-ce que cela devient plus serré/meilleur avec des blocs? –

+1

Le seul bloc qui serait utilisé ici dans un langage comme ruby, serait de passer dans ce code à 'Array # each'. Mais comme ObjC supporte nativement une boucle de style for/each, nous n'avons pas vraiment besoin de faire cela. Vous pourriez, bien sûr, faire quelque chose avec des blocs et un itérateur, mais cela ne résoudrait rien et obtenir le sélecteur et l'appeler sur 'self' pour obtenir la valeur d'une propriété ne serait pas du tout changé de cet exemple. Les blocs compliqueraient inutilement cela. Sauf si vous aviez une bonne raison. –

+0

@Yar, ce n'est pas aussi joli que ruby ​​(d'un tir long), mais vous pouvez utiliser enumerateObjectsUsingBlock: pour le rendre plus propre. –