2010-05-23 18 views
21

Sono un po 'nuovo con l'obiettivo c e sto cercando di passare un argomento per riferimento ma si comporta come se fosse un valore. Sai perché questo non funziona?Passare argomenti per valore o per riferimento nell'obiettivo C

Questa è la funzione:

- (void) checkRedColorText:(UILabel *)labelToChange { 
    NSComparisonResult startLaterThanEnd = [startDate compare:endDate]; 
    if (startLaterThanEnd == NSOrderedDescending){ 
     labelToChange.textColor = [UIColor redColor]; 
    } 
    else{ 
     labelToChange.textColor = [UIColor blackColor]; 
    } 

} 

e questa è la chiamata:

UILabel *startHourLabel; // This is properly initialized in other part of the code 
[self checkRedColorText:startHourLabel]; 

Grazie per il vostro aiuto

+3

Cosa intendi con "comportarsi come se fosse un valore"? –

risposta

68

Objective-C solo supporto che passa i parametri in base al valore. Il problema qui è stato probabilmente già risolto (Poiché questa domanda ha più di un anno di vita), ma ho bisogno di chiarire alcune cose riguardanti gli argomenti e l'Objective-C.

Objective-C è un superset rigido di C che significa che tutto ciò che C fa, Obj-C lo fa anche.

Di avere una rapida occhiata a Wikipedia, è possibile che seeFunction parameters are always passed by value

Objective-C non è diverso. Quello che sta accadendo qui è che ogni volta che passiamo un oggetto a una funzione (in questo caso un UILabel *), passiamo il valore contenuto all'indirizzo del puntatore.

Qualsiasi cosa tu faccia, sarà sempre il valore di ciò che stai passando. Se si desidera passare il valore del riferimento , si dovrebbe passare un oggetto ** (come spesso si vede quando si passa NSError).

Questa è la stessa cosa con gli scalari, vengono passati per valore, quindi è possibile modificare il valore della variabile ricevuta nel metodo e che non modificherà il valore della variabile originale passata alla funzione .

Ecco un esempio per facilitare la comprensione:

- (void)parentFunction { 
    int i = 0; 
    [self modifyValueOfPassedArgument:i]; 
    //i == 0 still! 
} 

- (void)modifyValueOfPassedArgument:(NSInteger)j { 
    //j == 0! but j is a copied variable. It is _NOT_ i 
    j = 23; 
    //j now == 23, but this hasn't changed the value of i. 
} 

Se si voleva essere in grado di modificare i, si dovrà passare il valore della di riferimento effettuando le seguenti operazioni:

- (void)parentFunction { 
    int i = 0; //Stack allocated. Kept it that way for sake of simplicity 
    [self modifyValueOfPassedReference:&i]; 
    //i == 23! 
} 

- (void)modifyValueOfPassedReference:(NSInteger *)j { 
    //j == 0, and this points to i! We can modify i from here. 
    *j = 23; 
    //j now == 23, and i also == 23! 
} 
+27

Tecnicamente, sì, tu passi solo i primitivi per valore. Tuttavia questo è del tutto fuorviante in quanto mentre il puntatore a un oggetto viene passato per valore, quel puntatore punta allo stesso oggetto. Poiché non c'è NESSUNO MODO PER PASSARE (o trattare) OGGETTI, * gli oggetti * vengono sempre passati per riferimento. L'unica volta che si comportano come se non lo fossero è se OP dicesse labelToChange = nil; o qualcosa del genere, ma è qualcosa che tutti sanno non funzionerebbe e non discuterà. –

+2

questo è così fuorviante .... Gli oggetti sono passati per riferimento in obiettivo-c ..per aggiungere più divertimento alla domanda è stato chiesto da oggetto e ha risposto con la spiegazione di int che viene passato per valore. E se questo non è abbastanza divertente hai 60+ voti per "Objective-C supporta solo il passaggio di parametri per valore." – hariszaman

0

in Objective-C, non v'è alcun modo per passare gli oggetti valore (a meno che non lo copi esplicitamente, ma questa è un'altra storia). Fai attenzione al tuo codice: sei sicuro checkRedColorText: si chiama? Che dire di [startDate compare: endDate], non è mai uguale a NSOrderedDescending? LabelToChange è zero?

+0

Nel metodo, NSOrderedDescending a volte è vero come mi aspettavo. L'etichetta non è nulla. In realtà, se cablassi labelToChange per startHourLabel funziona ... Mi sembra che si stia comportando come se passassi l'etichetta come valore e non come riferimento: S .. Non capisco .. Grazie per il tuo aiuto ! – Rafael

+1

Cosa intendi con "wired labelToChange per startHourLabel"? Non è possibile collegare un argomento di metodo a qualsiasi cosa eccetto passandolo come parametro. – JeremyP

+0

Voglio dire cablando per non usare labelToChange e usare direttamente la variabile startHourLabel (solo per il debug di puroposes). StartHourLabel è globale e potrebbe essere raggiunto nel metodo. Ma voglio usare lo stesso metodo per altre etichette nella vista. Ecco perché ho aggiunto il parametro labelToChange. Grazie! – Rafael

0

Ti è modificare il codice tra questa linea

UILabel *startHourLabel; 

e questa linea?

[self checkRedColorText:startHourLabel]; 

In caso contrario, il problema è che si sta ri-dichiarando la variabile startHourLabel, in modo che stai perdendo qualsiasi tipo di inizializzazione che c'era in precedenza. Dovresti ricevere un errore del compilatore qui.

+0

Presumibilmente era a scopo illustrativo, perché se non altro, ci sarebbe (probabilmente) un EXE_BAD_ACCESS se hai fatto qualcosa con una variabile locale non inizializzata. –

+0

Ciao, grazie. No startHourLabel non è presente, l'inizializzazione è un'altra parte del codice. L'ho dichiarato nell'interfaccia e ne ho fatto un costruttore. Non ho errori lì ... – Rafael

0

Qui ci sono le possibilità di cui questo non funziona:

  1. l'etichetta si passa a checkRedColorText non è quello che si pensa che sia.
  2. il risultato del confronto viene sempre visualizzato allo stesso modo.
  3. ... in realtà, non v'è alcuna 3.

Lei sostiene che si inizializzato startHourLabel altrove, ma, se si tratta di un'etichetta da un file pennino, non si dovrebbe essere l'inizializzazione a tutti. Dovrebbe essere dichiarato come IBOutlet e collegato all'etichetta nel pennino con il generatore di interfacce.

Se non è un'etichetta nel pennino vale a dire che si sta deliberatamente creando a livello di codice, è necessario controllare l'indirizzo della etichetta inizializzare e controllare l'indirizzo dell'etichetta passata a checkRedColorText. NSLog il suo indirizzo all'inizializzazione e in checkRedColorText o ispezionarlo con il debugger.

11

Objective-C, come Java, ha solo il pass-by-value. Come Java, gli oggetti sono sempre accessibili tramite puntatori. "oggetti" non sono mai valori direttamente, quindi non si assegna o passa mai un oggetto. Stai passando un puntatore all'oggetto per valore. Ma questo non sembra essere il problema - stai provando a modificare l'oggetto puntato dal puntatore, che è perfettamente permesso e non ha nulla a che fare con il pass-by-value rispetto al pass-by-reference. Non vedo alcun problema con il tuo codice.

Problemi correlati