Domanda

Il codice seguente implementa una sottoclasse NSProxy che inoltra metodi per un'istanza NSNumber.

Tuttavia quando si chiama [nsproxy floatValue] ottengo 0.0 sotto GCC 4.2.

Sotto LLVM-Clang ottengo la risposta corretta 42.0.

Qualche idea di cosa sta succedendo?

(dal modo in cui questo è in esecuzione in Garbage Collection)

-(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;
} 
È stato utile?

Soluzione

Il tuo classe proxy non dichiara la firma del messaggio per -floatValue. Dato che restituisce un numero decimale, che può essere un problema. Perché non hai dichiarato da nessuna parte e presumibilmente non sono lanciando l'oggetto proxy per la sua classe rappresentato il compilatore deve indovinare la firma del metodo. In tal caso, il compilatore GCC indovina che il messaggio restituirà un puntatore id.

In Objective-C, a seconda della firma del messaggio e l'architettura della macchina, funzioni diverse abituarsi per l'elaborazione del suo valori di ritorno dei messaggi e. Su macchine x86 messaggi che restituiscono un valore in virgola mobile sono chiamati attraverso objc_msgSend_fpret mentre le funzioni che restituiscono void e l'uso id objc_msgSend.

Poiché il compilatore GCC è supponendo che il valore restituito è un id usa quest'ultima funzione e non correttamente gestisce il risultato. Quel Clang è in grado di gestire correttamente questo è interessante, ma io esiterei a fare affidamento su tale comportamento. Sarebbe meglio per dichiarare una categoria sul proxy per tutti i metodi che sarete inoltro. Che ha anche il vantaggio di rimuovere l'avvertimento che era stato generato per la riga di codice chiamando il metodo floatValue.

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

Altri suggerimenti

Qualsiasi metodo init dovrebbe chiamare [super init]; per evitare un comportamento imprevisto. Come modo:

- (id)init {
    self = [super init];
    if (self) {
        // Your init code
    }
    return self;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top