Sử dụng `textField: ShouldChangeChar characterInRange:`, làm cách nào để tôi có được văn bản bao gồm ký tự được nhập hiện tại?


116

Tôi đang sử dụng mã bên dưới để thử và có textField2nội dung văn bản được cập nhật để khớp với textField1bất cứ khi nào người dùng nhập vào textField1.

- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {    
  if (theTextField == textField1){    
     [textField2 setText:[textField1 text]];    
  }
}

Tuy nhiên, đầu ra tôi quan sát là ...

textField2 là "12", khi textField1 là "123"

textField2 là "123", khi textField1 là "1234"

... khi điều tôi muốn là:

textField2 là "123", khi textField1 là "123"

textField2 là "1234", khi textField1 là "1234"

Tôi đang làm gì sai?


8
Chỉ cần một lời nhắc nhở là dễ dàng hơn đáng kinh ngạc khi luôn luôn sử dụng sự kiện "Chỉnh sửa thay đổi" .. chỉ cần kéo nó trong IB đến một chức năng bạn thực hiện.
Fattie

Lưu ý rằng sự kiện thay đổi chỉnh sửa không nắm bắt bất kỳ sự kiện thay đổi văn bản nào được tạo theo chương trình, ví dụ: tự động sửa / tự động hoàn thành / thay thế văn bản.
shim

Câu trả lời:


272

-shouldChangeCharactersInRangeđược gọi trước khi trường văn bản thực sự thay đổi văn bản của nó, đó là lý do tại sao bạn nhận được giá trị văn bản cũ. Để có được văn bản sau khi cập nhật sử dụng:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];

15
Điều này gần như làm việc cho tôi. Nếu tôi gõ một ký tự, điều này làm việc. Nếu tôi nhấn nút xóa, nó sẽ xóa hai ký tự. Đối với tôi, đề xuất sau đã có hiệu quả: stackoverflow.com/questions/388237/ , Về cơ bản, hãy kéo từ UITextField vào mã của bạn (để tạo hàm), sau đó nhấp chuột phải vào TextField của bạn và kéo ' thả từ vòng tròn cho "Chỉnh sửa thay đổi" sang chức năng mới của bạn. (Thở dài. Đôi khi tôi nhớ Visual Studio ..)
Mike Gledhill

Tôi cũng cảm thấy đây là một câu trả lời hợp lệ, nhưng không phải là câu trả lời. Cách tốt nhất để thực hiện những gì bạn muốn đã được trả lời bởi @tomute
Pedro Borges

5
Hoặc textFiel.text = (textFiel.text như NSString) .stringByReplacingCharactersInRange (phạm vi, withString: string) trong Swift
Max

@MikeGledhill Bạn có thể làm điều tương tự theo chương trình:[textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]
Steve Moser

52
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    NSLog(@"%@",searchStr);
    return YES;
}

40

Swift 3

Dựa trên câu trả lời được chấp nhận, những điều sau đây sẽ hoạt động trong Swift 3 :

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)

    return true
}

Ghi chú

Cả hai StringNSStringcó phương thức gọi replacingCharacters:inRange:withString. Tuy nhiên, như mong đợi, cái trước mong đợi một thể hiện của Range, trong khi cái sau mong đợi một thể hiện của NSRange. Các textFieldphương pháp đại biểu sử dụng một NSRangeví dụ, do đó việc sử dụng NSStringtrong trường hợp này.


replacingCharactersnên làstringByReplacingCharactersInRange
Alan Scarpa

1
@Alan_s Tôi đã sao chép đoạn mã này trực tiếp từ dự án Xcode của mình và nó hoạt động tốt. Bạn có đang sử dụng Xcode 8.1 với mục tiêu đến iOS 10.1 không?
trung vào


13

Trong Swift (4), không có NSString(Swift thuần túy):

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if let textFieldString = textField.text, let swtRange = Range(range, in: textFieldString) {

        let fullString = textFieldString.replacingCharacters(in: swtRange, with: string)

        print("FullString: \(fullString)")
    }

    return true
}

Là một phần mở rộng:

extension UITextField {

    func fullTextWith(range: NSRange, replacementString: String) -> String? {

        if let fullSearchString = self.text, let swtRange = Range(range, in: fullSearchString) {

            return fullSearchString.replacingCharacters(in: swtRange, with: replacementString)
        }

        return nil
    }
}

// Usage:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if let textFieldString = textField.fullTextWith(range: range, replacementString: string) {
        print("FullString: \(textFieldString)")
    }

    return true
}

8

Phiên bản Swift cho nó:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    if string == " " {
        return false
    }

    let userEnteredString = textField.text

    var newString = (userEnteredString! as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString

    print(newString)

    return true
}

5

Đây là mã bạn cần,

if ([textField isEqual:self.textField1])
  textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];

1

sử dụng bảo vệ

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        guard case let textFieldString as NSString = textField.text where
            textFieldString.stringByReplacingCharactersInRange(range, withString: string).length <= maxLength else {
                return false
        }
        return true
    }

0

Giải pháp của tôi là sử dụng UITextFieldTextDidChangeNotification.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(copyText:) name:UITextFieldTextDidChangeNotification object:nil];

Đừng quên gọi [[NSNotificationCenter defaultCenter] removeObserver:self];theo deallocphương thức.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.