对我而言,Objective-C开发人员过去很简单。一个类需要公开的每个字段都是一个属性,每个私有字段都是没有getter或setter的实例变量。但更常见的是,人们在实现文件中使用私有接口来声明私有属性。我被告知这是现在做事的方式。
虽然这很好但我很难看到它的优点。只要我在getter或setter中不需要一些逻辑,我就会继续使用实例变量来处理所有不公开的事情。我必须承认使用属性然后使用关键字self使代码更具可读性。您可以查看属性是属于该类,还是属于方法中的局部变量,但这不是唯一的原因。
为何或为何不使用私人物业?
答案 0 :(得分:7)
与ivars相比,使用(私有)属性有几个原因。
答案 1 :(得分:1)
首先,如果您不需要私有属性,请不要使用属性:除非您希望以声明方式从编译器中获取某些特定行为,例如强制NSString
复制赋值,否则没有任何好处使用属性。
此外,您不一定需要使用self
来访问这些属性:当您自动或使用@synthesize
关键字为您合成属性时,您会获得一个“支持”该变量的变量属性。分配该变量是访问该属性的完全合法方式,例如,当您想要将其显示为只读时。
然而,将这些变量设为私有是一个优点,即在类扩展中声明它们,如下所示:
@interface MyClass() { // <<== Note the () -- it's a class extension
SomeOtherClass *privateIvar;
}
如果在类扩展中声明一个变量(在.m文件中而不是标题中),您将能够隐藏"SomeOtherClass"
的标题,这在开发单个应用程序时不太重要,但是当你开始使用自己的类库进行开发时,它会变得非常有用。
答案 2 :(得分:1)
IMO OP正在问为什么在界面中放入一些ivars,在实现中放置一些。另一个问题是为什么属性。
重点是封装。只将那些东西放在公共接口(.h)文件中,这些文件应该由类外的设计使用。将那些按设计的方法仅用于实现(.m)文件中的实现。这是任何未公开的内容都可以在以后更改,而不会影响该类用户。
属性为关联的ivars提供setter / getter方法。在当前的objective-c编译器中,如果没有@synthesize
语句,编译器将自动生成与前缀为下划线(_)的属性同名的ivar。 getter / setter也支持KVO,根据您的使用情况,这可能是一个加号。注意,可以在接口文件中声明一个属性readonly,并在实现文件类扩展中读取。
因此,目前的最佳做法是对所有ivars使用属性,如果属性设计为公共属性,则将属性语句放在接口文件中,如果设计为私有,则将属性语句放在类扩展的实现文件中。这提供了一个干净的接口文件,只公开公共方法和属性。
答案 3 :(得分:0)
属性不是只是实例变量。它们是由实例变量支持的getter和setter方法的组合。
通常当人们在实现文件(私有类扩展)中添加属性时,将公共readonly
属性设置为readwrite
属性,以便他们可以设置它并保留所有属性语义,如key-价值编码。属性还会为您处理复制保留。
它只是一种将公共接口与实现分开的方法。
答案 4 :(得分:0)
这只是一个封装问题,你可以拥有许多不同程度的私密性......
最初在Objective-C中,运行时不支持在运行时向Object添加实际字段,因此每个iVar都必须在类中列出:
@interface MyClass : NSObject
{
//every ivar that MyClass adds to NSObject must be here
}
这是一个简单而且足够好的系统......
甚至必须声明私有iVars,尽管编译器不允许您在错误的范围内访问它们。
@interface MyClass : NSObject
{
@private
id someObj;
}
此可见性说明符限制访问,如:
// someotherclass.m
+ (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,需要在那里工作的库需要采用旧方法。
答案 5 :(得分:0)
使用属性可能更“方便”(至少因为您不必担心在KVO-able属性的情况下忘记调用willChange / didChange),毫无疑问,使用ivars而不是属性会更快。所以我建议使用属性,除非你真的关心每秒的帧数。如果是这种情况,请查看this awesome post。
答案 6 :(得分:-1)
这很简单。
如果您想使用私有 @property
,请在.m中添加此属性:
@interface MyViewController ()
@property (nonatomic, strong) NSString *myPrivateStringProperty;
@end
@implementation MyViewController
@end
此处,只能在.m。
中访问该媒体资源如果您想使用公开 @property
,请在.h中添加此属性:
@interface MyViewController : UIViewController
@property (nonatomic, strong) NSString *myPublicStringProperty;
@end
此处,您可以在课堂外访问该媒体资源。