Skip to content

Instantly share code, notes, and snippets.

@diamantidis
Created June 21, 2020 12:59
Show Gist options
  • Save diamantidis/061d101853f6400f76780345614b2c90 to your computer and use it in GitHub Desktop.
Save diamantidis/061d101853f6400f76780345614b2c90 to your computer and use it in GitHub Desktop.
A SwiftUI field with a UIPickerView as a keyboard
import SwiftUI
struct ContentView: View {
@State var selectedIndex: Int? = nil
let options: [String] = ["Option1", "Option2"]
var body: some View {
PickerField("Select an option", data: self.options, selectionIndex: self.$selectedIndex)
}
}
import SwiftUI
struct PickerField: UIViewRepresentable {
// MARK: - Public properties
@Binding var selectionIndex: Int?
// MARK: - Initializers
init<S>(_ title: S, data: [String], selectionIndex: Binding<Int?>) where S: StringProtocol {
self.placeholder = String(title)
self.data = data
self._selectionIndex = selectionIndex
textField = PickerTextField(data: data, selectionIndex: selectionIndex)
}
// MARK: - Public methods
func makeUIView(context: UIViewRepresentableContext<PickerField>) -> UITextField {
textField.placeholder = placeholder
return textField
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<PickerField>) {
if let index = selectionIndex {
uiView.text = data[index]
} else {
uiView.text = ""
}
}
// MARK: - Private properties
private var placeholder: String
private var data: [String]
private let textField: PickerTextField
}
import SwiftUI
class PickerTextField: UITextField {
// MARK: - Public properties
var data: [String]
@Binding var selectionIndex: Int?
// MARK: - Initializers
init(data: [String], selectionIndex: Binding<Int?>) {
self.data = data
self._selectionIndex = selectionIndex
super.init(frame: .zero)
self.inputView = pickerView
self.tintColor = .clear
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Private properties
private lazy var pickerView: UIPickerView = {
let pickerView = UIPickerView()
pickerView.delegate = self
pickerView.dataSource = self
return pickerView
}()
// MARK: - Private methods
@objc
private func donePressed() {
self.selectionIndex = self.pickerView.selectedRow(inComponent: 0)
self.endEditing(true)
}
}
// MARK: - UIPickerViewDataSource & UIPickerViewDelegate extension
extension PickerTextField: UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.data.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return self.data[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.selectionIndex = row
}
}
@michael94ellis
Copy link

override func caretRect(for position: UITextPosition) -> CGRect {
.null
}

This will truly make it unselectable! Relevant StackOverflow post: https://stackoverflow.com/questions/32846678/how-to-disable-the-selection-of-a-uitextfield/62754240#62754240

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment