6

简而言之,有没有办法在 Objective-C 类中的任何属性发生更改时接收一般通知?setProperty:我知道我可以使用 KVO 来监视特定的属性更改,但是每当有任何消息发送到我的班级时,我都需要调用特定的方法。我希望能够接收通用通知,而不用担心特别修改了哪个属性。

如果有助于澄清我为什么要这样做,我正在使用这里找到的一些快速表格滚动代码:http: //blog.atebits.com/2008/12/fast-scrolling-in-tweetie-with-uitableview /

实现这一点的部分过程是,每当修改表视图单元格中的属性时,都[ self setNeedsDisplay ]需要调用。我宁愿不必为了进行此调用而重写类中每个属性的 setter 方法。

4

4 回答 4

6

正如 Chuck 所说,您可以创建一个依赖键,或者您当然可以直接观察所有属性(这比重载 setter 工作量少)。

使用 Objective-C 运行时,如果您专门使用属性,您可以使用class_copyPropertyList(). 但是,如果您遇到这个问题,我可能只会这样做。如果您只有这个问题的一个实例,那么直接观察属性列表可能更容易、更安全、更易于维护,除非您喜欢在 ObjC 运行时中工作。

于 2009-12-15T21:32:13.507 回答
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];
于 2015-01-16T17:26:13.447 回答
2

不完全是。您可以创建一个依赖键,该键依赖于您希望公开的每个属性,然后观察它。我想这差不多是你能得到的。

于 2009-12-15T21:19:42.503 回答
0

这里是代码示例。我有一个通用对象和一个多特对象。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

毕竟我们有dother类,它应该在每次更改任何属性时保存他的状态

#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

快乐编码!

于 2016-10-07T22:32:00.583 回答