0

解決できないジレンマに悩んでいます。モデルのプロパティへのバインディングを介して 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インスタンス化時に値が設定されていない場合に問題があると思われます)。NSMutableAttributedStringappendAttributedString

これは、完全に別のクラスで文字列が追加される方法です。

Channel *c = [channels valueForKey:@"server"];
[c appendString:val];

最後に、私の UI にはNSTextView、属性付き文字列プロパティに移動するためのバインディングがありself.currentChannel.messagesStringます。現時点では Mac を使用していないため、これらのビットを表示できません。

私のクラスのappendStringメソッドは、Channel動作させるためにいじっていたので、そのままのように見えます。非常に多くのコードを再生します。

4

1 に答える 1

2

私はプロジェクトを作成し、それをいじりました。手動の KVO を (自動的に... クラス メソッド宣言を使用して) 使用することにした場合、その ivar/property で「setValue」を使用しても kvo を取得できません (したがって、私の元の答えは正しくありませんでした)。

テスト プロジェクトを作成し、変更可能な文字列を使用して、はい、appendString: を変更可能な文字列にラップした will/did メッセージを使用したときに KVO を取得したことを確認しました。これにより、表示するコードが実際に機能することが確認されました。次に、そのコードをコメントアウトし、変更可能な文字列を別の文字列で直接設定しましたが、KVO はまったく取得されませんでした (予想どおり)。

この時点で、これらの変更を監視しているプロパティ、クラス、またはobserveValueForKeypath:メソッドに非常に異常な何かがあると推測することしかできません。

編集: 問題は NSTextView です。独自のストレージ システムを維持するため、実際にデータを追加する場合は、直接追加し、YOUR attributedString へのバインディングを更新する必要があります (その逆ではありません)。最終的な変更を行ったときに機能した理由は、文字列が変更されたことを textView に伝えたことですが、最初は変更されていないように見えましたが、最終的に完全に新しい文字列を設定すると、変更が登録されて更新されました。

理由と解決策の両方について、このスレッドを見てください。Davidson はテキストシステムを長年担当している Apple エンジニアの 1 人です (彼は質問に答えました)。

于 2012-08-04T12:11:54.110 に答える