Je suis en train d'implémenter la méthode countByEnumeratingWithState:objects:count:
du protocole NSFastEnumeration sur une classe personnalisée.
Jusqu'à présent, j'ai réussi à parcourir mes objets correctement, mais les objets retournés ne sont pas des objets Objective-C mais plutôt les équivalents du framework Core Foundation.
Voici la partie du code qui définit state->itemsPtr:
MyCustomCollection.m
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
objects: (id __unsafe_unretained *)buffer
count: (NSUInteger)bufferSize {
// ... ignorer les détails ...
NSLog(@"Objet à l'intérieur de la méthode : %@", someObject);
state->itemsPtr = (__unsafe_unretained id *)(__bridge void *)someObject;
// ... ignorer les détails ...
}
Ensuite, j'appelle la boucle 'for..in' ailleurs comme ceci
SomeOtherClass.m
MyCustomCollection *myCustomCollection = [MyCustomCollection new];
[myCustomCollection addObject:@"foo"];
for (id object in myCustomCollection) {
NSLog(@"Objet dans la boucle : %@", object);
}
La sortie dans la console est la suivante :
Objet à l'intérieur de la méthode : foo
Objet dans la boucle : __NSCFConstantString
Comme vous pouvez le voir, à l'intérieur de la méthode du protocole NSFastEnumeration, l'objet s'affiche correctement, mais dès qu'il est converti en id __unsafe_unretained *
, je perds la classe Objective-C correspondante d'origine.
Pour être honnête, je ne suis pas tout à fait sûr de comment fonctionne la conversion (__unsafe_unretained id *)(__bridge void *)
dans ce cas. Le (__unsafe_unretained id *)
semble convertir pour correspondre au bon type nécessaire pour itemsPtr. Le (__bridge void *)
semble convertir en un pointeur de type void avec __bridge utilisé pour faire le pont entre le monde obj-c et le monde CF. Selon les docs llvm, pour __bridge
:
Il n'y a pas de transfert de propriété et ARC n'insère aucune opération de conservation
Est-ce correct ?
D'après ce que je comprends, __NSCFConstantString est simplement l'équivalent du framework Core Foundation de NSString. Je comprends également qu'avec ARC, vous devez faire le pont entre les objets Objective-C et les équivalents du framework CoreFoundation car ARC ne sait pas comment gérer la mémoire de ces derniers.
Comment puis-je faire en sorte que cela fonctionne pour que les objets dans ma boucle 'for..in' soient du type d'origine ?
Remarquez également que dans ce cas, j'ajoute des NSStrings à ma collection mais en théorie, cela devrait prendre en charge n'importe quel objet.
MISE À JOUR
La réponse de Rob est sur la bonne voie, mais pour tester cette théorie, j'ai changé la boucle for comme ceci :
for (id object in myCustomCollection) {
NSString *stringObject = (NSString *)object;
NSLog(@"Chaîne %@ longueur : %d", stringObject, [stringObject length]);
}
En théorie, cela devrait fonctionner puisque les objets sont équivalents mais cela plante avec cette erreur :
+[__NSCFConstantString length]: unrecognized selector sent to class
Il semble presque que les objets retournés dans la boucle for sont des classes et non des instances. Quelque chose d'autre pourrait être erroné ici... Des idées à ce sujet ?
MISE À JOUR 2 : SOLUTION
C'est aussi simple que cela : (merci à CodaFi)
state->itemsPtr = &someObject;