是否可以在目标C中为静态variables设置KVO通知?

我有类A,实例variables从caching的数据派生的属性,这个caching的数据被表示为一个单身,是A(它本质上是一个NSDictionary)的一部分。 不时,这个caching被修改。

发生这种情况时,我想让所有A实例在下次访问属性时从caching中提取新信息,或换句话说,使其属性内容无效。

到目前为止,手动通知每个实例(使用静态数组来跟踪成员)。 我不是粉丝。 通知中心可能有一个选项,但我宁愿尝试使用KVO。

有没有人设法订阅iOS上的类variables的KVO变化? (换句话说,使用来自A的静态variables的更改来告诉A实例刷新其数据。)

换句话说,我很想拥有

static void* context = &context; static myHadHocObject* msignal; 

并在稍后的A类代码

 [msignal addObserver:self forKeyPath:@"operation" options:NSKeyValueObservingOptionNew context:context]; 

并通过一个类实例通知msignal的变化

 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ } 

我试过使用各种专门的课程,没有运气。 似乎我失去了一些东西。

指针是受欢迎的,谢谢!

KVO说,一个特定的对象观察另一个对象(或其本身)属性的变化。 所以我认为你想达到的目标是不可能的,至less不是这样的。 或者至less你需要更深入的KVO机制。

您可以从Apple Key-Value Observing编程指南中获取所需的所有信息来回答您的问题

与使用NSNotificationCenter的通知不同,不存在为所有观察者提供更改通知的中央对象。 而是在发生更改时直接将通知发送到观察对象。 NSObject提供了这个键值观察的基本实现,你应该很less需要重写这些方法。

您可以用- willChangeValueForKey:- didChangeValueForKey:来激发KVO。 你可以在NSKeyValueObserving Protocol Reference上阅读更多

我build议你使用一种不同的方法,通过创build一个pipe理器来pipe理你的caching,并观察caching上的值,只是一个例子。

CacheManager.h

 #import <Foundation/Foundation.h> @interface CacheManager : NSObject @property (nonatomic, strong, readonly) NSArray *data; + (instancetype)sharedManager; @end 

CacheManager.m

 #import "CacheManager.h" @implementation CacheManager - (instancetype)init { if (self = [super init]) { _data = [[NSArray alloc] init]; } return self; } + (instancetype)sharedManager { static CacheManager *selfManager; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ selfManager = [[[self class] alloc] init]; }); return selfManager; } @end 

ViewController.m

 #import "ViewController.h" #import "CacheManager.h" static void *CacheManagerDataChangedContext = &CacheManagerDataChangedContext; @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; CacheManager *cacheManager = [CacheManager sharedManager]; [cacheManager addObserver:self forKeyPath:NSStringFromSelector(@selector(data)) options:NSKeyValueObservingOptionNew context:CacheManagerDataChangedContext]; } - (void)dealloc { [[CacheManager sharedManager] removeObserver:self forKeyPath:NSStringFromSelector(@selector(data)) context:CacheManagerDataChangedContext]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == CacheManagerDataChangedContext) { <# your stuff #> } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } @end 

如果您从其他所有实例中观察到CacheManagerdata属性,那么在更改时将通知所有该实例。

希望有所帮助;)

以防万一,而且不会削弱@meligaletiko的优​​点,我正在编写完整解决scheme的蓝图,对应于我的问题,以防万一对任何人都有用。

问题是:给定类实例使用从存储中获取的数据的副本,如何有效地通知所有类实例,当其中一个实例修改数据? (例如:数据来自NSUserDefaults,但是您不一定要每次都从/中获取/保存数据,因为速度很慢)另外,数据更改并不常见。

从@meligaletiko

 #import <Foundation/Foundation.h> @interface CacheManager : NSObject @property (nonatomic, strong) NSString *data; + (instancetype)sharedManager; @end #import "CacheManager.h" @implementation CacheManager - (instancetype)init { if (self = [super init]) { _data = @"x"; } return self; } + (instancetype)sharedManager { static CacheManager *selfManager; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ selfManager = [[[self class] alloc] init]; }); return selfManager; } @end static void *CacheManagerDataChangedContext = &CacheManagerDataChangedContext; @interface A:NSObject -(NSString*)sz; -(void)setSz:(NSString*)sz; @end @interface A () @property (nonatomic,sopy) NSString* sz; @property (nonatomic) BOOL shouldFetchDataFromStore; -(id)fetchDataForKey:(NSString*)key @end @implementation A -(instancetype)init{ self = [super init]; if (self) { [[CacheManager sharedManager] addObserver:self forKeyPath:NSStringFromSelector(@selector(data)) options:NSKeyValueObservingOptionNew context:CacheManagerDataChangedContext]; } return self; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == CacheManagerDataChangedContext) { self.shouldFetchDataFromStore = YES; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } -(void)dealloc{ [[CacheManager sharedManager] removeObserver:self forKeyPath:NSStringFromSelector(@selector(data)) context:CacheManagerDataChangedContext]; } -(void)setSz:(NSString*)sz{ _sz = sz;//sanity checks spared... [CacheManager sharedManager].data = @"x";//this line will notify all other instances } -(NSString*)sz{ if(self.shouldFetchDataFromStore) { // in other class instances, this was updated to YES, thanks to KVO self.shouldFetchDataFromStore = NO; _sz = (NSString*)[self fetchDataForKey:(NSString*)sz];//updates _sz with the correct value. } return _sz; } @end