Предупреждение в примере кода PageControl
Я пытаюсь понять, как работает UIPageControl. Итак, я скачал этот пример кода из Apple UIPageControlSampleCode. Он работает нормально, но есть предупреждение (Использование результата присваивания в качестве условия без скобок) в операторе if в следующем коде:
- (id)initWithPageNumber:(int)page
{
if (self = [super initWithNibName:@"MainView" bundle:nil])
{
pageNumber = page;
}
return self;
}
Теперь мой вопрос: зачем разработчику делать что-то подобное? сделать присваивание внутри условия if-Statement? Это ошибка?
2 ответа
Оператор присваивания (=), кроме выполнения присваивания, также возвращает присвоенное значение. Это так, что вы можете делать такие вещи, как
a = b = 1;
Который для компилятора такой же, как написание
a = (b = 1);
Это означает, что при выполнении
self = <some init function>;
Вы можете проверить успешность инициализации, поместив присваивание в оператор if. Если это удалось, он возвращает действительный указатель, который не равен нулю, что означает, что условие оператора if является истинным. Если инициализация завершается неудачно, она возвращает ноль, который фактически равен нулю, поэтому нет смысла продолжать оставшуюся инициализацию.
Причина предупреждения заключается в том, что легко использовать (=) в операторе if вместо (==):
if ( a = 1 ) // Should be a == 1
{
// Do important stuff
}
Поэтому компилятор пытается защитить вас от этой ошибки.
По этой причине я предпочитаю сделать условие явным, в вашем примере:
if ((self = [super initWithNibName:@"MainView" bundle:nil]) != nil)
Это предупреждение вызвано тем, что поскольку образец кода был создан Apple, версия компилятора и параметры компилятора по умолчанию изменились.
В частности, это предупреждение - которое говорит вам, что вы можете иметь в виду "==" вместо "=" (потому что оператор находится в условии "если" и вы обычно проверяете равенство вместо присваивания) - вполне логично; но предупреждение не было активировано по умолчанию в предыдущих версиях компилятора и XCode, что объясняет, почему такой код все еще может присутствовать в старых образцах кода (никто не идеален, даже разработчики Apple;)).
Правильное нормальное использование / соглашение тогда:
- Либо для явного тестирования на равенство в условии "если", либо для явного указания компилятору, чтобы он был уверен в том, что вы имеете в виду:
if (nil != (self = [super initWithNibName:@"MainView" bundle:nil]))
- Или запись, которая также принимается компилятором, заключается в удвоении скобок, чтобы упомянуть, что создание условия с простым присваиванием, а не "==", не является ошибкой. Таким образом, написание
if ((self = [super initWithNibName:@"MainView" bundle:nil]))
тоже сработает и уберет предупреждение.
Я бы предложил принять первое решение. Если вы явно проверите, что после присвоения, результат присваивания (таким образом, значение в self
) не ноль, то когда вы читаете код (даже если он не ваш), вы уверены в том, что предполагалось.
Даже если код будет работать, если вы сохраните код таким образом (и сохраните предупреждение), это предупреждение гарантирует, что вы не набрали в коде "=" вместо "==", так как это может быть распространенной ошибкой (для новичков, но также и для опытных программистов, которые, возможно, печатали слишком быстро;)) поэтому я считаю хорошей вещью, что теперь она активирована, и хорошей практикой является явное сравнение с нулем для ясности