简单地说,有没有办法在Objective-C类中的任何属性发生变化时收到一般通知?我知道我可以使用KVO监视特定的属性更改,但只要有任何setProperty:
消息发送到我的类,我就需要调用特定的方法。我希望能够收到通用通知,而不必担心特别修改哪个属性。
如果有助于澄清我为什么要这样做,我会使用一些快速表格滚动代码:http://blog.atebits.com/2008/12/fast-scrolling-in-tweetie-with-uitableview/
完成此任务的部分过程是,只要修改了表视图单元格中的属性,就需要调用[ self setNeedsDisplay ]
。我宁愿不必为我的班级中的每个属性覆盖setter方法,只是为了进行这个调用。
答案 0 :(得分:6)
正如Chuck所说,你可以创建一个从属密钥,当然你可以直接观察所有属性(这比重载setter的工作少。)
使用Objective-C运行时,如果您专门使用属性,则可以使用class_copyPropertyList()
自动执行此过程。但是,如果这个问题对你来说有点问题,我可能只会这样做。如果你只有这个问题的一个实例,那么直接观察属性列表可能更容易,更安全,更易于维护,除非你想在ObjC运行时工作。
答案 1 :(得分:4)
这是一个基于Chuck和Rob的建议的例子:
DrakeObject.h
@interface DrakeObject : NSObject
@property (nonatomic, strong) NSNumber *age;
@property (nonatomic, strong) NSNumber *money;
@property (nonatomic, strong) NSString *startPosition;
@property (nonatomic, strong) NSString *currentPosition;
@property (nonatomic, strong, readonly) id propertiesChanged;
@end
DrakeObject.m
@implementation DrakeObject
- (instancetype)init {
self = [super init];
if (self) {
self.age = @25;
self.money = @25000000;
self.startPosition = @"bottom";
self.currentPosition = @"here";
}
return self;
}
- (id)propertiesChanged {
return nil;
}
+(NSSet *)keyPathsForValuesAffectingPropertiesChanged {
return [NSSet setWithObjects:@"age", @"money", @"startPosition", @"currentPosition", nil];
}
观察propertiesChanged会在财产发生变化时随时通知我们。
[self.drakeObject addObserver:self
forKeyPath:@"propertiesChanged"
options:NSKeyValueObservingOptionNew
context:nil];
答案 2 :(得分:2)
不完全是。您可以创建一个dependent key,它取决于您希望公开的每个属性,然后观察它。我认为那就差不多了。
答案 3 :(得分:0)
这是一个代码示例。我有一个普通的对象和dother对象。 Dother对象必须在改变每个属性时保存他的状态。
#import <Foundation/Foundation.h>
@interface GeneralObject : NSObject
+ (instancetype)instanceWithDictionary:(NSDictionary *)aDictionary;
- (instancetype)initWithDictionary:(NSDictionary *)aDictionary;
- (NSDictionary *)dictionaryValue;
- (NSArray *)allPropertyNames;
@end
实施
#import "GeneralObject.h"
#import <objc/runtime.h>
@implementation GeneralObject
#pragma mark - Public
+ (instancetype)instanceWithDictionary:(NSDictionary *)aDictionary {
return [[self alloc] initWithDictionary:aDictionary];
}
- (instancetype)initWithDictionary:(NSDictionary *)aDictionary {
aDictionary = [aDictionary clean];
for (NSString* propName in [self allPropertyNames]) {
[self setValue:aDictionary[propName] forKey:propName];
}
return self;
}
- (NSDictionary *)dictionaryValue {
NSMutableDictionary *result = [NSMutableDictionary dictionary];
NSArray *propertyNames = [self allPropertyNames];
id object;
for (NSString *key in propertyNames) {
object = [self valueForKey:key];
if (object) {
[result setObject:object forKey:key];
}
}
return result;
}
- (NSArray *)allPropertyNames {
unsigned count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
NSMutableArray *array = [NSMutableArray array];
unsigned i;
for (i = 0; i < count; i++) {
objc_property_t property = properties[i];
NSString *name = [NSString stringWithUTF8String:property_getName(property)];
[array addObject:name];
}
free(properties);
return array;
}
@end
毕竟我们有课,这应该可以保存他的状态任何属性的每次更改
#import "GeneralObject.h"
extern NSString *const kUserDefaultsUserKey;
@interface DotherObject : GeneralObject
@property (strong, nonatomic) NSString *firstName;
@property (strong, nonatomic) NSString *lastName;
@property (strong, nonatomic) NSString *email;
@end
和实施
#import "DotherObject.h"
NSString *const kUserDefaultsUserKey = @"CurrentUserKey";
@implementation DotherObject
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
if (self = [super initWithDictionary:dictionary]) {
for (NSString *key in [self allPropertyNames]) {
[self addObserver:self forKeyPath:key options:NSKeyValueObservingOptionNew context:nil];
}
}
return self;
}
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context {
NSDictionary *dict = [self dictionaryValue];
[[NSUserDefaults standardUserDefaults] setObject:dict forKey:kUserDefaultsUserKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (NSString *)description {
return [NSString stringWithFormat:@"%@; dict:\n%@", [super description], [self dictionaryValue]];
}
@end
快乐的编码!