Передача аргументов по значению или по ссылке в цель C - PullRequest
22 голосов
/ 23 мая 2010

Я новичок с целью 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];

Спасибо за вашу помощь

Ответы [ 5 ]

71 голосов
/ 07 октября 2011

Objective-C только поддерживает передачу параметров по значению. Проблема здесь, вероятно, уже исправлена ​​(так как этому вопросу больше года), но мне нужно уточнить некоторые моменты, касающиеся аргументов и Objective-C.

Objective-C является строгим надмножеством C, что означает, что все, что делает C, Obj-C делает также.

Быстрый просмотр Википедии, вы можете увидеть что Function 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.
}

Если вы хотите изменить i, вам нужно будет передать значение reference , выполнив следующее:

- (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!
}
11 голосов
/ 08 октября 2011

Objective-C, как и Java, имеет только передачу по значению. Как и в Java, объекты всегда доступны через указатели. «объекты» никогда не являются значениями напрямую, поэтому вы никогда не назначаете или не передаете объект. Вы передаете указатель объекта по значению. Но, похоже, это не проблема - вы пытаетесь изменить объект, на который указывает указатель, что совершенно допустимо и не имеет ничего общего с передачей по значению или передачей по ссылке. Я не вижу проблем с вашим кодом.

0 голосов
/ 23 мая 2010

Вы редактировали код между этой строкой

UILabel *startHourLabel;

и этой строкой?

[self checkRedColorText:startHourLabel];

Если нет, проблема заключается в том, что вы повторно объявляете свой startHourLabelпеременная, так что вы теряете любой вид инициализации, который был там ранее.Вы должны получить ошибку компилятора здесь.

0 голосов
/ 24 мая 2010

Вот возможные причины, почему это не работает:

  1. метка, которую вы передаете checkRedColorText, не та, которую вы думаете.
  2. результат сравнениявсегда получается одинаково.
  3. ... на самом деле, нет 3.

Вы утверждаете, что инициализировали startHourLabel в другом месте, но, если это метка из файла пераВы не должны его инициализировать вообще.Он должен быть объявлен как IBOutlet и подключен к метке в кончике с помощью построителя интерфейса.

Если это не метка в кончике, т.е. вы намеренно создаете ее программно, вам необходимо проверить адресВы инициализируете метку и проверьте адрес метки, переданной в checkRedColorText.Либо NSLog его адрес при инициализации и в checkRedColorText или проверить его с помощью отладчика.

0 голосов
/ 23 мая 2010

В target-c нет способа передать объекты по значению (если вы явно не скопируете их, но это уже другая история). Обойдите свой код - вы уверены, что checkRedColorText: вызывается? Как насчет [startDate сравнить: endDate], он никогда не равен NSOrderedDescending? Является ли labelToChange nil?

...