我想在访问和更改属性时触发一些代码。我在我的代码中使用@property
和@synthesize
作为我的ivars。这些属性被保留,所以我想保留@synthesize
自动生成的内存管理内容。
但是,我假设@synthesize
告诉编译器在@synthesize is
的位置生成访问器方法代码,所以代码顶部的大多数情况都是对的吗?
当我有一个属性foo
时,我会获得-setFoo
和-foo
方法。我是否可以制作这样的方法,在更改属性时执行更多自定义代码?
-(void)setFoo {
// custom stuff
}
现在这是一个问题。如何执行第一个?我不想在这里有一个不同的名字。有没有办法让@synthesize
指令为getter和setter方法创建其他名称,然后我可以轻松调用它们?然后我仍然可以使用点语法来访问它们吗?
答案 0 :(得分:5)
您可以像往常一样使用@property
和@synthesize
,但提供自定义设置器或获取器(或两者),而是使用它们。通常我会做这样的事情:
// Override the setter
- (void)setName:(NSString *)aName
{
if (name == aName)
return;
[name release];
name = [aName retain];
//custom code here
}
当我使用set属性时,它将调用我的自定义方法。但是,get仍将被合成。
答案 1 :(得分:1)
如果您为setter或getter提供实现,它将使用它而不是生成的实现。实现编译器在你合成时为你生成的getter和setter的“保留”方面并不难,所以你可以自己编写你自己的getter和setter,然后继续使用它。
答案 2 :(得分:0)
一个古怪的解决方案是创建一个抽象超类,它可以为您提供正常的属性合成。 然后创建一个你将实际使用的具体子类,它只是实现和覆盖方法(相同的签名)并调用super来进行实际设置。 这使您可以在调用super实现之前或之后执行任何操作。
示例:
@interface ALTOClassA : NSObject
@property NSString *catName;
@end
此测试的存根文件之外的.m中没有其他任何内容。
创建子类,在@interface
中没有特别需要#import "ALTOClassA.h"
@interface ALTOClassAJunior : ALTOClassA
@end
在@implementation中,我们进行覆盖。
#import "ALTOClassAJunior.h"
@implementation ALTOClassAJunior
- (void)setCatName:(NSString*)aCatName {
NSLog(@"%@",NSStringFromSelector(_cmd));
[super setCatName:aCatName];
NSLog(@"after super: self.catName %@", self.catName);
}
@end
使用中:
ALTOClassAJunior *aCAJ = [ALTOClassAJunior new];
NSLog(@"aCAS.catName %@", aCAJ.catName);
NSLog(@"set it to George.");
[aCAJ setCatName:@"George"];
NSLog(@"aCAS.catName %@", aCAJ.catName);
这允许您利用自动生成的代码,并且仍然可以执行您想要对您的类执行的操作。抽象超类通常是许多事物的有用解决方案。
答案 3 :(得分:-2)
是的,在@property声明中,您可以指定getter和setter方法。
@property (readwrite,getter=privateGetFoo,setter=privateSetFoo:) NSObject * foo;
在foo
和setFoo:
方法中,请拨打[self privateGetFoo]
或[self privateSetFoo:f]
,然后调用您的自定义代码。
对象还可以使用addObserver:forKeyPath:options:context:
为自己设置观察者。
那就是说,我不认为其中任何一种都是非常干净的做事方式。最好像其他人建议的那样编写自己的getter / setter。