objective-c - 我如何优化这个巨大的 if/else if block 在 observeValueForKey 中

标签 objective-c nsdictionary key-value-observing foundation

我有一个注册为 View 上很多属性的观察者的 Controller 。这是我们的 -observeValueForKeyPath::::: 方法:

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

   if( context == kStrokeColorWellChangedContext )
   {
      [self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:kStrokeColorProperty];
   }
   else if( context == kFillColorWellChangedContext )
   {
      [self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:kFillColorProperty];
   }
   else if( context == kBodyStyleNumChangedContext )
   {
      [self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:kBodyStyleNumProperty];
   }
   else if( context == kStyleChangedContext )
   {
      [self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:kStyleProperty];
   }
   else if( context == kStepStyleChangedContext )
   {
      [self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:kStepStyleProperty];
   }
   else if( context == kFirstHeadStyleChangedContext )
   {
      [self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:kFirstHeadStyleProperty];
   }
   else if( context == kSecondHeadStyleChangedContext )
   {
      [self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:kSecondHeadStyleProperty];
   }

实际上,这些 else if 语句的数量是原来的 3 倍。
您可以看到的一件事是每个 block 都有相同的代码,这让我认为可以对此进行优化。

我最初的想法是有一个名为 keyPathForContextDictionaryNSDictionary,其中的键是带有 Context 后缀( 类型)的常量void*),值是适当的字符串常量,由 Property 后缀

表示

那么这个方法就只需要一行:

[self setValue:[change objectForKey:NSKeyValueChangeNewKey] forKey:keyPathForContextDictionary[context]];

请注意,我需要使用某种数据结构来确定要使用的 keyPath,而且我不能简单地使用传递到方法中的 keyPath 参数。这是因为有多个 View 具有我正在观察的相同属性(例如,颜色井具有 color 属性)。因此每个 View 都需要确定一个唯一的键路径,目前正在根据上下文确定该键路径

问题在于您不能将 void* 用作 NSDictionary 中的键。那么...有人对我在这里可以做什么有什么建议吗?

编辑: 下面是如何定义常量的示例:

void * const kStrokeColorWellChangedContext = (void*)&kStrokeColorWellChangedContext;
void * const kFillColorWellChangedContext = (void*)&kFillColorWellChangedContext;
void * const kBodyStyleNumChangedContext = (void*)&kBodyStyleNumChangedContext;
void * const kStyleChangedContext = (void*)&kStyleChangedContext;

NSString *const kStrokeColorProperty     = @"strokeColor";
NSString *const kFillColorProperty       = @"fillColor";
NSString *const kShadowProperty          = @"shadow";
NSString *const kBodyStyleNumProperty    = @"bodyStyleNum";
NSString *const kStyleProperty           = @"style";

最佳答案

void * 类型本身并不是您必须匹配的类型,因为它是“通用指针”。它精确地用于 context 参数,因此您可以使用您喜欢的任何基础类型,包括对象类型。您所要做的就是执行正确的转换。

因此,您可以非常轻松地将 kTHINGYChangedContext 更改为 NSString 或您喜欢的任何其他对象,然后将它们用作上下文中的键 -> 键路径映射。

开始于:

NSString * const kStrokeColorWellChangedContext = @"StrokeColorWellChangedContext";

注册观察时,您必须执行桥接 Actor :

[colorWell addObserver:self
            forKeyPath:keyPath
               options:options
               context:(__bridge void *)kStrokeColorWellChangedContext];

然后当观察发生时,你做反向转换:

-(void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void*)ctx
{
    NSString * context = (__bridge NSString *)ctx;
    // Use context, not ctx, from here on.
}

然后从那里继续查找关键路径。

关于objective-c - 我如何优化这个巨大的 if/else if block 在 observeValueForKey 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33135532/

相关文章:

iphone - 以编程方式备份​​完整的iPhone AddressBook

ios - 在 swift 的 HTTP POST 请求中设置参数

ios - 在用户位置更新时停止 map 更新 - Google Maps iOS SDK

iphone - 如何用自身叠加声音?

objective-c - 如何在没有 init( ) 方法的情况下创建新实例?

objective-c - 将两个不同的模型键路径绑定(bind)到相同的 NSArrayController 选择

iphone - 如何键值观察 CALayer 的旋转?

ios - 如何在 Swift 中使用键值编码获取全局常量?

iphone - 如何在 iPhone 中访问收件箱消息

ios - 如何将 filteredArrayUsingPredicate 与 NSDictionary 一起使用?