2011-04-03 71 views
2

我有一個ImageView,它顯示一個鎖,告知打開的文件是否被鎖定。我有2張鎖定和解鎖的圖像。我想要將顯示的圖像與代表打開文件的對象的布爾值同步。手動綁定在可可

爲此,我希望我的ViewController根據對象的鎖定狀態更改ImageView中的圖像。所以對象和ViewController都有一個屬性「isLocked」。

我該如何同步它們?在IB很容易,但我不知道如何以編程方式進行。我嘗試使用我的ViewController的初始化方法:

[ViewController bind:@"value" toObject:[ArrayController selection] withKeyPath:@"isLocked" options:nil]; 

但它不起作用。在文檔中,據說我必須在使用它之前公開我的綁定。

我嘗試把下面的代碼在我的對象的初始化方法:

[self exposeBinding:@"isLocked"]; 

但Xcode中不承認這個方法。

有人有這種綁定建立的經驗嗎?

+0

你想要做的鍵 - 值觀察? – 2011-04-03 09:00:06

+0

可能是有可能的。但我認爲綁定更容易實現。其實我只需要我的ViewController屬性來更新對象的屬性更改。通過按下ImageView觸發的ViewController的IBAction提供逆向更改。但無論如何,關於在不在InterfaceBuilder中的對象之間建立手動綁定的問題仍然是實際的。我相信我會在我的計劃的其他部分需要它。 – BartoNaz 2011-04-03 09:28:39

+0

還有一條評論。我曾經想過關鍵值觀察,我不知道它是否非常合適,因爲我有許多代表文件的對象,並且它們是按數組組織的。所以我的ViewController可以通過arrayController.selection.isLocked訪問它們。將觀察者添加到這樣的對象是否合適?我該如何指出呢?有我的對象使用IBOutlet ViewController使其可以添加爲觀察員? – BartoNaz 2011-04-03 10:03:21

回答

6

正如@nick所說的,你需要鍵值觀察。

[arrayController addObserver:self 
       forKeyPath:@"selection.isLocked" 
       options:NSKeyValueObservingOptionNew 
       context:@"this_context"] 

然後當isLocked改變-observeValueForKeyPath:ofObject變化:背景:您已經添加到您的viewController將被調用的方法(只要你只有在一個KVC兼容的方式操縱isLocked)。

通過options參數,您可以選擇精確地調整哪些條件將觸發通知以及哪些數據與通知一起發送。上下文參數可幫助您區分您註冊接收的通知和通知您的超類註冊接收的通知。這是可選的。

綁定似乎可能有助於保持兩個值同步。但是,這不是他們所做的

是的,許多事物似乎給人的印象是這是他們所做的事情,並沒有太多說這不是他們所做的事情,也有很多人認爲這是他們所做的 - 但不,你不能爲此使用它們。

只有一類支持綁定(少數they are listed here)然後,,這是最重要的一點,這些類只支持綁定自己命名綁定,並且這些綁定不是實例變量。例如的NSTextField有。「fontFamilyName」結合還的NSTextField 沒有一個「fontFamilyName」屬性或實例變量,甚至派生一個的NSTextField確實有一個「isBordered」財產,但不具有約束力的 - 所以你不能綁定「isBordered」

這並不意味着任何「綁定」任意類的任意屬性。

+0

非常感謝你的詳細解釋。如果我理解正確,我可以像這樣在我的ViewController類中實現所有這些:[[ArrayController selection] addObserver:self forKeyPath:@「selection」options:nil context:nil];然後實現方法: - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {[keyPath isEqualToString:@「selection.isLocked」 ] && object == ArrayController)[self setIsLocked:[object valueForKeyPath:keyPath]; } – BartoNaz 2011-04-05 04:19:52

+0

是的。 – hooleyhoop 2011-04-05 08:41:32

+0

對不起,這是完全錯誤的。綁定非常明確地允許你綁定任意類的任意屬性(參見我的答案中的代碼示例)。 – mpw 2014-03-15 08:25:45

1

是的,你可以綁定任意兩個值,下面的代碼工作得很好:

#import <Cocoa/Cocoa.h> 

@interface SomeObject : NSObject 

@property (retain,nonatomic) id someValue; 

@end 
@implementation SomeObject 

@end 

int main() 
{ 
    SomeObject *source=[SomeObject new]; 
    SomeObject *target=[SomeObject new]; 

    [target bind:@"someValue" toObject:source withKeyPath:@"someValue" options:0]; 
    [source bind:@"someValue" toObject:target withKeyPath:@"someValue" options:0]; 

    [source setSomeValue:@(42)]; 
    NSLog(@"target: %@",[target someValue]); 


    [target setSomeValue:@(22)]; 
    NSLog(@"source: %@",[source someValue]); 

    return 0; 
} 

據我所知道的,問題是位[ArrayController selection]。第一個問題是ArrayController是(或者應該是)一個類,而獲得該類的選擇可能毫無意義。另一個問題是,即使這是一個實例,在調用的時候你也會綁定到選擇上,這幾乎肯定不是你想要的。您想跟蹤當前選擇的變化。

所以,你想要什麼可能是類似以下內容:

[myViewController bind:@"value" toObject:myArrayController withKeyPath:@"selection.isLocked" options:nil];