Ok, les gars, le premier projet de ce livre est fait, et j'ai une marge de manoeuvre jusqu'à ce que le démarrage des chapitres de retour de l'examinateur tech et éditeur de copie. Généralement, j'utilise ce temps pour rattraper le sommeil et de l'emploi maison et passer du temps avec les enfants, mais j'ai aussi travaillé sur une idée je l'ai mentionné plus tôt sur la création d'une voie à NSObjects automatiquement eux persistent dans un SQLite base de données. Je viens de terminer mon premier projet de code pour faire cela, et une fois j'ai fait quelques tests plus approfondies, je vais faire un blog sur elle.
Aujourd'hui, je vais poster un des pièges peu m'a mordu pendant l'écriture de ce code, et qui est vraiment, vraiment difficile à comprendre de la documentation d'Apple: comment ajouter dynamiquement une class méthode à l'exécution. Ce que j'ai fait dans mes classes de persistance était de créer des méthodes de classe pour vous aider à récupérer des objets. Donc, si vous voulez retrouver tous les objets dans la base de données où les name la propriété égalé "John", vous pourriez faire cela
Quiconque a travaillé avec la mise en œuvre de Ruby ActiveRecord excellente reconnaîtra ce modèle que celui utilisé là-bas. La façon d'appliquer cet consiste à surcharger resolveClassMethod: (vous pouvez utiliser resolveInstanceMethod: faire la même chose pour les méthodes d'instance, mais qui est bien documenté et facile à mettre en œuvre je ne vais pas en discuter ici).
Le resolveClassMethod: documentation vous renvoie à resolveInstanceMethod: pour une mise en œuvre par exemple, qui se présente comme suit:
Si vous utilisez du code comme ça dans votre resolveClassMethod: Cependant, vous obtiendrez une erreur inconnue sélection à l'exécution. Pourquoi? Parce que le code ajoute une méthode à l'objet de classe, ce qui signifie que vous avez ajouté une méthode d'instance de cette classe. Ce n'est pas ce que vous voulez. Qu'est-ce que vous voulez est d'ajouter une méthode de «instance de métaclasse objet, ce qui signifie aller à l'exécution pour obtenir l'objet Class qui représente la classe» de votre classe d'objets métaclasse (dire que cinq fois rapide!). Ainsi, l'exemple ci-dessus, quand transformé en un remplacement de méthode de classe, ressemblerait à ceci:
Et, dans les mots immortels de Bugs Bunny: Viola! Vous avez ajouté une méthode de classe à votre classe à l'exécution. Bien sûr, vous devez créer la fonction de dynamicMethodIMP pour que cela fonctionne et de faire toutes les autres étapes nécessaires pour faire un assortiment dynamique des méthodes de travail, mais ce n'est pas un tutorial sur la création de méthode dynamique, juste une solution à un gotcha vous pouvez rencontre tout en le faisant.
Aujourd'hui, je vais poster un des pièges peu m'a mordu pendant l'écriture de ce code, et qui est vraiment, vraiment difficile à comprendre de la documentation d'Apple: comment ajouter dynamiquement une class méthode à l'exécution. Ce que j'ai fait dans mes classes de persistance était de créer des méthodes de classe pour vous aider à récupérer des objets. Donc, si vous voulez retrouver tous les objets dans la base de données où les name la propriété égalé "John", vous pourriez faire cela
NSArray *johns = [Person findByName:@"John"];
Quiconque a travaillé avec la mise en œuvre de Ruby ActiveRecord excellente reconnaîtra ce modèle que celui utilisé là-bas. La façon d'appliquer cet consiste à surcharger resolveClassMethod: (vous pouvez utiliser resolveInstanceMethod: faire la même chose pour les méthodes d'instance, mais qui est bien documenté et facile à mettre en œuvre je ne vais pas en discuter ici).
Le resolveClassMethod: documentation vous renvoie à resolveInstanceMethod: pour une mise en œuvre par exemple, qui se présente comme suit:
+ (BOOL) resolveInstanceMethod:(SEL)aSEL
{
if (aSEL == @selector(resolveThisMethodDynamically))
{
class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:aSel];
}
Si vous utilisez du code comme ça dans votre resolveClassMethod: Cependant, vous obtiendrez une erreur inconnue sélection à l'exécution. Pourquoi? Parce que le code ajoute une méthode à l'objet de classe, ce qui signifie que vous avez ajouté une méthode d'instance de cette classe. Ce n'est pas ce que vous voulez. Qu'est-ce que vous voulez est d'ajouter une méthode de «instance de métaclasse objet, ce qui signifie aller à l'exécution pour obtenir l'objet Class qui représente la classe» de votre classe d'objets métaclasse (dire que cinq fois rapide!). Ainsi, l'exemple ci-dessus, quand transformé en un remplacement de méthode de classe, ressemblerait à ceci:
+ (BOOL) resolveClassMethod:(SEL)aSEL
{
if (aSEL == @selector(resolveThisMethodDynamically))
{
Class selfMetaClass = objc_getMetaClass([[self className] UTF8String]);
class_addMethod([selfMetaClass, aSEL, (IMP) dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveClassMethod aSEL];
}
Et, dans les mots immortels de Bugs Bunny: Viola! Vous avez ajouté une méthode de classe à votre classe à l'exécution. Bien sûr, vous devez créer la fonction de dynamicMethodIMP pour que cela fonctionne et de faire toutes les autres étapes nécessaires pour faire un assortiment dynamique des méthodes de travail, mais ce n'est pas un tutorial sur la création de méthode dynamique, juste une solution à un gotcha vous pouvez rencontre tout en le faisant.
Aucun commentaire:
Enregistrer un commentaire