代码之家  ›  专栏  ›  技术社区  ›  Atma

cocoa objective-c类中变量前面的下划线是如何工作的?

  •  156
  • Atma  · 技术社区  · 16 年前

    我在一些iPhone示例中看到,属性在变量前面使用了下划线。有人知道这是什么意思吗?或者它是如何工作的?

    我正在使用的接口文件如下所示:

    @interface MissionCell : UITableViewCell {
        Mission *_mission;
        UILabel *_missionName;
    }
    
    @property (nonatomic, retain) UILabel *missionName;
    
    - (Mission *)mission;
    

    我不确定上面所说的到底是什么,但当我尝试将任务名称设置为:

    aMission.missionName = missionName;
    

    我得到一个错误:

    在非结构或联盟中请求成员“missionName”

    9 回复  |  直到 8 年前
        1
  •  99
  •   Kelan    16 年前

    如果对ivar使用下划线前缀(这只不过是一种常见的约定,但很有用),那么需要做一件额外的事情,以便自动生成的访问器(用于属性)知道要使用哪个ivar。具体来说,在您的实现文件中 synthesize 应该是这样的:

    @synthesize missionName = _missionName;
    

    @synthesize propertyName = _ivarName;
    
        2
  •  18
  •   Marc Charbonneau    16 年前

        3
  •  9
  •   Peter DeWeese    12 年前

    我看到的唯一有用的目的是区分局部变量和成员变量,如上所述,但这不是必要的约定。当与@property配对时,它会增加synthesis语句的冗长性 @synthesize missionName = _missionName;

    不要使用下划线,只需在不冲突的方法中使用描述性变量名即可。当他们必须冲突时, 方法中的变量名应带有下划线,而不是多个方法可能使用的成员变量

    -(void)setMyString:(NSString*)_myString
    {
        myString = _myString;
    }
    

    编辑: 使用最新的自动合成编译器功能,我现在对ivar使用下划线(在极少数情况下,我需要使用ivar来匹配自动合成的功能)。

        4
  •  5
  •   smorgan    16 年前

    它实际上没有任何意义,它只是一些人用来区分成员变量和局部变量的约定。

    至于错误,听起来aMission的类型是错误的。它的声明是什么?

        5
  •  2
  •   Dave Newton    11 年前

    这仅适用于属性的命名约定。

    当您在.m文件中合成变量时,Xcode将自动为您提供变量智能。

        6
  •  1
  •   Jason Fuerstenberg    13 年前

    使用下划线不仅可以解决IVAR问题,而无需使用 自我成员

    例子:

    - (void) displayImage: (UIImage *) image {
    
        if (image != nil) {
            // Display the passed image...
            [_imageView setImage: image];
        } else {
            // fall back on the default image...
            [_imageView setImage: _image];
        }
    }
    
        7
  •  1
  •   RayInNoIL    12 年前

    这似乎是有关self.variableName与_variableName的问题的“主”项。让我大吃一惊的是,在.h中,我有:

    ...
    @interface myClass : parentClass {
    className *variableName;    // Note lack of _
    }
    
    @property (strong, nonatomic) className  *variableName;
    ...
    

    这导致self.variableName和_variableName是.m中两个不同的变量。我需要的是:

    ...
    @interface myClass : parentClass {
    className *_variableName;    // Note presence of _
    }
    
    @property (strong, nonatomic) className  *variableName;
    ...
    

    然后,在类“.m”中,self.variableName和_variableName是等价的。

    我仍然不清楚的是,为什么许多例子仍然有效,即使很难做到这一点。

    射线

        8
  •  0
  •   SARATH SASI    10 年前

    您可以使用self.variable name代替下划线,也可以合成变量以使用不带下划线的变量或出口。

        9
  •  0
  •   pkamb santoshIOS    9 年前

    其他答案中缺少的是使用 _variable variable 以及访问ivar而不是(预期的)财产。

    编译器将强制您使用 self.variable . 使用下划线使键入变得不可能 ,这减少了程序员错误。

    - (void)fooMethod {
    
        // ERROR - "Use of undeclared identifier 'foo', did you mean '_foo'?"
        foo = @1;
    
        // So instead you must specifically choose to use the property or the ivar:
    
        // Property
        self.foo = @1;
    
        // Ivar
        _foo = @1;
    
    }