Objective c 目标C:私有变量与私有属性
对我来说,作为Objective-C开发者的过去很简单。类需要公共的每个字段都是属性,每个私有字段都是实例变量,没有getter或setter。但我经常看到人们在实现文件中使用私有接口来声明私有属性。有人告诉我,这就是现在做事的方式 虽然这样做很好,但我很难看到它的优点。只要我不需要getter或setter中的一些逻辑,我就会继续使用实例变量来处理所有非公共的事情。我必须承认使用了一个属性,然后使用关键字self使代码更具可读性。您可以查看属性是否属于类,或者它是否只是方法中的局部变量,但这不是唯一的原因Objective c 目标C:私有变量与私有属性,objective-c,Objective C,对我来说,作为Objective-C开发者的过去很简单。类需要公共的每个字段都是属性,每个私有字段都是实例变量,没有getter或setter。但我经常看到人们在实现文件中使用私有接口来声明私有属性。有人告诉我,这就是现在做事的方式 虽然这样做很好,但我很难看到它的优点。只要我不需要getter或setter中的一些逻辑,我就会继续使用实例变量来处理所有非公共的事情。我必须承认使用了一个属性,然后使用关键字self使代码更具可读性。您可以查看属性是否属于类,或者它是否只是方法中的局部变量,但这不
为什么或者为什么不使用私有属性?objective-c中的属性不仅仅是实例变量。它们是由实例变量支持的getter和setter方法的组合 通常,当人们在实现文件(私有类扩展名)中添加属性时,会将一个公开的
readonly
属性设置为readwrite
属性,以便设置它并保留所有属性语义,如键值编码。属性还负责为您保留副本
这只是一种将公共接口与实现分开的方法。在IVAR上使用(私有)属性有几个原因
- 正如您所说,使用属性将允许您轻松地使用访问器方法,这些方法除了访问变量之外,还可以执行一些额外的编码
- 不适用于IVAR
- 为实现生成一个公共readonly属性readwrite only,以便在getter之外合成一个setter(正如Brad所指出的)
- 个人偏好、习惯或懒惰(财产为公共财产,但改为私人财产)
NSString
,否则使用属性没有任何好处
此外,您不一定需要使用self
来访问这些属性:当为您自动或使用@synthesis
关键字合成属性时,您会得到一个“支持”属性的变量。指定该变量是访问属性的一种完全合法的方式,例如,当您希望将其表示为只读时
但是,将这些变量私有化是一个优势,即在类扩展中声明它们,如下所示:
@interface MyClass() { // <<== Note the () -- it's a class extension
SomeOtherClass *privateIvar;
}
@interface MyClass(){/非常简单
如果要使用私有属性@属性
,请在.m中添加此属性:
@interface MyViewController ()
@property (nonatomic, strong) NSString *myPrivateStringProperty;
@end
@implementation MyViewController
@end
在这里,该属性只能在.m中访问
如果要使用公共@属性
,请在.h中添加此属性:
@interface MyViewController : UIViewController
@property (nonatomic, strong) NSString *myPublicStringProperty;
@end
在这里,属性可以在您的类之外访问。这只是一个封装问题,您可以拥有许多不同级别的私有性
最初在Objective-C中,运行时不支持在运行时向对象添加实际字段,因此必须在类中列出每个iVar:
@interface MyClass : NSObject
{
//every ivar that MyClass adds to NSObject must be here
}
在一段时间内,这是一个简单且足够好的系统
即使是私有IVAR也必须声明,尽管编译器不允许您在错误的范围内访问它们
@interface MyClass : NSObject
{
@private
id someObj;
}
此可见性说明符限制访问,例如:
//另一类
+ (void)doSomething
{
MyCLass * mc = [MyClass new];
mc->someObj = [SomeOtherClass new]; // error cant access private variable...
}
但是,您可能会使用指针算术实现它,因此要混淆,您将在类中看到如下内容:
@interface MyClass : NSObject
{
@private
void * __reserved1;
void * __private1;
}
这是相当好的混淆
但是等等……一定有更好的办法!
输入非易碎ABI
现在类只需要导出它们的超类和公共接口
@interface MyClass : NSObject
@property (readonly,retain) id someIVar;
其余的类内容可以包含在类扩展中:
@interface MyClass ()
{
id someObj;
}
@property (readwrite,retain) id someIVar;
请注意,这只适用于iPhone和64位OS X 32位OS X仍然是旧的ABI,需要在那里工作的库需要采用旧的方式。良好地使用属性可能更“方便”(至少因为您不必担心在KVO可访问属性的情况下忘记调用willChange/didChange)而且,毫无疑问,使用IVAR而不是属性更快。因此,我建议使用属性,除非你真的关心每秒帧数。看看是否是这样。我的OP询问为什么在接口中放置一些IVAR,在实现中放置一些IVAR。一个次要问题是为什么要使用属性
关键是封装。只在公共接口(.h)文件中放置那些设计用于类外的东西。将那些设计用于实现的东西放置在实现(.m)内任何未公开的内容都可以在以后更改,而不会影响类的用户
属性为关联的ivar提供setter/getter方法。在当前objective-c编译器中,如果没有@synthesis
语句,编译器将自动生成ivar,该ivar的名称与以下划线(\ux)为前缀的属性的名称相同。getter/setter还支持KVO,这可能是一个加号,具体取决于您的使用情况。请注意,可以在接口文件中声明readonly属性,并在实现文件类扩展名中声明readwrite属性
因此,当前的最佳实践是对所有IVAR使用属性,如果属性语句设计为公共的,则将其放在接口文件中;如果属性语句设计为私有的,则将其放在类扩展的实现文件中。这提供了一个干净的接口文件,只公开公共方法和属性。明白了。你可以有一个只读的pu