Как привязать редактируемое TextField к свойству только для чтения

Кто-нибудь знает, как предотвратить привязку Cocoa для установки значений обратно в связанное свойство, но все же запускает селектор действий по умолчанию?

Я пытаюсь привязать NSTextField к свойству NSString только для чтения в моем объекте данных. Мой объект данных похож на

...

@property(только для чтения) NSString* outCome;

-(void)otherMethodsAffectOutCome;

...

Я связал NSTextField со свойством результата и в обработчике действий по умолчанию я вызвал -otherMethodAffectOutCome, и я надеюсь, что will/didChangeValueForKey запустит наблюдателя свойства outCome и вернет NSTextField.

Но это не сработает, NSTextField выйдет из строя, потому что он попытается вернуть измененный текст с помощью метода setOutCome... Я думаю, мне нужно, чтобы NSTextField следил за изменением значения свойства, но не пытайтесь установить значения обратно при изменении текста, как Я делаю это?

Спасибо! -Джонни


person Jonny    schedule 05.02.2010    source источник


Ответы (2)


Поскольку у вас уже есть собственный объект модели, есть два варианта лучше, чем переопределение -setValue:forUndefinedKey:.

  1. Просто измените свойство, чтобы оно не было readonly. Поскольку это объект Objective-C, он должен быть retained.

  2. Если вам нужно, чтобы свойство отображалось как readonly для внешнего мира, вы можете либо вручную определить setOutCome: исключительно в реализации; внешнему миру будет казаться, что это свойство доступно только для чтения, если только не появится какой-нибудь умник и не вызовет напрямую -setOutCome:. Одним из таких умников является сама технология Cocoa Bindings.

    Это плохая идея, если вы не очень хорошо знаете, как должен работать retain сеттер, и если вы очень осторожны с ним. Кроме того, вам придется преобразовать свойство в nonatomic — рекомендуемый параметр для iOS, но не для OS X.

  3. Наконец, вот лучшее решение из этих трех, вариант метода 2. Помимо "категорий", классы также могут иметь "расширения". Проще говоря, вы должны думать о них как о не-настоящих категориях: дополнительных объявлениях методов, объявленных внутри вашего основного файла реализации (внутри файла .m) и реализованных внутри вашего основного файла реализации. Это используется для определения дополнительного частного интерфейса для вашего класса.

    В коде кажется, что это категория @interface, за исключением того, что круглые скобки пусты, опустив имя категории. Кроме того, это странная категория, в которой нет подходящего @implementation.

    Чем это полезно для вас?

    Вы можете определить свойство в своем заголовке как (retain, readonly), но затем переопределить его как (retain) в расширении класса. @synthesize теперь будет создавать методы доступа как для получения, так и для установки.

Итак, давайте рассмотрим пример метода 3.

#import <Foundation.h>

@interface MyClass : NSObject
{
    id _myValue;
}
@property (retain, readonly) id myValue;
@end

//
#import "MyClass.h"

@interface MyClass ()
@property (retain) id myValue;
@end

@implementation MyClass
@synthesize myValue = _myValue;
@end

Теперь тот факт, что свойство фактически содержит сеттер, является вашей деталью реализации, и в то же время вы не написали свой собственный сеттер. Возможно, это немного быстрее, чем если бы вы написали его самостоятельно, и вам не нужно было следить за порядком вызовов retain/release и операций присваивания.

person Ivan Vučica    schedule 30.07.2012

Наконец, я нашел обходной путь, переопределив метод setValue: forUndefinedKey: для моего объекта данных. если имя ключа outCome, просто вернитесь, не вызывая super.

person Jonny    schedule 06.02.2010