Lấy và thiết lập vị trí con trỏ của UITextField và UITextView trong Swift


109

Tôi đã thử nghiệm UITextFieldvà cách làm việc với vị trí con trỏ của nó. Tôi đã tìm thấy một số câu trả lời Objective-C quan hệ, như trong

Nhưng vì tôi đang làm việc với Swift nên tôi muốn học cách lấy vị trí con trỏ hiện tại và cũng đặt nó trong Swift.

Câu trả lời dưới đây là kết quả của quá trình thử nghiệm và dịch từ Objective-C của tôi.

Câu trả lời:


316

Nội dung sau đây áp dụng cho cả UITextFieldUITextView.

Thông tin hữu ích

Phần đầu của văn bản trường văn bản:

let startPosition: UITextPosition = textField.beginningOfDocument

Phần cuối của văn bản trường văn bản:

let endPosition: UITextPosition = textField.endOfDocument

Phạm vi hiện được chọn:

let selectedRange: UITextRange? = textField.selectedTextRange

Nhận vị trí con trỏ

if let selectedRange = textField.selectedTextRange {

    let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)

    print("\(cursorPosition)")
}

Đặt vị trí con trỏ

Để thiết lập vị trí, tất cả các phương pháp này thực sự đang thiết lập một phạm vi có cùng giá trị bắt đầu và giá trị kết thúc.

Cho tới khi bắt đầu

let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)

Đến cuối cùng

let newPosition = textField.endOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)

Đến một vị trí bên trái vị trí con trỏ hiện tại

// only if there is a currently selected range
if let selectedRange = textField.selectedTextRange {

    // and only if the new position is valid
    if let newPosition = textField.position(from: selectedRange.start, offset: -1) {

        // set the new position
        textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
    }
}

Đến một vị trí tùy ý

Bắt đầu từ đầu và di chuyển 5 ký tự sang bên phải.

let arbitraryValue: Int = 5
if let newPosition = textField.position(from: textField.beginningOfDocument, offset: arbitraryValue) {

    textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}

Có liên quan

Chọn tất cả văn bản

textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)

Chọn một loạt văn bản

// Range: 3 to 7
let startPosition = textField.position(from: textField.beginningOfDocument, offset: 3)
let endPosition = textField.position(from: textField.beginningOfDocument, offset: 7)

if startPosition != nil && endPosition != nil {
    textField.selectedTextRange = textField.textRange(from: startPosition!, to: endPosition!)
}

Chèn văn bản ở vị trí con trỏ hiện tại

textField.insertText("Hello")

Ghi chú

  • Sử dụng textField.becomeFirstResponder()để tạo tiêu điểm cho trường văn bản và làm xuất hiện bàn phím.

  • Xem câu trả lời này để biết cách lấy văn bản ở một số phạm vi.

Xem thêm


Mục đích của startPosition là gì? bạn có thể làm gì với nó? Ngoài ra, mục đích mà người ta có thể cần để có được vị trí con trỏ là gì?
Honey,

2
@Honey, tôi đã sử dụng tên biến đó để chỉ hai thứ khác nhau ở đây. Đầu tiên là tham chiếu đến phần đầu của trường văn bản. Nó sẽ hữu ích nếu bạn muốn di chuyển con trỏ đến đó. Thứ hai là đề cập đến việc cầu xin một loạt văn bản đã chọn. Sẽ rất hữu ích nếu bạn muốn sao chép phạm vi đó hoặc đặt một số thuộc tính trên đó.
Suragch

Có gì để di chuyển con trỏ sang phải trong khi trường văn bản trống không? Tôi đã làm theo câu trả lời của bạn nhưng tôi không thể làm được.
Yucel Bayram

1
@yucelbayram, Bạn có thể đặt con trỏ sau chữ H bằng cách sử dụng textField.endOfDocument. Bạn cũng có thể sử dụng dấu gạch dưới hoặc dấu cách để thể hiện các chữ cái còn thiếu.
Suragch

1
@ArielSD, tôi xin lỗi, tôi đã không làm việc này trong một thời gian. Tôi không thể nhớ.
Suragch

42

trong trường hợp của tôi, tôi phải sử dụng DispatchQueue:

func textViewDidBeginEditing(_ textView: UITextView) {

   DispatchQueue.main.async{
      textField.selectedTextRange = ...
   }
}

không có gì khác từ điều này và các chủ đề khác hoạt động.

Tái bút: Tôi đã kiểm tra kỹ luồng textViewDidBeginE Chỉnh sửa đang chạy trên luồng nào và đó là luồng chính, vì tất cả giao diện người dùng sẽ chạy trên đó, vì vậy không chắc tại sao độ trễ nhỏ đó khi sử dụng main.asynch lại hoạt động.


2
Đó không phải là sự chậm trễ mà là vòng lặp chạy tiếp theo. Nhiều khả năng phạm vi đã chọn của trường văn bản đang được sửa đổi bởi cùng một hàm đã gọi textViewDidBeginEditing. Vì vậy, bằng cách đặt nó vào hàng đợi, nó sẽ xảy ra sau khi người gọi kết thúc.
Michael Ozeryansky

@MichaelOzeryansky Vâng, tôi cũng nghĩ vậy. Nhưng điều này đặt ra câu hỏi - phương pháp phù hợp để đặt vị trí con trỏ theo cách thủ công là gì?
timetowonder 19/09/19

cũng giải pháp này trong trường hợp của tôi
Hattori Hanzō

1

Để đặt vị trí con trỏ tại điểm của bạn:

textView.beginFloatingCursor(at: CGPoint(x: 10.0, y: 10.0))

Để đặt lại vị trí con trỏ:

textView.endFloatingCursor()

Lưu ý : Ví dụ này hoạt động trong cả Textview & Textfield.


@Suragch Floating Cursor là một phương pháp để đặt vị trí con trỏ trong textView hoặc textField.
Parth Patel

1
let range = field.selectedTextRange

field.text = "hello world"

field.selectedTextRange = range 
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.