【问题标题】:Difference between using properties and not for accessing ivars使用属性和不访问 ivars 之间的区别
【发布时间】:2023-03-17 18:01:01
【问题描述】:

使用属性或直接访问 ivars 的具体性能和行为差异。

对于全局变量,使用this有什么区别:

@interface myClass (){

    UIImageView *myView;
}

-(void)loadView{

  [super loadView];
  myView = [[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)];
}

然后这样做:

    @interface myClass (){

    }

    @property (nonatomic, strong) UIImageView *myView; 

@synthesize myView = _myView;

    -(void)loadView{

    [super loadView];
    myView = [[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)];
    }

每种方法都有什么好处? 建议始终使用属性的原因是什么?

【问题讨论】:

标签: iphone objective-c ios


【解决方案1】:

在第一种情况下,您的实例变量(或 ivar)myView 是类私有的,不能被其他类访问。​​

在第二种情况下,您提供了一个属性,允许其他类通过合成访问器访问您的 ivar。声明属性的替代方法是编写自己的访问器方法。 @synthesize 符号可以为您做到这一点。

请参阅declared properties 上的 Apple 文档

【讨论】:

  • 那么唯一的区别就是第二个是公开的??
  • 还有一个小问题(无论如何我都会给出这个答案)在 .m 或 .h 中声明私有变量有什么区别?
  • 从技术上讲,在第二种情况下,ivar 仍然是私有的,但您已经通过该属性提供了公共访问器。现在,可以声明 ivars @public@private(默认)或 @protected(可用于子类) - 但通常不会使用 @public,因为它破坏了封装。
  • 我相信在实现文件中声明的 ivars 对子类不可用。我相信这是唯一的区别。也可以在类扩展中声明属性以创建私有属性。有了 ARC,我就少用了。
【解决方案2】:

总是为每个数据成员创建一个@property,并使用self.name 在整个类实现中访问它。 切勿直接访问您自己的数据成员。

以下是使用属性的一些原因:

  • 属性强制执行访问限制(例如只读)
  • 属性强制执行内存管理策略(保留、分配)
  • 属性(很少)用作线程安全策略(原子)的一部分
  • 属性提供了透明地实现自定义 setter 和 getter 的机会。
  • 使用单一方式访问实例变量可提高代码可读性。

您也可以查看:The Code Commandments: Best Practices for Objective-C Coding

【讨论】:

  • 嘿,我希望你是俄罗斯人,这样我就可以与你分享关于面向对象与低级地址偏移(甚至不是 ivars :))编程的最新 bash-org 报价之一非常非常,我的意思是,非常繁忙的计算。
  • @A-Live google 可以翻译页面(在一定程度上)。您应该发布链接。 :D
  • @Sam 给你 :) ithappens.ru/story/8584 和翻译链接:translate.google.com/…
  • @A-Live 整洁阅读。属性当然不适合每种情况。尽管如此,令人惊讶的是,它在特定情况下产生了如此大的差异。让我想知道如果不使用互斥锁或某些锁定机制(如果正在进行线程/其他操作),是否仍然会出现一些错误。我没有完全遵循用户试图做的事情,但这不是一个坏点有时您需要尽可能优化。
  • (或者如果你继承了 NSManagedObject 的 description 方法)
【解决方案3】:

Synthesize 使您可以根据您是否尝试读取或写入值而自动调用 getter 和 setter 方法。对于 myView 属性:

myView = newView1; // using direct ivar access
myobject.myView = newvew1; // eq [myobject setMyView:newvew1]; where setMyView: is generated for you automatically with respect to assign/retain, the same for reading:
newvew1 = myobject.myView; // newvew1 = [myobject myView:newvew1];

生成的 getter/setter 名称可通过 setter=/getter= 自定义,如果您不需要 setter,请使用只读方式。

没有办法禁止其他类使用合成的getter和setter,ivars默认是@protected,如果你想为其他类提供对ivars的访问,你可以在@public下声明它们:

@interface myClass (){

   UIImageView *myView; // this is protected

   @public
   UIImageView *myPublicView; // this is public    
}

【讨论】:

    【解决方案4】:

    在您的第一个示例中,您直接访问您的 ivar 并更改其内容。在您的第二个示例(属性)中,已自动创建一个 ivar 来支持该属性,并且您设置和获取该属性的所有调用都作为消息发送(例如:[self setMyView:[[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)]];)。访问器方法也是自动创建的。这意味着您现在正在遵循 KVC/KVO 协议。更多关于这种设计的好处see here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2012-10-03
      • 2011-06-22
      • 2012-08-27
      • 2011-02-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多