我想添加一些逻辑,当清除另一个复选框时清除一个复选框,并恢复原始值,如果它在同一个会话中重新检查.由于我需要将存储与字典相关联,并且还需要添加代码,我以为我会使用composition来扩展NSMutableDictionary.
这就是我所做的:
>我创建了一个包含NSMutableDictionary的libraryEntry子类.
>我实现了forwardInvocation:,respondsToSelector:,methodSignatureForSelector:,以及一些试错了valueForUndefinedKey:.
>我创建了我的转发器对象.
>我按原样离开了绑定.
它加载数据很好,但我猜测KVO将无法正常工作.我猜测绑定器在我的对象上调用addobserver:但我没有实现任何特殊的处理它.
我想简单地重写addobserver:并将消息转发到字典.但是如果我这样做,observeValueForKey:notification将不会来自我的对象(addobserver的原始接收者),而是来自字典.
在我尝试为这些KVO调用实现更透明的转发之前,我想……这变得越来越混乱.我继续阅读“使用组合,而不是子类”来获得这样的行为.对于这种情况,这只是错误的模式吗?为什么?因为KVO?
如果我放弃作曲并选择其中一种替代方案,我似乎会得到更清晰的结果:
>使用装饰器,一个实例观察每个字典
>将临时密钥存储在字典中,让控制器在保存之前将其删除
>取消字典并声明属性
这是我的代码,万一它有用(值是字典):
- (voID)forwardInvocation:(NSInvocation *)anInvocation { if ([values respondsToSelector:[anInvocation selector]]) [anInvocation invokeWithTarget:values]; else [super forwardInvocation:anInvocation];}- (BOol)respondsToSelector:(SEL)aSelector { if ( [super respondsToSelector:aSelector] ) return YES; else return [values respondsToSelector:aSelector];}- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { NSMethodSignature* signature = [super methodSignatureForSelector:selector]; if (!signature) signature = [values methodSignatureForSelector:selector]; return signature;}-(ID)valueForUndefinedKey:(Nsstring *)key { return [values valueForKey:key];}解决方法 我认为结合使用Objective-C相关存储和一些块,您可以将任意行为连接到字典(或任何其他符合KVO的对象)并以这种方式解决您的问题.我提出了以下想法,它实现了一个通用的KVO-triggers-block机制,编码和示例似乎做了你想要它做的事情,并且不涉及子类化或装饰基础集合.
首先是这个机制的公共接口:
typedef voID (^KBBehavior)(ID object,Nsstring* keyPath,ID oldValue,ID newValue,ID userInfo);@interface NSObject (KBKVOBehaviorObserver)- (voID)addBehavior: (KBBehavior)block forKeyPath: (Nsstring*)keyPath options: (NSkeyvalueObservingOptions)options userInfo: (ID)userInfo;- (voID)removeBehaviorForKeyPath: (Nsstring*)keyPath;@end
这将允许您将基于块的观察/行为附加到任意对象.您使用复选框描述的任务可能如下所示:
- (voID)testBehaviors{ NSMutableDictionary* myModelDictionary = [NSMutableDictionary dictionary]; KBBehavior behaviorBlock = ^(ID object,ID userInfo) { NSMutableDictionary* modelDictionary = (NSMutableDictionary*)object; NSMutableDictionary* prevIoUsValues = (NSMutableDictionary*)userInfo; if (nil == newValue || (![newValue boolValue])) { // If the master is turning off,turn off the slave,but make a note of the prevIoUs value ID prevIoUsValue = [modelDictionary objectForKey: @"slaveCheckBox"]; if (prevIoUsValue) [prevIoUsValues setobject: prevIoUsValue forKey: @"slaveCheckBox"]; else [prevIoUsValues removeObjectForKey: @"slaveCheckBox"]; [modelDictionary setobject: newValue forKey: @"slaveCheckBox"]; } else { // if the master is turning ON,restore the prevIoUs value of the slave ID prevValue = [prevIoUsValues objectForKey: @"slaveCheckBox"]; if (prevValue) [modelDictionary setobject:prevValue forKey: @"slaveCheckBox"]; else [modelDictionary removeObjectForKey: @"slaveCheckBox"]; } }; // Set the state... [myModelDictionary setobject: [NSNumber numberWithBool: YES] forKey: @"slaveCheckBox"]; [myModelDictionary setobject: [NSNumber numberWithBool: YES] forKey: @"masterCheckBox"]; // Add behavior [myModelDictionary addBehavior: behaviorBlock forKeyPath: @"masterCheckBox" options: NSkeyvalueObservingOptionNew userInfo: [NSMutableDictionary dictionary]]; // turn off the master [myModelDictionary setobject: [NSNumber numberWithBool: NO] forKey: @"masterCheckBox"]; // we Now expect the slave to be off... NSLog(@"slaveCheckBox value: %@",[myModelDictionary objectForKey: @"slaveCheckBox"]); // turn the master back on... [myModelDictionary setobject: [NSNumber numberWithBool: YES] forKey: @"masterCheckBox"]; // Now we expect the slave to be back on,since that was it's prevIoUs value NSLog(@"slaveCheckBox value: %@",[myModelDictionary objectForKey: @"slaveCheckBox"]);}
我通过创建一个跟踪块和userInfos的对象来实现块/ KVO连接,然后让它成为KVO观察者.这是我做的:
#import <objc/runtime.h>static voID* kKVOBehaviorsKey = &kKVOBehaviorsKey; @interface KBKVOBehaviorObserver : NSObject{ NSMutableDictionary* mBehaviorsByKey; NSMutableDictionary* mUserInfosByKey;}@end@implementation KBKVOBehaviorObserver- (ID)init{ if (self = [super init]) { mBehaviorsByKey = [[NSMutableDictionary alloc] init]; mUserInfosByKey = [[NSMutableDictionary alloc] init]; } return self;}- (voID)dealloc{ [mBehaviorsByKey release]; mBehaviorsByKey = nil; [mUserInfosByKey release]; mUserInfosByKey = nil; [super dealloc];}- (voID)addBehavior: (KBBehavior)block forKeyPath: (Nsstring*)keyPath userInfo: (ID)userInfo{ @synchronized(self) { ID copIEdBlock = [[block copy] autorelease]; [mBehaviorsByKey setobject: copIEdBlock forKey: keyPath]; [mUserInfosByKey setobject: userInfo forKey: keyPath]; }}- (voID)removeBehaviorForKeyPath: (Nsstring*)keyPath{ @synchronized(self) { [mUserInfosByKey removeObjectForKey: keyPath]; [mBehaviorsByKey removeObjectForKey: keyPath]; }}- (voID)observeValueForKeyPath:(Nsstring *)keyPath ofObject:(ID)object change:(NSDictionary *)change context:(voID *)context{ if (context == kKVOBehaviorsKey) { KBBehavior behavior = nil; ID userInfo = nil; @synchronized(self) { behavior = [[[mBehaviorsByKey objectForKey: keyPath] retain] autorelease]; userInfo = [[[mUserInfosByKey objectForKey: keyPath] retain] autorelease]; } if (behavior) { ID oldValue = [change objectForKey: NSkeyvalueChangeoldKey]; ID newValue = [change objectForKey: NSkeyvalueChangeNewKey]; behavior(object,keyPath,oldValue,newValue,userInfo); } }}@end@implementation NSObject (KBKVOBehaviorObserver)- (voID)addBehavior: (KBBehavior)block forKeyPath: (Nsstring*)keyPath options: (NSkeyvalueObservingOptions)options userInfo: (ID)userInfo{ KBKVOBehaviorObserver* obs = nil; @synchronized(self) { obs = objc_getAssociatedobject(self,kKVOBehaviorsKey); if (nil == obs) { obs = [[[KBKVOBehaviorObserver alloc] init] autorelease]; objc_setAssociatedobject(self,kKVOBehaviorsKey,obs,OBJC_ASSOCIATION_RETAIN); } } // Put the behavior and userInfos into stuff... [obs addBehavior: block forKeyPath: keyPath userInfo: userInfo]; // add the observation [self addobserver: obs forKeyPath: keyPath options: options context: kKVOBehaviorsKey];}- (voID)removeBehaviorForKeyPath: (Nsstring*)keyPath{ KBKVOBehaviorObserver* obs = nil; obs = [[objc_getAssociatedobject(self,kKVOBehaviorsKey) retain] autorelease]; // Remove the observation [self removeObserver: obs forKeyPath: keyPath context: kKVOBehaviorsKey]; // remove the behavior [obs removeBehaviorForKeyPath: keyPath];}@end
有点不幸的是,你必须删除观察/行为才能打破原始字典和观察对象之间的传递保留周期,所以如果你不删除行为,你就会泄漏采集.但总的来说这种模式应该是有用的.
希望这可以帮助.
总结以上是内存溢出为你收集整理的objective-c – 在使用组合扩展NSMutableDictionary时支持KVO全部内容,希望文章能够帮你解决objective-c – 在使用组合扩展NSMutableDictionary时支持KVO所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)