2009-02-09 114 views
5

我正在嘗試爲整數用戶輸入使用NSTextField。文本字段綁定到一個NSNumber屬性,在setter方法中,我清理輸入值(確保它是一個int),並在必要時設置屬性。我發送了willChangeValueForKey:和didChangeValueForKey :,但該UI不會更新爲新值,而該文本字段仍處於活動狀態。將NSTextField綁定到NSNumber

因此,例如,我可以在setter方法清除爲「12」的文本字段中鍵入「12abc」,但文本字段仍顯示「12abc」。

我有「連續更新值」在界面生成器中檢查。

(我也注意到,setter方法接受一個NSString,而不是一個NSNumber。那是正常的嗎?)

什麼是的NSTextField掛接到一個NSNumber的正確方法是什麼? setter方法對於屬性是什麼樣的?如何防止在文本字段中顯示非數字值?

回答

0

我認爲你需要設置一個數字格式到你的NSTextField

請閱讀Apple網站上的格式化程序:Applying Formatters

+0

我掉到地上的文本字段添加了一個數字格式化爲你指出的文檔建議,但沒有任何反應。我仍然可以鍵入非數字字符。除了將格式器連接到文本字段之外,我還需要做什麼? – lajos 2009-02-09 17:23:18

1

像Ben提到的那樣,一種方法是將一個NSNumberFormatter附加到您的文本框中,這對於在界面構建器中設置非常簡單,並且很可能是Just Work™。

如果您不喜歡模式對話框NSNumberFormatter在用戶輸入非數值時拋出,您可以繼承NSNumberFormatter以實現不同的「更寬容」格式化行爲。我認爲重寫 - numberFromString:在調用超級實現之前去除非數字字符應該做的伎倆。

另一種方法是創建並註冊您自己的NSValueTransformer子類,以便將字符串解析爲NSNumbers並返回,但是我會嘗試先使用NSNumberFormatter,因爲它非常清楚地是爲此目的而設計的類。

More about value transformers

10

I send the willChangeValueForKey: and didChangeValueForKey:, but the UI doesn't update to the new values while that text field is still active.

有發送這些消息很少的原因。通常,通過實現和使用訪問器(或更好的屬性),您可以更好,更乾淨地完成同樣的工作。 KVO會在你這樣做的時候爲你發送通知。

在你的情況下,你想要拒絕或過濾虛假輸入(如「12abc」)。此任務的正確工具是鍵值驗證。

要啓用此功能,請檢查IB中綁定的「立即驗證」框,並實施驗證方法。

過濾:

- (BOOL) validateMyValue:(inout NSString **)newValue error:(out NSError **)outError { 
    NSString *salvagedNumericPart; 
    //Determine whether you can salvage a numeric part from the string; in your example, that would be 「12」, chopping off the 「abc」. 
    *newValue = salvagedNumericPart; //@"12" 
    return (salvagedNumericPart != nil); 
} 

拒絕:

- (BOOL) validateMyValue:(inout NSString **)newValue error:(out NSError **)outError { 
    BOOL isEntirelyNumeric; 
    //Determine whether the whole string (perhaps after stripping whitespace) is a number. If not, reject it outright. 
    if (isEntirelyNumeric) { 
     //The input was @"12", or it was @" 12 " or something and you stripped the whitespace from it, so *newValue is @"12". 
     return YES; 
    } else { 
     if (outError) { 
      *outError = [NSError errorWithDomain:NSCocoaErrorDomain code: NSKeyValueValidationError userInfo:nil]; 
     } 
     //Note: No need to set *newValue here. 
     return NO; 
    } 
} 

(I've also noticed that the setter method receives an NSString, not an NSNumber. Is that normal?)

是的,除非你使用值轉換器是轉換字符串到數字,一個數字格式化連接到formatter出口,或替代驗證方法中的NSString的NSNumber。

+0

驗證方法似乎有以下簽名: - (BOOL)validateNewValue:(id *)ioValue error:(NSError **)outError; 但即使我使用正確的簽名實現方法並返回NO或更正值,文本字段仍顯示非數字字符。 – lajos 2009-02-09 17:09:35

2

Peter Hosey的優秀答案有一個重要的評論,我想提高到最高水平(因爲我第一次錯過了)。

如果您想在每次輸入字符時驗證/修改NSTextField,而不是僅當用戶提交該字段時,則無法單獨獲得您想要的綁定。您需要將委派分配給文本字段,然後在委託中實施- (void)controlTextDidChange:(NSNotification *)aNotification。每次文本更改時都會調用它。如果需要,可以撥打controlTextDidChange中的值驗證器。

例如:

- (void)controlTextDidChange:(NSNotification *)aNotification 
{ 
    NSError *outError; 
    NSControl *textField = [aNotification object]; 
    NSString *myText = [textField stringValue]; 

    // myObject is the model object that owns the text in question 
    // the validator can modify myText by reference 
    [myObject validateValue:&myText error:&outError]]; 

    // update the NSNextField with the validated text 
    [postingObject setStringValue:myText]; 
} 
相關問題