Сбой создания NSString внутри if-case?

#objective-c

#objective-c

Вопрос:

Я просто пытаюсь решить, с каким текстом я буду работать простым if-способом. Почему X-code жалуется и не позволяет мне создать проект, говоря, что переменная не определена, когда она четко определена в if?

  if(indexPath.row == [listOfItems count]) {
            NSString *cellValue = [[NSString alloc] initWithFormat:@"Totalt: %@st registrerade", companyTotalReg]; //cellValue is unused
        } else {
            NSString *cellValue = [[NSString alloc] initWithFormat:@"Totalt: SEK%@ intjänat", companyTotalPay]; //cellValue is unused
        }
        cell.textLabel.text = cellValue; //cellValue is undefined
  

Комментарии:

1. en.wikipedia.org/wiki/Scope_(programming)

Ответ №1:

Вам нужно сделать это таким образом:

 NSString *cellValue = nil;
if(indexPath.row == [listOfItems count]) {
    cellValue = [[NSString alloc] initWithFormat:@"Totalt: %@st registrerade", companyTotalReg]; //cellValue is unused
} else {
    cellValue = [[NSString alloc] initWithFormat:@"Totalt: SEK%@ intjänat", companyTotalPay]; //cellValue is unused
}
cell.textLabel.text = cellValue; //cellValue is not undefined anymore
  

В противном случае теоретически может случиться так, что оба ваших предложения if завершатся неудачей (хотя в вашем случае это невозможно) и cellValue останутся необъявленными.
Поскольку компилятор не может знать, теоретически возможно ли, чтобы все ваши условия завершились неудачей, поэтому он просто предупредит вас в любом случае.

В общем случае вы должны всегда инициализировать переменные в пределах области, в которой они собираются использоваться. В вашем случае cellValue это было бы вне области для cell.textLabel.text = cellValue; .

Немного не по теме, но вы также должны использовать NSLocalizedString() для любой строки пользовательского интерфейса вместо жестко закодированных.

Комментарии:

1. Спасибо вам большое, Regexident! 🙂

Ответ №2:

  NSString *cellValue = NULL; 

if(indexPath.row == [listOfItems count]) {
    cellValue = [[NSString alloc] initWithFormat:@"Totalt: %@st registrerade", companyTotalReg]; //cellValue is unused
} else {
    cellValue = [[NSString alloc] initWithFormat:@"Totalt: SEK%@ intjänat", companyTotalPay]; //cellValue is unused
}
cell.textLabel.text = [cellValue autorelease]; // The autorelease is here because you are leaking the memory otherwise. If you release the string later anyway, you can and should remove it!
  

Комментарии:

1. Традиционно литералом нулевого указателя для объектов Objective-C является nil , оставляя NULL для стандартных указателей C (или указателей на указатели).

Ответ №3:

То, как вы это сделали, определяет две NSStrings, которые имеют имена cellValue . Время жизни первого cellValue ограничено областью действия if предложения, а время жизни второго cellValue ограничено областью действия else предложения. Вы могли бы решить это двумя способами:

 NSString *cellValue;
if (indexPath.row == [listOfItems count])
    cellValue = [[NSString alloc] initWithFormat:@"Totalt: %@st registrerade", companyTotalReg];
else
    cellValue = [[NSString alloc] initWithFormat:@"Totalt: SEK%@ intjänat", companyTotalPay]; 
cell.textLabel.text = cellValue;
  

или

 NSString *cellValue = (indexPath.row == [listOfItems count])
    ? [[NSString alloc] initWithFormat:@"Totalt: %@st registrerade", companyTotalReg]
    : [[NSString alloc] initWithFormat:@"Totalt: SEK%@ intjänat", companyTotalPay];
cell.textLabel.text = cellValue;
  

Комментарии:

1. Просто уточнение: время жизни имен ограничено. Сами объекты продолжают существовать, и фактически происходит утечка.

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