【问题标题】:Cocoa: NSMutableString binding to XIB does not update, but NSString binding does updateCocoa:NSMutableString 绑定到 XIB 不会更新,但 NSString 绑定会更新
【发布时间】:2014-08-26 21:17:31
【问题描述】:

当我更改字符串时,绑定到 NSMutableString 属性的 XIB 中的标签似乎不会更新,但如果属性是 NSString,标签会更新。

在一个测试应用程序中,我有默认的 AppDelegate 类和 MainMenu.xib。我在 AppDelegate 中创建了两个属性,一个 NSString 和一个 NSMutableString,并将它们绑定到 XIB 中的两个标签。我有两个按钮可以将这些字符串的值从一组更改为另一组并返回。代码如下。 NSLog 的输出显示 NSMutableString 的值正在改变,但没有反映在 GUI 中。

不知道我错过了什么......任何帮助将不胜感激!

PS:编辑:我想在不创建新的可变字符串的情况下实现这一点

代码:

@synthesize mutLabel, unmutLabel;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [self willChangeValueForKey:@"mutLabel"];
    mutLabel = [NSMutableString stringWithCapacity:10];
    [mutLabel setString:@"MutLabel 1"];
    [self didChangeValueForKey:@"mutLabel"];

    [self willChangeValueForKey:@"unmutLabel"];
     unmutLabel = @"UnMutLabel 1";
    [self didChangeValueForKey:@"unmutLabel"];

    [self addObserver:self forKeyPath:@"mutLabel" options:0 context:nil];
    [self addObserver:self forKeyPath:@"unmutLabel" options:0 context:nil];
}

- (IBAction)clkBtn1:(id)sender {

    [self willChangeValueForKey:@"mutLabel"];
    [mutLabel setString:@"MutLabel 1"];
    [self didChangeValueForKey:@"mutLabel"];

    [self willChangeValueForKey:@"unmutLabel"];
    unmutLabel = @"UnMutLabel 1";
    [self didChangeValueForKey:@"unmutLabel"];
}

- (IBAction)clkBtn2:(id)sender {

    [self willChangeValueForKey:@"mutLabel"];
    [mutLabel setString:@"MutLabel 2"];
    [self didChangeValueForKey:@"mutLabel"];

    [self willChangeValueForKey:@"unmutLabel"];
    unmutLabel = @"UnMutLabel 2";
    [self didChangeValueForKey:@"unmutLabel"];
}

-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"Key change: Key: %@  Value: %@\n",keyPath, [self performSelector:NSSelectorFromString(keyPath)]  );
}

【问题讨论】:

  • 尝试使用 mutLabel.string,而不是 mutLabel? KVC 查找 setter/getter 调用,因此 setString/string 基本上是可变字符串对象上字符串“property”的访问器。
  • @stevesliva :试过了,但我崩溃了。“类不是键值编码投诉”
  • 嗯。这很烦人。 (因为没有一个类同时支持 setter 和 getter?)this question 的重复,顺便说一句。虽然我不确定我是否喜欢这些答案。当绑定正在寻找设置器时,您可能会收到该错误消息——也许尝试将 mutLabel.string 绑定到按钮的标题或某些工具提示。只读绑定可能有效。如果单向绑定有效,那么可能有一种方法可以让值绑定永远不会寻找 setter。

标签: objective-c cocoa nsmutablestring


【解决方案1】:

删除上面的代码行并尝试下面的代码行来设置绑定到标签的可变和不可变对象中的字符串。

    NSString * str=@"yourString";
    self.mutLabel=[str mutableString];
    self.unmutLabel=str;

【讨论】:

  • 侯赛因,谢谢!您的解决方案有效,但不是每次都创建一个新的可变字符串吗?例如,如果我声明第三个属性“pointToMutLabel”,并将其定义为“pointToMutLabel = mutLabel”,那么这两个字符串在更改后不会跟踪。我想在不创建新字符串的情况下实现这一目标
  • 如果你有第三个属性,那么只需声明为 self.pointToMutLabel=[str mutableString];就像以前的可变字符串一样。这样它将确保在所有可变字符串中都使用一个字符串变量。
  • 这就是我想要做的:在我的真实应用程序中,AppDelegate 首先处理一些时间变量数据以生成一堆字符串,因此无法再次实例化。不时地,基于套接字中断,这些字符串被更新。我有几个显示这些字符串的 XIB,每个 XIB 都有自己的 NSWindowController,它在 AppDelegate 中实例化。如何在不将 AppDelegate 实例化为 XIB 中的对象的情况下将这些 XIB 中的标签绑定到 AppDelegate 中的字符串属性?我认为解决方案是创建 NSMutableString 属性并“将它们等同”
  • 好的,然后始终使用新值更新您的 NSString str=[self.mutLabel string];并将这个字符串传递给新的 self.pointMutLabel=[str mutableString];
【解决方案2】:

根据文档,在适当的情况下调用willChangeValueForKey:didChangeValueForKey: 应该是为了支持绑定在KVO 合规性方面所需要的。但是,据我可以通过实验确定*,如果它们绑定的属性在更新。实验表明观察发生了,但被忽略了;据推测,视图包含避免不必要更新的逻辑。

简而言之,NSTextViewNSTextField 的绑定与 NSMutableString 突变不兼容。除非您有其他理由使用可变字符串,否则最好坚持使用不可变版本。

* AppKit 似乎并未包含在 Apple 的开源版本中,因此无法检查源代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-29
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多