【问题标题】:How do I bind an NSMutableString to the value of an NSTextView?如何将 NSMutableString 绑定到 NSTextView 的值?
【发布时间】:2010-09-05 04:30:52
【问题描述】:

好的,所以我正在尝试在 Xcode 中为自己设置一个非常简单的程序。
我有一个窗口(在界面生成器中),其中包含一个 NSTextView 和一个 NSButton。在我的 AppController 类中,我已将 NSMutableString 声明为属性。我想做的是为字符串设置一个初始值,比如@“First Entry\n”,然后将它绑定到NSTextView。当我按下按钮时,会调用一个方法 -(IBAction)appendToString,它将 @"Another Line\n" 附加到 NSMutableString
我希望这些更改通过绑定和键值观察反映在NSTextView 中,而不是通过声明IBOutlet 并手动更新内容。我还想在 textview 中进行更改以编辑 NSMutable 字符串。

不幸的是,我非常困惑,并且没有运气弄清楚这一点。

有哪些基本步骤可以解决这个问题?

*****编辑*****

好的,Peter Hosey 间接解决了这个问题。我忘记了我必须使用 setLogString 方法,而不是使用 [logString appendFormat:]。所以这是我最终得到的代码:

在 AppController.h 中:

#import <Cocoa/Cocoa.h>
@interface AppController : NSObject {
    IBOutlet NSButton *appendButton;
    NSString *logString;
    IBOutlet NSTextView *thatView;
}
@property (readwrite, copy) NSString *logString;
-(IBAction)hitIt:(id)sender;
@end

AppController.m:

#import "AppController.h"
@implementation AppController
-(void)awakeFromNib
{
}
-(id)init
{
    [super init];   
    logString = @"First Line\n";
    return self;
}
-(IBAction)hitIt:(id)sender
{
    [self setLogString:[logString stringByAppendingString:@"Hey, Another Line!\n"]];
}
@synthesize logString;
@end

然后,在 InterfaceBuilder 中,我将 NSTextView 绑定到 AppController.logString,并设置“持续更新值”标志,以便我对文本字段所做的更改将应用​​于字符串。

非常感谢各位的帮助!

【问题讨论】:

  • 你不需要在那里使用allocinitWithFormat:。当您有要传递的格式字符串时,您应该只使用initWithFormat:(和stringByAppendingFormat:);这些字符串都不包含任何格式化序列,所以你应该在第一种情况下分配裸字符串文字(它是一个 NSString,因为它是一个文字,所以不保留它是可以的),并使用stringByAppending*String: * 在第二种情况下。
  • 哎呀,感谢您接住彼得。我在其中使用的实际程序确实使用了 stringByAppendingFormat,我不小心把它带到了我的测试程序中。现在修好了。 :)

标签: cocoa binding


【解决方案1】:

在我的 AppController 类中,我已将 NSMutableString 声明为属性。

这是正确的、符合 MVC 的解决方案。模型的主要所有者应该是控制器,而不是视图。所有视图都应该从控制器获取模型。

但是,您不应该公开字符串的可变性。然后,任何使用该属性的东西都可以尝试直接改变字符串,而 AppController 不知道更改并能够通知该属性的任何观察者。该属性应声明为 NSString,并声明为可读写,以便提供一个访问器,用该访问器将值替换为新字符串。

我要做的是为字符串设置一个初始值,比如@“First Entry\n”,然后将它绑定到NSTextView。

设置支持init 中属性的实例变量的值。

在 IB 中绑定 NSTextView。那么,当你加载笔尖时,它就已经被绑定了。

请注意,您要在加载笔尖之前设置 ivar。如果您先加载 nib,文本视图将看不到更改,因为直接设置 ivar(正如您在 init 中所做的那样,以避免产生属性副作用)正在观察者(视图)背后进行更改.如果在您加载 nib 时已经进行了更改(并且视图开始观察),那么视图不会错过任何内容。

当我按下按钮时,一个方法,-(IBAction)appendToString ...

Cocoa 中的每个动作都只接受一个参数——不多也不少。该参数是发送消息的控件。因此,正确的签名是:

- (IBAction) appendToString:(id)sender;

… 被调用,将 @"Another Line\n" 附加到 NSMutableString。

您需要做的就是向属性询问您当前的字符串,制作可变副本,进行更改,并将修改后的字符串设置为属性的新值。不要忘记释放那个可变副本。

我希望这些更改通过绑定和键值观察反映在 NSTextView 中,而不是通过声明 IBOutlet 并手动更新内容。我还希望在 textview 中进行更改以编辑 NSMutable 字符串。

当您将文本视图的 value 绑定绑定到 AppController 的属性时,这两种情况都是免费的。

【讨论】:

    【解决方案2】:

    只需使用这些简单的方法来设置和在需要时获取它,而不是拥有变量的本地副本。这样您就可以从视图中获取所有附加和编辑。

    - (IBAction)appendString:(id)sender{
    [[[textView textStorage] mutableString] appendString: string];
    

    }

    - (NSMutableString)getString{
    return [[textView storage] mutableString];
    

    }

    【讨论】:

    • 这是一个很好的解决方案,我想我会在我的 REAL 程序中使用它。但是,我仍然想弄清楚这个字符串绑定垃圾,因为我预计它以后可能很重要,而且至少,它没有按照我认为的方式工作,这让我很生气。困扰我的是我可以很好地绑定浮点数和整数。像 NSString 之类的对象在困扰我,我很确定这与它们都是通过指针传递的事实有关。
    • 是的,我敢打赌,在很多课程中,他们都会制作自己的字符串副本,这样您就永远无法获得指向它的直接指针。
    • 所以你要在视图中存储模型值?不是很MVC;控制器应该拥有模型,所有视图都应该从控制器中获取它。
    • 有了你的修复,我会以正确的方式来做,现在我知道怎么做了。 :)
    猜你喜欢
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 2020-07-09
    相关资源
    最近更新 更多