简体   繁体   English

防止在 Swift 中编辑 UITextField 而不是用户交互

[英]Prevent editing UITextField but not the user interaction in Swift

I want to know how to prevent a user from edition a UITextField but not the user interaction.我想知道如何防止用户编辑 UITextField 而不是用户交互。 What I want to do here is when the user taps on the text field a UIPickerView pops up from the bottom and the user can select an item from the picker view and display it on the text field.我想在这里做的是当用户点击文本字段时,UIPickerView 从底部弹出,用户可以从选择器视图中选择一个项目并将其显示在文本字段上。 But I don't want the user to be able to edit the text field.但我不希望用户能够编辑文本字段。 I want to do this for the class below.我想为下面的班级做到这一点。

import UIKit

typealias PickerTextFieldDisplayNameHandler = ((Any) -> String)
typealias PickerTextFieldItemSelectionHandler = ((Int, Any) -> Void)

class PickerTextField: UITextField {

    private let pickerView = UIPickerView(frame: .zero)
    private var lastSelectedRow: Int?
    
    public var pickerData: [Any] = []
    public var displayNameHandler: PickerTextFieldDisplayNameHandler?
    public var itemSelectionHandler: PickerTextFieldItemSelectionHandler?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.configureView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.configureView()
    }
    
    override func caretRect(for position: UITextPosition) -> CGRect {
        return .zero
    }
    
    
    
    private func configureView() {
        self.pickerView.delegate = self
        self.pickerView.dataSource = self
        self.inputView = pickerView
        
        let toolbar = UIToolbar()
        toolbar.barStyle = .default
        toolbar.sizeToFit()
        
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneButtonTapped))
        toolbar.setItems([spaceButton, doneButton], animated: false)
        
        self.inputAccessoryView = toolbar
    }
    
    private func updateText() {
        if self.lastSelectedRow == nil {
            self.lastSelectedRow = 0
        }
        if self.lastSelectedRow! > self.pickerData.count {
            return
        }
        let data = self.pickerData[self.lastSelectedRow!]
        self.text = self.displayNameHandler?(data)
    }
    
    @objc func doneButtonTapped() {
        self.updateText()
        self.resignFirstResponder()
    }
    
}

extension PickerTextField: UIPickerViewDelegate {
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        let data = self.pickerData[row]
        return self.displayNameHandler?(data)
    }
}

extension PickerTextField: UIPickerViewDataSource {
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return self.pickerData.count
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        self.lastSelectedRow = row
        self.updateText()
        let data = self.pickerData[row]
        self.itemSelectionHandler?(row, data)
    }
}

From my understanding you want to achieve the following behavior:据我了解,您希望实现以下行为:

  1. You would like to show the what the user selected in a picker view inside a textfield.您想显示用户在文本字段内的选择器视图中选择的内容。
  2. But you don't want the user to change the text after the text has been inserted in the textfield.但是您不希望用户在文本字段中插入文本后更改文本。

I would use the delegate methods of UITextField and UIPickerView .我会使用UITextFieldUIPickerView的委托方法。 There is a method in UIPickerViewDelegate that lets you know which row was selected by the user: UIPickerViewDelegate中有一个方法可以让您知道用户选择了哪一行:

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    textField.text = "Hello \(row)"
}

Here you would set the text to the textfield which solves (1).在这里,您可以将文本设置为解决 (1) 的文本字段。

And also you can use the method in UITextFieldDelegate that allows you to prevent user input into the textfield.您还可以使用UITextFieldDelegate中的方法来阻止用户输入文本字段。

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

This prevents the user from typing anything into the textfield.这可以防止用户在文本字段中输入任何内容。 This solves (2).这解决了(2)。 However, the cursor will still be showing which might confuse the user.但是,光标仍会显示,这可能会使用户感到困惑。 He might think he can enter something into the textfield from the cursor blinking when he actually can't.他可能认为他可以通过闪烁的光标在文本字段中输入内容,而实际上他不能。

And of course you have to make the inputView of textfield to your custom picker view like so:当然,您必须将 textfield 的inputView设置为您的自定义选择器视图,如下所示:

textField.inputView = myPickerView

I hope this answers your question :)我希望这回答了你的问题 :)

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM