2011-12-05 70 views
0

我有一個核心數據模型類與客戶ID屬性。它綁定到一個表格單元格。當用戶完成編輯文本時,我希望有機會將其條目轉換爲大寫,使用取決於舊值和新值的邏輯添加編輯行爲綁定NSFormCell

理想情況下,我想保持行爲接近它所屬的視圖,使用一個對象,我可以在筆尖實例化並連接到文本單元格。但是我會爲一個我不得不與模型掛鉤的物體而定居。

我這個執行三種不同的方式:

  1. 模型類定製的setter方法
  2. 文本編輯委託實施NSControlTextEditingDelegate
  3. 它使用志願要注意的變化,並啓動後續
  4. 輔助類更改

所有這三個實現都有問題。問題分別爲:

  1. 此行爲不屬於模型。例如,我應該能夠在代碼中設置屬性,而不會觸發它。
  2. 我無法獲得「before」值,因爲表格單元格不提供controlTextDidBeginEditing:調用(並且在調用controlTextDidEndEditing:之前舊值已消失)。此外,在沒有鍵入任何內容的情況下進入和退出該字段會觸發controlTextDidEndEditing:的呼叫。
  3. 當觀察觸發用戶的更改,並且我啓動對該屬性的後續更改時,該視圖忽略更改通知並且不重繪。 (我認爲活頁夾是爲了提高效率,通常在更新模型時,它可以忽略正在更新的字段中的KVO觀察結果。)

你會如何解決這個問題?

回答

0

some discussion here後,聽起來似乎有些方法可以做到壽:

  1. 放在模型類一個類別,並覆蓋validateMyKey
  2. 子類NSFormCell

我都嘗試。更多問題:

  1. validateMyKey直到模型自動更新後才被調用,因此舊值不可用。
  2. editWithFrame:inView:editor:delegate:event:在進入一個字段時並不總是被調用,所以很難訪問endEditing:中的舊值。

新解決方案是對我原來的#2:文本編輯委託實施NSControlTextEditingDelegate的改進。

而不是controlTextDidBeginEditing:controlTextDidEndEditing:,只實現control:textShouldEndEditing:。在該方法中,如有必要操作文本,然後返回YES。

我在筆尖實例化它,並使它成爲窗體的委託(而不是單元格)。在下面的代碼中,我使用infoForBinding:獲得舊值,但如果您未使用綁定,則可以將模型對象添加到插座中。

-(BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor { 
    NSCell *cell = [(NSForm *)control selectedCell]; 
    NSString *identifier = [(NSCell *)[(NSForm *)control selectedCell] identifier]; 
    if (!identifier) return YES; 

    NSDictionary *bindingInfo = [cell infoForBinding:@"value"]; 
    if (!bindingInfo) return YES; 
    NSString *oldValue = [[bindingInfo valueForKey:NSObservedObjectKey] valueForKeyPath:[bindingInfo valueForKey:NSObservedKeyPathKey]]; 

    NSString *newValue = cell.stringValue; 

    if ([identifier isEqualTo:@"firstField"]) { 
     if (criteria) 
      cell.stringValue = ....; 

    } else if ([identifier isEqualTo:@"secondField"]) { 
     if (criteria) 
      cell.stringValue = ....; 
    } 

    return YES; 
}