Подтвердить что ты не робот

Передача аргументов по значению или по ссылке в объекте 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];

Спасибо за помощь

4b9b3361

Ответ 1

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, вам нужно будет передать значение ссылки, выполнив следующие действия:

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

Ответ 2

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

Ответ 3

В objective-c невозможно передать объекты по значению (если вы явно не скопировали его, а вот еще один рассказ). Выказываете свой код - вы уверены, что вызывается checkRedColorText:? Что относительно [startDate compare: endDate], он никогда не равен NSOderedDescending? Является ли labelToChange nil?

Ответ 4

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

UILabel *startHourLabel;

и эта строка?

[self checkRedColorText:startHourLabel];

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

Ответ 5

Вот, почему это не работает:

  • ярлык, который вы передаете в checkRedColorText, не тот, который вы считаете.
  • результат сравнения всегда выходит аналогичным образом.
  • ... на самом деле, нет 3.

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

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