我正在学习Swift编程语言,在此期间我有时会接触旧的Objective-C编程语言及其代码。
我是一个绝对的初学者,因此我有一些问题需要更好地了解Setter和Getter。
所以,我知道我可以通过.h文件中的花括号创建一个实例变量,但通常我会使用属性。这些属性由实例变量支持,并自动提供Getter和Setter方法。
示例:
车辆.h文件:
@interface Vehicle : NSObject
@property int myProperty;
@end
因为我创建了这个属性,所以我不必在vehicle.m文件中声明Getter和Setter方法,因为它们是由编译器自动创建的。所以我可以创建一个车辆对象,设置并获得价值。
示例
的main.m
Vehicle *myvehicle = [[vehicle alloc] init];
[myvehicle myProperty] // myvehicle.myProperty
[myvehicle setMyProperty : 10] // myvehicle.myProperty = 10;
现在我读到可以覆盖我创建的属性" myProperty"的自动创建的Getter和Setter方法。在声明我自己的Getter和Setter版本时,我必须在vehicle.h和vehicle.m文件中声明两个方法。在vehicle.m文件中,我不使用self关键字调用该对象,而是使用它自动创建的实例变量(_myProperty)。是不是?
我尝试过但总是出错,我不知道为什么,有什么意义。
示例
车辆.h文件:
@interface Vehicle : NSObject
@property int myProperty;
-(int) myProperty; //my new Getter method
-(void) setMyProperty: (int)updatedMyProperty; //My new Setter method
@end
vehicle .m文件:
@implementation Vehicle
-(int) myProperty {
if (! _myProperty) {
_myProperty = NO;
}
return _myProperty;
}
-(void) setMyProperty: (int)updatedMyProperty {
if (_myProperty == updatedMyProperty) return;
_myProperty = updatedMyProperty;
}
@end
我总是得到错误"使用未声明的标识符"而且我不知道为什么。如果我理解正确,我不必使用@synthesize声明ivar或其名称,因为编译器会自动为我创建名为_myProperty的ivar。当我想改变ivar的名字时,我只需要使用@synthesize。
我不确定为什么我会被卡住,重点是什么。你能解释一下吗? 提前谢谢!
答案 0 :(得分:2)
如果实现所有访问器方法,编译器将不再自动为您合成ivar。在这种情况下,您必须自己明确地这样做。 E.g。
@synthesize myProperty = _myProperty;
仅在手动实施所有访问者方法时才需要这样做。原因是编译器足够聪明,知道如果你接管访问器方法,你可能不需要ivar,即你可能正在做一些根本不同的事情,例如:从一些其他属性计算值,从某些不同的商店设置/获取值等等。您可能希望编译器合成ivar(在这种情况下,您添加上面的@synthesize
语句),但它同样可能是你'我实现了访问器方法,因为不需要支持ivar(在这种情况下,你省略了上面的@synthesize
语句)。
无论如何,坚持你的简单例子,你会得到类似的东西:
@interface Vehicle : NSObject
@property (nonatomic) int myProperty; // if you don't write atomic accessor methods, you really should be explicit that this is nonatomic
// as an aside, even if you implement accessor methods, you don't have to declare them here
//
// -(int) myProperty; //my new Getter method
// -(void) setMyProperty: (int)updatedMyProperty; //My new Setter method
@end
并且
@implementation Vehicle
// since you implemented all of the accessor properties, you have to manually synthesize the ivar
@synthesize myProperty = _myProperty;
- (int) myProperty {
// do whatever you want here; note, the following doesn't make sense
//
// if (! _myProperty) {
// _myProperty = NO;
// }
return _myProperty;
}
- (void)setMyProperty:(int)updatedMyProperty {
if (_myProperty == updatedMyProperty) return;
_myProperty = updatedMyProperty;
}
@end
显然,在上面的例子中编写这些特定的访问器方法是没有意义的,因为你没有提供任何新的功能,所以你不会。您只需使用自动合成的存取方法。
但是在那些你确实需要编写自己的访问器方法的情况下,你必须明确地告诉编译器你是否需要它来为你合成ivar。
答案 1 :(得分:-1)
如果使用非原子属性,则可以覆盖getter或setter或两者。编译器将负责其余的工作。
@property (nonatomic) int yourInt;
然后在.m文件中写入getter或setter
-(int)yourInt
{
// do something
return _yourInt;
}
-(void)setYourInt:(int)someInt
{
// do something
_yourInt = someInt;
}
注意到这些差异:
_yourInt; //access variable directly
[self yourInt]; // use getter method
_yourInt = 4; // set vsriable directly
[self setYourInt:4]; // use setter method