2009-02-09 43 views
5

Tôi đang cố sử dụng NSTextField cho đầu vào số nguyên của người dùng. Trường văn bản được liên kết với thuộc tính NSNumber và trong phương thức setter, tôi dọn sạch giá trị đầu vào (đảm bảo rằng nó là một int) và thiết lập thuộc tính nếu cần thiết. Tôi gửi willChangeValueForKey: và didChangeValueForKey :, nhưng giao diện người dùng không cập nhật các giá trị mới trong khi trường văn bản đó vẫn hoạt động.ràng buộc NSTextField với NSNumber

Vì vậy, ví dụ tôi có thể nhập "12abc" trong trường văn bản mà phương thức setter dọn dẹp thành "12", nhưng trường văn bản vẫn hiển thị "12abc".

Tôi đã chọn "Cập nhật giá trị liên tục" trong trình tạo giao diện.

(Tôi cũng đã nhận thấy rằng phương pháp setter nhận được một NSString, không phải là một NSNumber. Có phải đó là bình thường không?)

cách chính xác của hooking lên một NSTextField một NSNumber là gì? Phương thức setter trông như thế nào cho thuộc tính? Làm cách nào để ngăn các giá trị không phải số hiển thị trong trường văn bản?

Trả lời

0

Tôi nghĩ bạn cần thiết lập trình định dạng số cho số NSTextField của mình.

Đọc đọc về các trình định dạng trên trang web của Apple: Applying Formatters.

+0

tôi đã thêm một định dạng số bằng cách thả nó trên các lĩnh vực văn bản như đề xuất trong doc bạn chỉ ra, nhưng không có gì xảy ra. Tôi vẫn có thể nhập ký tự không phải số. Tôi có cần phải làm bất cứ điều gì khác ngoài việc kết nối trình định dạng với trường văn bản không? – lajos

1

Giống như Ben đã đề cập, một cách để thực hiện việc này là đính kèm NSNumberFormatter vào trường văn bản của bạn, khá tầm thường để thiết lập trong trình tạo giao diện và có khả năng là Just Work ™.

Nếu bạn không thích các hộp thoại phương thức NSNumberFormatter ném vào người dùng của bạn khi họ nhập giá trị không phải số, bạn có thể phân lớp NSNumberFormatter để triển khai hành vi định dạng khác, ‘tha thứ hơn’. Tôi nghĩ rằng trọng số - numberFromString: để loại bỏ các ký tự không phải là số trước khi gọi thực hiện của siêu nên làm các trick.

Cách tiếp cận khác là tạo và đăng ký lớp con NSValueTransformer của riêng bạn để phân tích chuỗi thành NSNumbers và ngược lại, nhưng tôi sẽ thử sử dụng NSNumberFormatter trước vì nó khá rõ ràng lớp đã được thiết kế cho mục đích chính xác này.

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.

Có rất ít lý do để gửi những thông điệp. Thông thường, bạn có thể làm cùng một công việc tốt hơn và sạch hơn bằng cách triển khai và sử dụng các trình truy cập (hoặc, tốt hơn, các thuộc tính). KVO sẽ gửi thông báo cho bạn khi bạn làm điều đó.

Trong trường hợp của bạn, bạn muốn từ chối hoặc lọc các đầu vào không có thật (như “12abc”). Công cụ chính xác cho tác vụ này là Xác thực giá trị khóa.

Để bật tính năng này, hãy chọn hộp "Xác thực ngay lập tức" trên liên kết trong IB và triển khai phương pháp xác thực.

Filtering:

- (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); 
} 

Từ chối:

- (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?)

Có, trừ khi bạn sử dụng một máy biến áp giá trị mà biến đổi chuỗi thành số, kết nối một định dạng số vào ổ formatter, hoặc thay thế một NSNumber cho NSString trong phương thức xác thực của bạn.

+0

Các phương thức xác thực dường như có chữ ký: - (BOOL) xác thựcNewValue: (id *) Lỗi ioValue: (NSError **) outError; Nhưng ngay cả khi tôi triển khai phương thức có chữ ký chính xác và trả về KHÔNG hoặc sửa giá trị, trường văn bản vẫn hiển thị các ký tự không phải số. – lajos

+0

Cảm ơn bạn đã lưu ý về chữ ký của phương thức — Tôi đã sửa câu trả lời của mình. Bạn đã chọn hộp "Xác thực ngay lập tức" chưa? Tôi không chắc những gì khác có thể là vấn đề, mà không nhìn thấy mã. –

+0

Tôi đã đăng dự án thử nghiệm tại đây: www.codza.com/files/numericFieldTest.zip Phương thức xác thực trả về CÓ hoặc KHÔNG (xem nhật ký), nhưng trường văn bản vẫn hiển thị ký tự alpha. Cảm ơn rất nhiều vì đã xem xét điều này. Bạn có thể liên hệ với tôi tại www.codza.com/contact và tôi cũng sẽ kiểm tra các ý kiến ​​ở đây. – lajos

2

Có một nhận xét quan trọng về câu trả lời tuyệt vời của Peter Hosey rằng tôi muốn đưa lên cấp cao nhất (vì tôi đã bỏ lỡ nó trong lần vượt qua đầu tiên).

Nếu bạn muốn xác thực/sửa đổi NSTextField mỗi lần nhập ký tự, thay vì chỉ khi người dùng gửi trường, thì bạn không thể có được những gì bạn muốn từ các ràng buộc. Bạn cần gán một đại biểu cho trường văn bản, và sau đó thực hiện - (void)controlTextDidChange:(NSNotification *)aNotification trong ủy nhiệm. Điều này sẽ được gọi mỗi khi văn bản thay đổi. Nếu muốn, bạn có thể gọi trình xác thực giá trị trong controlTextDidChange.

Ví dụ:

- (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]; 
} 
Các vấn đề liên quan