2010-05-23 72 views
21

我是一種新的目標c,我試圖通過引用傳遞參數,但表現得像是一個值。你知道爲什麼這不起作用嗎?按值或按引用在目標中傳遞參數C

這是函數:

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

} 

這是召喚:

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

感謝您的幫助

+3

你的意思是「表現得像是一種價值」? – 2010-05-23 16:49:05

回答

68

Objective-C only支持按值傳遞參數。這裏的問題可能已經被解決了(因爲這個問題已經有一年多了),但是我需要澄清一些關於參數和Objective-C的問題。

Objective-C是一個嚴格的超集的C這意味着一切C做,Obj C也做到了。

由於具有快速看一下維基百科,你可以seeFunction parameters are always passed by value

的Objective-C是沒有什麼不同。這裏發生的事情是,只要我們將一個對象傳遞給一個函數(在這種情況下是一個UILabel *),我們將包含的值傳遞到指針的地址。

無論你做什麼,它永遠是你所傳遞的價值。如果你想通過參考的值,你將不得不將它傳遞給一個**對象(就像在通過NSError時經常看到的那樣)。

這與標量是一樣的,它們通過值傳遞,因此您可以修改您在方法中收到的變量的值,並且不會更改您傳遞給函數的原始變量的值。

下面就來緩解理解的例子:

- (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. 
} 

如果你希望能夠改變我,你就必須做傳遞參考的值以下內容:

- (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

從技術上講,是的,你只能通過價值傳遞原語。然而,這完全是誤導,因爲指向一個對象的指針是通過值傳遞的,該指針指向同一個對象。由於沒有其他方法可以通過(或處理)對象,因此*對象*總是以引用形式傳遞。如果OP說labelToChange = nil,他們表現的唯一時間就好像他們不是。或類似的東西,但這是每個人在這裏知道不會工作,不討論。 – 2011-10-22 16:49:13

+2

這是如此的誤導......對象在objective-c中通過引用傳遞。爲它增加更多樂趣問題被對象詢問並回答了通過值傳遞的int的解釋。如果這還不夠好玩,你有60+票「Objective-C只支持按值傳遞參數」。 – hariszaman 2017-06-30 09:38:50

0

在Objective-C,沒有辦法通過傳遞對象價值(除非你明確地複製它,但那是另一回事)。戳你的代碼 - 你確定checkRedColorText:被調用嗎? [startDate compare:endDate]怎麼樣,它是否不等於NSOrderedDescending?是labelToChange零?

+0

在該方法中,NSOrderedDescending有時如我所料。該標籤不是零。其實,如果我將labelToChange連接到startHourLabel,它就可以工作......在我看來,如果我將標籤作爲值傳遞,而不是作爲參考傳遞:S ..我不明白..感謝您的幫助! – Rafael 2010-05-24 07:25:12

+1

你的意思是「有線labelToChange startHourLabel」?除了將參數作爲參數傳遞外,您不能將方法參數連接到任何東西。 – JeremyP 2010-05-24 09:49:31

+0

我的意思是通過接線不使用labelToChange並直接使用startHourLabel變量(僅用於調試puroposes)。 startHourLabel是全局的,可以在方法中使用。但是我想在視圖中爲其他標籤使用相同的方法。這就是我添加labelToChange參數的原因。謝謝! – Rafael 2010-05-24 17:48:05

0

你編輯了這行代碼

UILabel *startHourLabel; 

與這條線之間?

[self checkRedColorText:startHourLabel]; 

如果沒有,問題是,你重新聲明你startHourLabel變量,所以你失去任何形式的初始化,這是以前存在。你應該在這裏得到一個編譯器錯誤。

+0

大概是出於說明的目的,因爲如果沒有其他的話,如果你對未初始化的局部變量做任何事情,將會(可能)是EXE_BAD_ACCESS。 – 2010-05-23 16:50:18

+0

你好,謝謝。不,startHourLabel不在那裏,初始化是代碼的其他部分。我在界面中聲明瞭它,並且爲它構造了一個構造函數。我在那裏沒有錯誤... – Rafael 2010-05-24 07:24:55

0

下面是爲什麼這不起作用的可能性:

  1. 你傳遞給checkRedColorText標籤是不是你認爲它是一個。
  2. 比較結果總是以相同的方式出現。
  3. ...其實,沒有3

你要求你初始化startHourLabel其他地方,但是,如果是從筆尖文件標籤,你不應該在所有的初始化它。它應該被聲明爲IBOutlet並通過界面構建​​器連接到筆尖的標籤。

如果它不是nib中的標籤,即您正在故意以編程方式創建它,則需要檢查您初始化的標籤的地址,並檢查傳遞給checkRedColorText的標籤的地址。 NSLog在初始化和checkRedColorText中記錄它的地址,或者用調試器檢查它。

11

Objective-C與Java一樣,只具有傳遞值。像Java一樣,對象總是通過指針來訪問。 「對象」從來都不是直接的值,因此你永遠不會分配或傳遞一個對象。您正在通過值傳遞一個對象指針。但是這似乎並不是問題所在 - 您正在嘗試修改指針所指向的對象,這是完全允許的,並且與傳遞值與傳遞引用無關。我沒有看到你的代碼有任何問題。