【问题标题】:Different usage of Objective C Properties (with/without underbar etc)Objective C 属性的不同用法(带/不带下划线等)
【发布时间】:2013-05-24 08:04:21
【问题描述】:

我更喜欢像这样在 Objective-C 中为类使用属性(这在较新的 Xcode 版本中似乎是标准的):

/* MyClass.h */
@interface MyClass : NSObject;
@property (nonatomic, strong) NSArray *myArray;
@end;


/* MyClass.m */
#import MyClass.h

@implementation
@synthesize myArray = _myArray;

- (void)anyMethod {
    self.myArray = // do something
}

@end

但是在网络上的一些 github 存储库中,我发现了使用属性的不同方式,例如:

/* MyClass.h */
@interface MyClass : NSObject {
    NSArray *myArray;
}

// sometimes the @property is used here too

@end;


/* MyClass.m */
#import MyClass.h

@implementation

- (void)anyMethod {
    _myArray = // do something
}

@end

这些方式之间究竟有什么区别?我读到它必须通过访问实例变量来做一些事情。但是为什么有些人在@interface 部分声明变量而不(或有时)使用@property?

【问题讨论】:

    标签: objective-c xcode properties synthesize


    【解决方案1】:

    这里有几个方面需要考虑,其中一些已经提到过。

    首先,下划线只是一个合法字符和名称的一部分。本地 iVar _foo 对应于属性 foo 或多或少只是一个约定。当

    • 您已将它们自动合成。 (没有@synthesize 语句)然后iVar 会自动生成,并带有前导下划线。 (在较新版本的 Objective C 中)
    • 您有意声明 iVar _foo 并扩展 @synthesize 语句,使其在命名为 foo 时引用 _foo。您也可以声明属性 foo 和 ivar bar 并将它们链接到 @synthezise 或自定义 getter 中。这与任何约定相去甚远,因此通常不推荐。 示例:@synthesize foo = _foo;
    • 您提供自定义 getter 和 setter 并访问该属性。同样,您可以将任何 iVar 与属性链接,甚至可以设置其中的一些以响应输入等。 pp。

    属性 foo 对应时的 ivar foo

    • 您使用 @synthezise 而不提供 ivar 的名称。就@synthesize foo; (我认为,取决于 ojective-c 的版本,无论是否使用 ivar foo 的 explizit 声明都可以使用,但我不会用血签名)

    一般来说,我建议坚持使用下划线模式,尽管我自己并不总是这样做。优点是 ivar 和属性之间的分离对程序员来说更明显,这有助于避免错误。特别是同名的本地参数(很常见)不会隐藏 ivar。 以foo 为例:

    foo = @1; //This refers to the iVar foo. 
    self.foo = @1; //This calls the setter. 
    [self setFoo:@1]; //This calls the setter. 
    someVar = [self foo]; // This calls the getter. 
    foo = foo; // This would not work assuming that foo is a local parameter of the method.
    self->foo = foo // This is not good style but a workaround for the line above in that situation. This accesses the ivar directly on the left side of the equation, not its setter.
    self.foo = foo; // This is fine when foo is the local parameter.
    

    与 _foo 相同,只是程序员更清楚:

    _foo = @1; //This refers to the iVar _foo.  
    self.foo = @1; //This calls the setter. 
    [self setFoo:@1]; //This calls the setter. 
    someVar = [self foo]; // This calls the getter. 
    _foo = foo; // This would work nicely assuming that foo is a local parameter of the method.
    self->_foo = foo // No need for doing that. It is rather C style anyway and not that common in Obj-C.
    self.foo = foo; // This, too, is fine when foo is the local parameter. Clearly uses the setter.
    

    【讨论】:

      【解决方案2】:

      “_varName”指的是存储在内存中的实际变量。通过使用“self.varName ...”,您只需使用访问器使用点语法约定“获取”和“设置”变量。所以通过这样做

      self.varName = someValue;
      

      [self setVarName:someValue];
      

      实际上你正在调用一个方法

      - (void)setVarName:(ObjectType *)varName
      

      这只是一个经典的“setter”方法,它负责设置该变量的值。这就像走进一家餐厅并与服务员/女服务员一起点菜,而不是走进厨房并自己动手。

      通常后者不受欢迎,建议您使用访问器方法来设置和获取使用“self...”的值。这是因为访问器方法通常会设置为“验证”是否存储了适当的数据。在获取或设置值时完成其他任务的自定义访问器更是如此。还有其他原因,但“保护”确实是重点。

      当你这样做时

      _varName = someValue; 
      

      不使用setter方法,直接改变量。

      【讨论】:

        【解决方案3】:
        {
         NSArray *myArray;
        }
        

        上面的东西叫做成员变量,它不能在类外访问。(重要点)(除非你提供自定义的getter和setter)

        如果你创建了一个@property,那么变量可以在类内和类外被读取..所以setter和getter会为你生成..自动

        那么就不需要将其声明为成员变量了..

        这样做是为了提高可读性,它也被认为是内存管理策略的重要组成部分。

        当您谈论私有财产时,那么

        A.如果你想要一个完全私有的变量。不要给它一个属性。

        B.如果您想要一个可从类的封装外部访问的只读变量,请使用全局变量和属性的组合:

        【讨论】:

        • 好的,感谢您的解释。当无法从类外部访问成员变量时,私有属性(在 .m 文件的@interface 部分中声明的)究竟是什么意思?
        • 没有办法在 Objetive-C 中真正声明私有属性。
        • 好的。因此,当我有只能从类访问的变量时,我应该使用成员变量。访问它们呢?我可以使用myArray = // do something_myArray 访问它们还是需要编写setter/getter?
        • 你不需要 setter getter
        • 这取决于您所说的“私人”是什么意思。如果您只是指“未公开记录”,您可以轻松地在私有标头或 .m 文件中使用类扩展。如果您的意思是“其他人根本无法调用它”,那您就不走运了。任何人只要知道它的名称就可以调用该方法,即使它没有公开记录。
        猜你喜欢
        • 2013-12-16
        • 1970-01-01
        • 1970-01-01
        • 2013-05-22
        • 2021-09-02
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 2011-09-03
        相关资源
        最近更新 更多