我遇到了一个我似乎无法解决的困境。我通过绑定到模型上的属性来应用一些KVO,但是,因为我没有通过点表示法分配KVO不被解雇。相反,我是这样追加的:
[[self messagesString] appendAttributedString:attrVal];
messagesString
是NSMutableAttributedString
。当然,这不会启动KVO通知,所以我做了以下事情:
[self willChangeValueForKey:@"messagesString"];
[[self messagesString] appendAttributedString:attrVal];
[self didChangeValueForKey:@"messagesString"];
但我对此没有运气。如果我执行以下操作:
NSAttributedString *attrVal = [[NSAttributedString alloc] initWithString:str];
[self willChangeValueForKey:@"messagesString"];
[[self messagesString] appendAttributedString:attrVal];
[self didChangeValueForKey:@"messagesString"];
messagesString = [[NSMutableAttributedString alloc] initWithAttributedString:messagesString];
然后它工作正常。但是,如果我删除附加行,则它不起作用。它似乎必须按照这个顺序,包括这些东西,才能发挥作用。
我错过了什么让它开始KVO通知显而易见?
修改
所以,我已经从这个类声明中删除了任何不相关的东西,但这是我所指的主要内容:
#import <Foundation/Foundation.h>
@interface Channel : NSObject {
NSString* name;
NSMutableAttributedString *messagesString;
}
@property (retain) NSString* name;
@property (retain) NSMutableAttributedString* messagesString;
- (id)initWithName:(NSString*)name;
- (void)appendString:(NSString*)str;
@end
实施
#import "Channel.h"
@implementation Channel
@synthesize name;
@synthesize messagesString;
- (id)initWithName:(NSString *)channelName {
self = [super init];
if (self)
{
[self setName:channelName];
messagesString = [[NSMutableAttributedString alloc] initWithString:@" "];
}
return self;
}
- (void)appendString:(NSString *)str {
NSAttributedString *attrVal = [[NSAttributedString alloc] initWithString:str];
[self willChangeValueForKey:@"messagesString"];
[[self messagesString] appendAttributedString:attrVal];
[self didChangeValueForKey:@"messagesString"];
messagesString = [[NSMutableAttributedString alloc] initWithAttributedString:messagesString];
}
@end
我为initWithString
做了NSMutableAttributedString
因为如果它没有空字符串,那么你使用这个类的实例的方式有些奇怪(appendAttributedString
有问题,如果在假设实例化时没有设置任何值。)
这是在完全独立的类中将字符串附加到它的方式:
Channel *c = [channels valueForKey:@"server"];
[c appendString:val];
最后,我的UI在Attributed String属性上绑定了NSTextView
以转到self.currentChannel.messagesString
。我现在不在Mac上,所以我无法展示这些内容。
我的appendString
课程中的Channel
方法看起来就像是因为我正在努力让它运转起来。很多游戏代码。
答案 0 :(得分:2)
我创建了一个项目并玩弄它。如果您决定使用手动KVO(使用自动...类方法声明),那么当您在该ivar / property上使用“setValue”时,您将无法获得kvo(因此我的原始答案不正确)。
我创建了一个测试项目,然后使用了一个可变字符串并验证了是,当我使用包含appendString的will / did消息时,我确实获得了KVO:变量字符串。这证实了您显示的代码实际上应该可以工作。然后我注释掉了代码并直接用另一个字符串设置了可变字符串,并且根本没有获得任何KVO(如预期的那样)。
此时我只能猜测你的财产,你的班级或者观察观察这些变化的observeValueForKeypath:方法有一些非常不寻常的事情。
编辑:问题是NSTextView。它维护自己的存储系统,所以实际上当你想要向它添加数据时,你将直接执行它,并且对你的attributionString的绑定应该更新(而不是相反)。当你做出最后一次更改时它的工作原理是你告诉textView字符串已经改变了,但是看起来它最初没有改变,但最后当你设置了一个全新的字符串时,它注册了更改并更新。
对于推理和解决方案,请查看此thread。 Davidson是Apple长期负责文本系统的工程师之一(他回答了这个问题)。