【问题标题】:In Objective-C, when should I use property and when should I use instance variable?在 Objective-C 中,什么时候应该使用属性,什么时候应该使用实例变量?
【发布时间】:2012-06-10 03:55:07
【问题描述】:

我不熟悉同时具有属性和实例变量的程序语言。
所以我不知道使用属性和实例变量的好方法。

现在我在我的 Objective-C 代码中只使用属性,不使用任何实例变量。

我需要使用实例变量吗?
还是只使用属性是 Objective-C 的最佳实践?

@interface ViewController : UIViewController
{
    // instance variable
    @public
    int a;
}

// property
@property(nonatomic, strong) NSString *b;

@end

【问题讨论】:

    标签: iphone objective-c ios properties


    【解决方案1】:

    变量和属性的基本区别在于,你可以给属性赋予属性。您不能为变量赋予任何属性。 因此,如果您希望有任何特定行为,例如保留变量、以原子方式访问它、在类之外访问,您应该选择属性。

    如果您只是想访问类中的变量并且没有附加特殊行为到该变量,则无需通过属性访问它。您可以直接使用变量本身。它也会提高性能。

    【讨论】:

      【解决方案2】:

      @property 比 ivar 有一些优势:

      • 内存管理:在幕后,它将创建一个设置器来创建具有正确内存管理的变量。它将为您省去一些麻烦,因为您可以轻松查看内存管理 是如何完成的(strong/weakretain/copy/assign)。

      • 其他类的可访问性:如果您在 .h 中声明 @property 并在 .m 中声明 @synthesize,您的 ivar 将是公共可读和可写的。您可以使用 privat 类扩展来防止这种情况。您甚至可以声明 @property public readonly 并通过 privat 类扩展在内部声明它们 readwrite。 例如:私有财产

         // [In the implementation file]  
         @interface MyClass ()  
         @property (nonatomic, retain) NSMutableArray* someData; // private!!   
         @end  
      
         @implementation MyClass @synthesize someData   
         @end
      
      • 自定义 getter 和 setter:如果您愿意,您仍然可以编写自定义 getter 和 setter,甚至可以只编写一个 getter 或 setter 并让另一个自动 @synthesize。您可以将自定义逻辑写入这样的 getter 和 setter,例如您可以在 @property 更改后重新加载 tableview。

      • 符合自动键值观察 (KVO) 标准:如果您使用或计划使用 KVO,您只需声明属性即可免费获得它。没有其他事情需要做!

      • 点表示法:如果您有 @property,则可以通过点表示法访问 getter 和 setter。

         self.myIvar = (id) someThing; 
         [array addObject:self.myIvar];
      
      • 如果您需要公开 iVar,编写 @property 比为 iVar 编写 getter 和 setter 更简单

      • 使用@property,您无需在 iVar 中声明(在 iOS 和 64 位 Mac Os X 应用程序中)。你可以通过@synthesize

          @synthesize myiVar = _myIvar;
      

      【讨论】:

        【解决方案3】:

        在任何地方使用属性。甚至不要声明实例变量,而是像这样合成它们:@synthesize myProperty = _myProperty 以便将它们与属性名称区分开来。属性也是处理内存管理的好方法。唯一必须使用合成实例变量的地方是 dealloc 方法。
        属性的优点很多:
        - 访问器方法定义了您将如何获取和设置实例变量的值。
        - 您可以自定义访问器方法(例如延迟实例化 ivar 或在设置新值时执行某些操作,例如 setNeedsDisplay
        - 设置新值时您无需处理内存管理 - 设置器负责释放/保留(取决于您如何声明属性 - retain/copy/assign/strong
        - 一些带有atomic/nonatomic 属性的多线程东西
        - 使用属性时,您可以利用KVO
        - 至少,但不是最后 - 如果您担心每次调用 getter 或 setter 时,请不要担心性能问题...

        【讨论】:

        • 我不同意这里。你能告诉我为什么你认为这不是一个好主意吗?
        • 阅读下面的答案。有时您也需要访问 ivars,这不是 cz。
        • @graver 谢谢!我尝试在任何地方都使用属性,并且仅在需要公开时才使用属性。但是当我到处使用属性时,我可以更舒适地编写代码。混合 ivar 和属性对我来说非常混乱。
        • 在被覆盖的 setter 中使用属性可能会导致无限循环。官方文档也不建议在 inits 中使用属性。所以那些不应该在任何地方使用。看看:Access Instance Variables Directly from Initializer Methods
        【解决方案4】:

        @property 是一个实例变量,它应用了一些语义糖,以帮助将其暴露给外部世界(通常),并帮助避免编写样板代码来获取和设置它。

        【讨论】:

          【解决方案5】:

          虽然属性通常是在你需要访问类之外的一些变量时创建的,意思是 getter n setter,但在目标 C 中,额外需要创建属性是内存管理在编译器结束时进行,所以如果你是使用一些对象,而不是原始数据类型,那么你应该使用属性并合成它,如果你使用手动引用计数,然后在 dealloc 中释放。但同样的主要目标是使其属性能够访问类外的一些 iVar,例如将参数从一个类传递到另一个类等。

          【讨论】:

          • though properties are made generally when you need to access some variable outside of the class - 这是制作它们的最不重要的原因。属性用于引入访问和设置实例变量的规则 - 类似于您的 ivar 的代理。将您的 ivar 暴露在您的类之外会发生思想方法(稍后调用 getter/setter),并且属性声明实际上会为您创建这些方法 - 但它们的主要目的和功能不是暴露您的 ivar,而是准确定义您如何获取/设置它。
          • iVar 对自己的类总是可见的,getter setter 的目的是保证 ivar 的隐私,即数据是私有的,显然我们在无权访问时需要调用 getter 或 setter ivar,那是类外而不是类内
          【解决方案6】:

          如果您@synthesize@property,您将可以访问get 和set 方法,非常方便。如果 setter 是非原子的或原子的并且是只读的,您还可以定义 setter 的行为方式(保留、分配、复制)。如果你没有指定任何东西(也就是你没有合成属性),默认情况下 ivar 在类之外是不可见的,但你可以通过使用@public 来实现这一点。从逻辑上讲,您也可以将它们定义为 @private@protected

          通常我 @synthesize@property 因为我想从类外部访问 ivar,还因为我想要一个 getter 和 setter 方法。

          【讨论】:

            【解决方案7】:

            一般意见是,您应该尽可能使用属性。如果您仍有疑问,以下是 Apple 的建议:

            一般来说,您应该使用访问器方法或点语法进行属性访问,即使您是从其自己的实现中访问对象的属性,在这种情况下您应该使用self

            ...

            此规则的例外是在编写初始化、释放或自定义访问器方法时

            ...

            您应该始终直接从初始化方法中访问实例变量,因为在设置属性时,对象的其余部分可能尚未完全初始化

            阅读整个文档here 以更好地理解该主题。

            至于性能问题,对于大多数应用程序来说,收益是微不足道的。阅读this 以获得非常详细的说明。

            【讨论】:

              猜你喜欢
              • 2010-10-18
              • 1970-01-01
              • 2020-06-03
              • 2010-12-30
              • 2023-04-02
              • 2011-04-15
              • 2017-04-10
              • 2012-03-19
              相关资源
              最近更新 更多