I'm having a dilemma that I can't seem to solve. I've applied some KVO through a binding to a property on a model, however, because I'm not assigning through dot notation the KVO doesn't get fired. Instead, I'm appending like so:
[[self messagesString] appendAttributedString:attrVal];
messagesString
is an NSMutableAttributedString
. Of course this won't kick off the KVO notification so I instead do the following:
[self willChangeValueForKey:@"messagesString"];
[[self messagesString] appendAttributedString:attrVal];
[self didChangeValueForKey:@"messagesString"];
But I'm having no luck with this. If I do the following:
NSAttributedString *attrVal = [[NSAttributedString alloc] initWithString:str];
[self willChangeValueForKey:@"messagesString"];
[[self messagesString] appendAttributedString:attrVal];
[self didChangeValueForKey:@"messagesString"];
messagesString = [[NSMutableAttributedString alloc] initWithAttributedString:messagesString];
Then it works fine. However, if I remove the appending line, it doesn't work. It seems it has to be in this order, including these things, for it to work.
What am I missing that's so obvious for it to kick off the KVO notification?
EDIT
So, I've torn out any non-relevant stuff from this class declaration, but here's the main one I was referring to:
#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
And the implementation
#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
I do initWithString
for the NSMutableAttributedString
because there's some oddities in the way you use an instance of this class if it doesn't already have an empty string (appendAttributedString
has issues if no value was set upon instantiation supposedly).
This is how a string is appended to it in a completely separate class:
Channel *c = [channels valueForKey:@"server"];
[c appendString:val];
Finally, my UI has a binding for an NSTextView
on the Attributed String property to go to self.currentChannel.messagesString
. I'm not on my Mac at the moment so I can't show these bits.
The appendString
method in my Channel
class looks as it is because I was toying around with getting it to work. Very much play code.