2009-09-20 5 views
4

Le code suivant implémente une sous-classe NSProxy qui transmet les méthodes à une instance NSNumber. Cependant, lorsque j'appelle [nsproxy floatValue], je reçois 0.0 sous GCC 4.2.-forwardInvocation fonctionne avec Clang - LLVM mais pas avec GCC

Sous LLVM-Clang, j'obtiens la bonne réponse 42.0.

Une idée de ce qui se passe?

(par la façon dont cela est en cours d'exécution dans la collecte des ordures)

-(id) init; 
{ 
    _result = [NSNumber numberWithFloat:42.0]; 
    return self; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 
{ 
    return [[_result class] instanceMethodSignatureForSelector:aSelector]; 
} 

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    [anInvocation setTarget:_result]; 
    [anInvocation invoke]; 
    return; 
} 

Répondre

6

Votre classe proxy ne déclare pas la signature du message pour -floatValue. Comme il renvoie un nombre à virgule flottante, cela peut poser problème. Puisque vous ne l'avez pas déclaré nulle part et que vous ne présumez pas que votre objet proxy est transtypé en sa classe représentée, le compilateur doit deviner la signature de la méthode. Dans ce cas, le compilateur GCC devine que le message renverra un pointeur id.

En Objective-C, selon la signature du message et l'architecture de la machine, différentes fonctions sont utilisées pour traiter le message et ses valeurs de retour. Sur les machines x86, les messages qui retournent une valeur à virgule flottante sont appelés via objc_msgSend_fpret tandis que les fonctions renvoyant void et id utilisent objc_msgSend.

Étant donné que le compilateur GCC suppose que la valeur de retour est id, il utilise la dernière fonction et gère incorrectement le résultat. Que Clang soit capable de gérer ça correctement est intéressant mais j'hésiterais à m'en remettre à ce comportement. Il serait préférable de déclarer une catégorie sur votre proxy pour toutes les méthodes que vous allez transmettre. Cela a également l'avantage de supprimer l'avertissement qui était généré pour la ligne de code appelant la méthode floatValue.

@interface Foo (ProxyMethods) 
- (float)floatValue; 
@end 
+0

Merci pour la réponse clairement expliquée, j'ai pensé que c'était quelque chose à faire avec l'attente d'un retour de pointeur d'id comme apposé pour flotter. Je n'ai vu aucune documentation Apple sur l'écueil potentiel. – rebo

-1

Toute init méthode doit appeler [super init]; pour éviter un comportement inattendu. Ainsi:

- (id)init { 
    self = [super init]; 
    if (self) { 
     // Your init code 
    } 
    return self; 
} 
+0

NSProxy n'a pas de méthode init. – Barjavel

Questions connexes