PageControl示例代码中的警告:将赋值结果用作不带括号的条件

时间:2011-09-29 10:07:12

标签: iphone if-statement warnings conditional-statements assignment-operator

我正在尝试了解UIPageControl的工作方式。所以我从Apple下载了这个示例代码 UIPageControlSampleCode 它运行正常,但在以下代码的if语句中有一个警告(使用赋值的结果作为没有括号的条件):

- (id)initWithPageNumber:(int)page 
{
    if (self = [super initWithNibName:@"MainView" bundle:nil])
    {
        pageNumber = page;
    }
    return self;
}

现在我的问题是:为什么开发人员会这样做?在if语句条件中进行赋值?这是一个错误吗?

2 个答案:

答案 0 :(得分:1)

赋值运算符(=)除执行赋值外,还返回赋值。这样你可以做像

这样的事情
a = b = 1;

编译器与编写

相同
a = (b = 1);

这意味着在做

self = <some init function>;

您可以通过将赋值放在if语句中来检查init是否成功。如果成功则返回一个有效指针,该指针不为零,这意味着if语句的条件为真。如果init失败,则返回nil,实际上为零,因此继续进行剩余的初始化是没有意义的。

警告的原因是很容易在if语句而不是(==)中意外使用(=):

if ( a = 1 ) // Should be a == 1
{
    // Do important stuff
}

所以编译器试图保护你免受这个错误。

出于这个原因,我更喜欢在你的例子中明确表达条件:

if ((self = [super initWithNibName:@"MainView" bundle:nil]) != nil)

答案 1 :(得分:0)

此警告是因为Apple已创建示例代码,因此编译器版本和默认编译器选项已更改。

特别是,这个警告 - 告诉你你可能意味着“==”而不是“=”(因为语句处于“if”条件而你通常测试的是相等而不是分配) - 是相当的逻辑;但是默认情况下,在早期版本的编译器和Xcode 中没有激活警告,这解释了为什么这些代码可能仍然存在于旧的示例代码中(没有人是完美的,甚至Apple开发人员; ))

正确的正常使用/惯例是

  • 要么在“if”条件下显式测试相等性,要对编译器明确,以便确定您的意思:if (nil != (self = [super initWithNibName:@"MainView" bundle:nil]))
  • 或者编译器也接受的符号是加倍括号,提到使用简单赋值而不是“==”的条件不是错误。因此,编写if ((self = [super initWithNibName:@"MainView" bundle:nil]))也会起作用并删除警告。

我建议采用第一种解决方案。 如果你明确地测试了,在赋值之后,赋值的结果(因此self中的值)不是nil,那么当你读取代码时(即使它不是你的代码),你就确定了什么打算。


即使代码以这种方式保存代码(并保持警告),代码仍然有效,此警告可确保您在代码中没有错误输入'='而不是'==',因为这样可能是一个常见的错误(对于新手而且对于可能输入太快的有经验的程序员来说;))所以我认为它现在被激活是一件好事,并且为了清楚地与nil进行比较是一个好的做法清晰度