【问题标题】:How to bind NSButton enabled state to a composed condition如何将 NSButton 启用状态绑定到组合条件
【发布时间】:2011-12-31 00:25:04
【问题描述】:

这是我在 Xcode Interface Builder 中的情况:

还有一个实体模式的 NSArrayController 来控制 NSTableView 的内容。我想在 NSTableView 为空时启用“创建”按钮(由 NSSearchField 控制)AND 当 NSSearchField 中的文本不为空时。我该如何做到这一点?不编程可以吗?

我可以将“创建”按钮的 2 个启用条件绑定到哪些 KVO 兼容值?

【问题讨论】:

    标签: cocoa interface-builder key-value-observing nsarraycontroller nsbutton


    【解决方案1】:

    我不认为有一种方法可以完全在界面生成器中完成,但只需少量代码,您就可以很容易地让它工作。首先,确保您的控制器(或 App Delegate)被设置为搜索字段的代理,并且它具有与搜索字段、按钮和数组控制器的 IBOutlet 连接。以下是我将如何实现它:

    // This is an arbitrary pointer to indicate which property has changed.
    void *kObjectsChangedContext = &kObjectsChangedContext;
    
    - (void)awakeFromNib {
    
        // Register as an observer so we're notified when the objects change, and initially at startup.
        [arrayController addObserver:self
                          forKeyPath:@"arrangedObjects"
                             options:NSKeyValueObservingOptionInitial
                             context:kObjectsChangedContext];
    }
    
    // This updates the button state (based on your specs)
    - (void)updateButton {
    
        BOOL canCreate = (searchField.stringValue.length > 0 &&
                          0 == [arrayController.arrangedObjects count]);
        [createButton setEnabled:canCreate];
    }
    
    // This delegate method is called whenever the text changes; Update the button.
    - (void)controlTextDidChange:(NSNotification *)obj {
        [self updateButton];
    }
    
    // Here's where we get our KVO notifications; Update the button.
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    
        if (kObjectsChangedContext == context)
            [self updateButton];
    
        // It's good practice to pass on any notifications we're not registered for.
        else {
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
    }
    

    如果您不熟悉绑定,其中一些可能看起来像希腊语,希望 cmets 足够清晰。

    【讨论】:

    • Francis,这个很不错,可以直接使用,文档很好。对我来说这不是希腊语,但我希望避免编码,你现在为我做了;)如果在接下来的 3 天内没有其他人提出声明性解决方案,我会将其标记为答案。非常感谢!
    【解决方案2】:

    我为此迟到了,但想出了另一种方法,并在我的应用程序中进行了测试。它有效,因此我将与将来发现此问题的任何人分享。

    基本上你想要做的是在你的控制器中创建一个没有相应值的属性

         @property (readonly) BOOL enableProperty;
    

    这意味着实际上没有

        BOOL enableProperty;
    

    在头文件中定义,或任何地方

    那么,与其合成它,不如写你自己的getter,然后把你的条件放在那里

        - (BOOL) enableProperty{
            return (condition);
        }
    

    第三步:任何时候你的病情有变化的机会,通知它。

        - (void) someMethod{
            //.... Some code
            [self willChangeValueForKey:@"enableProperty"];
            [Thisline mightChange:theCondition];
            [self didChangeValueForKey:@"enableProperty"];
            //.... Some other code
        }
    

    第四步:在 IB 中,将控件的 enabled 属性绑定到这个“假”属性。

    享受吧! ;)

    【讨论】:

      【解决方案3】:

      你似乎有一个窗口,所以大概你有一个控制器对象,它被设置为 NIB 文件的文件所有者。

      为什么不在这个控制器类中声明一个布尔属性,它会根据你想要的任何条件返回一个值?

      @property(readonly) BOOL canCreate;
      

      你实施的:

      -(BOOL)canCreate {
          // compute and return the value
      }
      

      确保在创建条件发生变化时适当地发送 KVO 通知。
      最后一步是将按钮的enabled绑定到文件所有者canCreate键上。

      【讨论】:

      • 这不会发送消息,因为在文本字段中输入了文本——需要添加逻辑。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-17
      相关资源
      最近更新 更多