首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >观察NSMutableDictionary的变化

观察NSMutableDictionary的变化
EN

Stack Overflow用户
提问于 2009-07-09 22:54:28
回答 2查看 7.8K关注 0票数 19

是否可以观察(订阅)存储在NSMutableDictionary中不同键下的值的更改?在我的例子中,键在订阅启动时就已经存在了,但是值发生了变化,在这种情况下我希望得到通知。我希望在通知中显示更改后的值的关键字。

我假设,如果我的字典键都是NSString实例,我可以单独订阅每个键路径。但是如果我的密钥是非字符串的呢?在这种情况下我是不是不走运?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-07-09 23:13:39

这是一个有趣的想法。我在NSDictionary或NSDictionaryController中找不到任何看起来有希望的东西。我的第一反应是使用围绕NSMutableDictionary的组合,并拦截对setObject:forKey:(可能还有-removeObjectForKey:)的调用,以通知订阅者更改。

有一个关于NSMutableDictionary子类化的Cocoa With Love post,如果你选择走这条路,它可能会很有用。我还有created my own NSMutableDictionary subclasses,欢迎您使用开放源码。

您可以设计一个观察者协议,该协议可以指定应该监视的特定密钥。不应该有太多的代码,但我现在有更多的时间去做。

票数 7
EN

Stack Overflow用户

发布于 2020-06-04 15:05:12

尽管我使用NSMutableDictionary有不同的原因,也有不同的方式(我不会对其进行子类化),但我找到了另一种方法。

我使用NSMutableDictionary,因为它可以很好地序列化和反序列化JSON。为了获取和设置值,我使用了"wrappers“。这些对象使用字典作为“原始”实体,并提供getter和setter来访问值。然后,我的getter和setter实现只定义了键(和对象类型)。

还有一个基类,它提供了我将这些字典传递到(或从中获取)的属性。

代码语言:javascript
复制
@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子类的实例。

代码语言:javascript
复制
@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内联中:

代码语言:javascript
复制
@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属性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1106862

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档