Objective-c中的“实例变量”和“属性”之间是否存在差异?
我对此并不十分肯定。我认为“属性”是一个具有存取方法的实例变量,但我可能认为错了。
答案 0 :(得分:81)
属性是一个更抽象的概念。实例变量实际上只是一个存储槽,就像结构中的槽。通常,其他对象永远不应该直接访问它们。另一方面,属性是您可以访问的对象的属性(听起来很模糊,应该是这样)。通常,属性将返回或设置实例变量,但它可以使用多个数据或根本不使用数据。例如:
@interface Person : NSObject {
NSString *name;
}
@property(copy) NSString *name;
@property(copy) NSString *firstName;
@property(copy) NSString *lastName;
@end
@implementation Person
@synthesize name;
- (NSString *)firstName {
[[name componentsSeparatedByString:@" "] objectAtIndex:0];
}
- (NSString *)lastName {
[[name componentsSeparatedByString:@" "] lastObject];
}
- (NSString *)setFirstName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:@" "];
NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
self.name = [newNameArray componentsJoinedByString:@" "];
}
- (NSString *)setLastName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:@" "];
NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
self.name = [newNameArray componentsJoinedByString:@" "];
}
@end
(注意:上面的代码是错误的,因为它假定名称已经存在并且至少有两个组件(例如“比尔盖茨”而不仅仅是“盖茨”)。我觉得修复这些假设会使实际点代码不太清楚,所以我只是在这里指出,所以没有人无辜地重复那些错误。)
答案 1 :(得分:31)
属性是一种为某些值实现getter / setter的友好方式,具有其他有用的功能和语法。属性可以由实例变量支持,但您也可以定义getter / setter以执行更具动态性的操作,例如您可以在字符串上定义lowerCase属性,该属性动态创建结果而不是返回某个成员变量的值。
以下是一个例子:
// === In your .h ===
@interface MyObject {
NSString *propertyName;
}
// ...
@property (nonatomic, retain) NSString *propertyName;
// === In your .m @implementation ===
@synthesize propertyName /* = otherVarName */;
@property
行定义了propertyName
类型NSString *
的属性。可以使用以下语法来获取/设置:
myObject.propertyName = @"Hello World!";
NSLog("Value: %@", myObject.propertyName);
当您分配或读取myObject.propertyName
时,您实际上是在对象上调用setter / getter方法。
@synthesize
行告诉编译器为您生成这些getter / setter,使用具有相同属性名称的成员变量来存储值(如果使用语法,则为otherVarName
注释)。
与@synthesize
一起,你仍然可以通过定义自己的getter / setter来覆盖其中一个。这些方法的命名约定对于setter而言是setPropertyName:
,对于getter而言是propertyName
(或getPropertyName
,而不是标准)。另一个仍将为您生成。
在@property
行中,您可以在属性的parens中定义许多属性,这些属性可以自动执行线程安全和内存管理等操作。默认情况下,属性是原子的,这意味着编译器将使用适当的锁包装@synthesiz
ed get / set调用以防止并发问题。您可以指定nonatomic
属性来禁用此功能(例如,在iPhone上,您希望将大多数属性默认为nonatomic
)。
有3个属性值可以控制任何@synthesized
setter的内存管理。第一个是retain
,它会自动将release
发送到属性的旧值,并retain
发送给新值。这非常有用。
第二个是copy
,它将复制传入的任何值,而不是保留它们。优良作法是将copy
用于NSString,因为调用者可以传入NSMutableString并将其从您的下方更改。 copy
将创建只有您有权访问的输入的新副本。
第三个是assign
,它在没有调用旧对象或新对象的保留/释放的情况下进行直指针分配。
最后,您还可以使用readonly
属性禁用该属性的setter。
答案 2 :(得分:6)
我使用接口部分的属性 - 对象与其他对象接口 实例变量是你在课堂上需要的东西 - 除了你之外,没有人应该看到并操纵它们。
答案 3 :(得分:3)
默认情况下,readwrite属性将由实例变量支持,该实例变量将再次由编译器自动合成。
实例变量是一个存在的变量,它保存对象生命周期的值。用于实例变量的内存在首次创建对象时(通过alloc)分配,并在释放对象时释放。
除非另行指定,否则合成的实例变量与属性具有相同的名称,但带有下划线前缀。例如,对于名为firstName的属性,合成的实例变量将被称为_firstName。
答案 4 :(得分:1)
以前人们公开使用属性而ivars用于私人使用,但几年前,您还可以在@implementation
中定义属性以私下使用它们。但是我仍然会尽可能使用ivars,因为输入的字母较少,而且根据this article它运行得更快。这是有道理的,因为属性意味着“沉重”:它们应该从生成的getter / setter或手动编写的那些访问。
然而,在Apple最近的代码中,不再使用ivars了。我想因为它更像objc
而不是C/C++
,而且使用assign
,nullable
等属性更容易。
答案 5 :(得分:0)
Objective-C 属性与实例变量 (iVar)
实例变量
Property
财产
Instance variable
property = variable + bounded getter/setter
在内部使用 @property
。 getter
。它是一个具有可变语法和访问权限的方法调用
setter
生成 backing ivar
和 _<var_name>
方法(访问器方法),它们使用 _someVariable
(又名支持字段),您可以通过下划线 method dispatch
(KVO
) 使用。
由于它调用了一个方法 - 使用了 @synthesize
机制,这就是为什么可以应用 #import "SomeClass.h"
@interface SomeClass()
@property (nonatomic, strong) NSString *someVariable;
@end
@implementation SomeClass
- (void) foo {
//property getter method
NSString *a1 = self.someVariable; //NSString *a1 = [self someVariable];
//property setter method
self.someVariable = @"set someVariable"; //[self setSomeVariable:@"set someVariable"];
//iVar read
NSString *a2 = _someVariable;
//iVar write
_someVariable = @"set iVar";
}
//if you overriding someVariable getter and setter the iVar(_someVariable) is not generated, that is why you can:
//1. create some variable explicitly
NSString *_someVariable;
//or
//2. use @synthesize
@synthesize someVariable = _someVariable;
//overriding
- (NSString*) someVariable {
return _someVariable;
}
- (void)setSomeVariable: (NSString*) updatedSomeVariable {
_someVariable = updatedSomeVariable;
}
@end
[About]
当您覆盖不生成支持 iVar 的访问器方法时,这就是为什么您可以显式声明一个新属性或使用 {{1}}[About] 生成一个新属性或与现有的链接
{{1}}