работает только если я использую промежуточную переменную

Я пытаюсь установить текст UILabel равным имени дня недели, представленного в NSDateComponents. Я использую следующий код:

NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease];
dateComponents.weekday = 1; //Sunday
NSString * const weekdayNames[8] = {@"Array starts at 1", @"Sunday", @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday"};

UILabel *myLabel = [[[UILabel alloc] init] autorelease];
myLabel.text = weekdayNames[dateComponents.weekday]; //compiler error: Assignment of read-only variable 'prop.49'

Я могу заставить код работать любым из трех способов:

  1. Сделайте так, чтобы имена дней недели не были константами
  2. Назначьте dateComponents.weekday промежуточной переменной типа int, прежде чем использовать ее в качестве индекса массива
  3. Назначьте день недели [dateComponents.weekday] промежуточной переменной NSString * перед вызовом setText:

Но я хочу знать, почему мой исходный код не работает.


person AlcubierreDrive    schedule 16.09.2010    source источник
comment
Что еще странно, так это то, что устарело. [myLabel setText: weekdayNames [dateComponents.weekday]; Это хорошо...   -  person toxaq    schedule 16.09.2010
comment
Вы говорите, что используете. вызывать аксессор устарел? Я вижу это повсюду, и это недавняя особенность. Что устарело?   -  person AlcubierreDrive    schedule 16.09.2010
comment
Я думаю, что "устаревшее" было ошибкой копирования и вставки. Для меня нет смысла читать ответ. Просто подчеркивал, что работает [myLabel setText: ...], который должен быть таким же, как myLabel.text. Хорошо, когда я прошлой ночью играл с вашим примером.   -  person toxaq    schedule 20.09.2010


Ответы (1)


Вы неправильно инициализируете NSDateComponents, поэтому будний день не возвращает ожидаемое значение. См. документацию .

Теперь вы должны инициализировать его, используя текущую дату:

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
int weekday = [weekdayComponents weekday];

Позднее редактирование: Инициализация является частью проблемы, чтобы исправить изменение ошибки компилятора:

NSString * const weekdayNames[8] =

to

NSString const * weekdayNames[8] =

(указатель на константу NSString).

Однако, когда вы это сделаете, вы получите предупреждение «передача аргумента 1 из 'setText:' отбрасывает квалификаторы из целевого типа указателя», потому что вы передаете постоянный указатель на функцию, которая ожидает указатель. Чтобы исправить предупреждение, вы можете привести аргумент setText к (NSString *).

Вероятно, имеет смысл вообще удалить квалификатор const. NSStrings уже неизменяемы в Objective-C, поэтому они уже являются константами.

person diciu    schedule 16.09.2010
comment
Кажется, проблема не в этом. Я пробовал ваш способ инициализации NSDateComponents, и, как и раньше, setText: работает только с промежуточной переменной или с неконстантными именами дней недели. Кроме того, сама документация, на которую вы ссылаетесь, инициализирует NSDateComponents * comps так же, как и я, в их самом первом примере кода (внизу страницы 5 в PDF). - person AlcubierreDrive; 16.09.2010
comment
Вы правы, если указатель не является константным, код компилируется. Но, если вы знаете, я все еще хочу понять, почему он не работает с константным указателем. Просто прочитав код Obj-C, я думаю, что мой исходный пример был совершенно законным. Компилятор каким-то образом изменяет указатель weekdayNames при выполнении арифметических операций с указателем, а затем изменяет weekdayNames обратно на исходное значение? Если так, то это похоже на незаконную оптимизацию со стороны компилятора ... - person AlcubierreDrive; 21.09.2010
comment
Clang отлично компилирует код. Когда я запускаю gcc с -fdump-tree-original, он показывает, что пытается назначить внутри const weekdayNames. Замена myLabel.text на [myLabel setText:] устраняет проблему - это может быть ошибка GCC. - person diciu; 21.09.2010
comment
Спасибо за ваш последний комментарий! Этот комментарий отвечает на мой вопрос, поэтому я принимаю ваш ответ. - person AlcubierreDrive; 22.09.2010