是否可以观察(订阅)存储在NSMutableDictionary中不同键下的值的更改?在我的例子中,键在订阅启动时就已经存在了,但是值发生了变化,在这种情况下我希望得到通知。我希望在通知中显示更改后的值的关键字。
我假设,如果我的字典键都是NSString实例,我可以单独订阅每个键路径。但是如果我的密钥是非字符串的呢?在这种情况下我是不是不走运?
发布于 2009-07-09 23:13:39
这是一个有趣的想法。我在NSDictionary或NSDictionaryController中找不到任何看起来有希望的东西。我的第一反应是使用围绕NSMutableDictionary的组合,并拦截对setObject:forKey:(可能还有-removeObjectForKey:)的调用,以通知订阅者更改。
有一个关于NSMutableDictionary子类化的Cocoa With Love post,如果你选择走这条路,它可能会很有用。我还有created my own NSMutableDictionary subclasses,欢迎您使用开放源码。
您可以设计一个观察者协议,该协议可以指定应该监视的特定密钥。不应该有太多的代码,但我现在有更多的时间去做。
发布于 2020-06-04 15:05:12
尽管我使用NSMutableDictionary有不同的原因,也有不同的方式(我不会对其进行子类化),但我找到了另一种方法。
我使用NSMutableDictionary,因为它可以很好地序列化和反序列化JSON。为了获取和设置值,我使用了"wrappers“。这些对象使用字典作为“原始”实体,并提供getter和setter来访问值。然后,我的getter和setter实现只定义了键(和对象类型)。
还有一个基类,它提供了我将这些字典传递到(或从中获取)的属性。
@protocol PMBase <NSObject>
@property (nonatomic, strong, nullable) NSMutableDictionary<NSString*, id>* entity;
@end
@interface MBase : NSObject<PMBase>
@property (nonatomic, strong, nullable) NSMutableDictionary<NSString*, id>* entity;
@end
inline static NSString* _Nullable mbase_get_string(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSString* _Nullable const fallback) {
id const val = [obj.entity objectForKey:key];
return [val isKindOfClass:NSString.class] ? val : fallback;
}
inline static void mbase_set_string(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSString* _Nullable const value) {
if (value) {
[obj.entity setObject:value forKey:key];
} else {
[obj.entity removeObjectForKey:key];
}
}
inline static NSNumber* _Nullable mbase_get_number(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSNumber* _Nullable const fallback) {
id const val = [obj.entity objectForKey:key];
return [val isKindOfClass:NSNumber.class] ? val : fallback;
}
inline static void mbase_set_number(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSNumber* _Nullable const value) {
if (value) {
[obj.entity setObject:value forKey:key];
} else {
[obj.entity removeObjectForKey:key];
}
}
(MBase implementation is no magic, so no code here.)
在子类中,我简单地定义了额外的属性,其中我覆盖了getter和setter。子类很大程度上实现了访问器,有时,它们会返回其他MBase
子类的实例。
@protocol PMDevice <NSObject>
// Not important here
@end
@interface MDevice : MBase <PMDevice>
@property (nonatomic, strong, nonnull) NSString* deviceName;
@property (nonatomic, assign) MDeviceType deviceType; // phone, tablet...
@end
@implementation MDevice
- (void)setDeviceName:(NSString*)name {
mbase_set_string(self, @"name", name);
}
- (NSString*)deviceName {
return mbase_get_string(self, @"name", NSLocalizedString(@"Unnamed", @"unnamed device placeholder"));
}
- (void)setDeviceType:(MDeviceType)deviceType {
mbase_set_number(self, @"type", [NSNumber numberWithInt:(int)deviceType]);
}
- (MDeviceType)deviceType {
return (MDeviceType)mbase_get_number(self, @"type", [NSNumber numberWithInt:MDeviceTypeOther]).intValue;
}
@end
现在我需要关键字,包装器用来访问特定的字典值。我只是将"last used key“作为属性添加到我的MBase中,并将该行添加到getter和setter内联中:
@protocol PMBase <NSObject>
@property (nonatomic, strong, nullable) NSString* lastUsedKey;
@property (nonatomic, strong, nullable) NSMutableDictionary<NSString*, id>* entity;
@end
@interface MBase : NSObject<PMBase>
@property (nonatomic, strong, nullable) NSString* lastUsedKey;
@property (nonatomic, strong, nullable) NSMutableDictionary<NSString*, id>* entity;
@end
inline static NSString* _Nullable mbase_get_string(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSString* _Nullable const fallback) {
obj.lastUsedKey = key;
id const val = [obj.entity objectForKey:key];
return [val isKindOfClass:NSString.class] ? val : fallback;
}
inline static void mbase_set_string(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSString* _Nullable const value) {
obj.lastUsedKey = key;
if (value) {
[obj.entity setObject:value forKey:key];
} else {
[obj.entity removeObjectForKey:key];
}
}
inline static NSNumber* _Nullable mbase_get_number(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSNumber* _Nullable const fallback) {
obj.lastUsedKey = key;
id const val = [obj.entity objectForKey:key];
return [val isKindOfClass:NSNumber.class] ? val : fallback;
}
inline static void mbase_set_number(id<PMBase> _Nonnull const obj,
NSString* _Nonnull const key,
NSNumber* _Nullable const value) {
obj.lastUsedKey = key;
if (value) {
[obj.entity setObject:value forKey:key];
} else {
[obj.entity removeObjectForKey:key];
}
}
现在,每当我需要有关键的信息时(如果我遇到这样做的原因,键可能会发生变化),我将访问一个值获取方法,然后访问lastUsedKey
属性。
https://stackoverflow.com/questions/1106862
复制相似问题