There may be cases when you would like bigger control over the TextField
that you are adding in your app. Of course in most cases it's completely fine and enough to use SwiftUI Textfield
, but I recently needed to create a UITextField
representable and to be honest it wasn't so easy to do initially. So I want to share what I did in order to get working solution.
Result
For the tutorial we will create a custom URLTextField
that will be used in SwiftUI
app and is a UIViewRepresentable
of UITextField
.
Project
Let's start with creating project.
- Open Xcode.
- Choose an
App
template for your new project. - Create project name and make sure that you have selected
SwiftUI
interface and life cycle.
URLTextField
Now let's make URLTextField
component that will be conforming to UIViewRepresentable
protocol that is a wrapper for UIKit
view which allows us to integrate that view into our SwiftUI
.
- Create new file
Command + N
- Save as
URLTextField.swift
Now create URLTextField
struct that conforms to UIViewRepresentable
protocol and don't forget to import SwiftUI
framework for the protocol.
Good, now we have error:
Type 'URLTextField' does not conform to protocol 'UIViewRepresentable'
.
So now to satisfy UIViewRepresentable
protocol requirements we need to implement two methods:
-
makeUIView()
- here we will create ourtext field
-
updateUIView()
- it's called whenever data in our text field will be changed
Actually we can already use this component in our SwiftUI
view. Let's add it to ContentView.swift
file.
Nice, we have a
UITextField
that is configured for typing URLs, but we need something more. We want it to have a
SwiftUI
functionality that allows us to store its value into @State
property wrapper and update it accordingly.Sounds simple, let's create
@Binding
property wrapper inside our URLTextField
struct that will store and update text value. And we can use now our updateUIView
method for updating our view as it should do.
And update our ContentView.swift
file. Add @State
property wrapper and pass it to our URLTextField
in order to track typed text.
It looks good, we have @State
property wrapper that is passed to our URLTextField
@Binding
.
But we still need one more thing, we need to create a delegate
and in order to communicate with our view we need to implement a Coordinator
instance.
Basically in Coordinator
you will create all UITextFieldDelegate
methods that are communicated through makeCoordinator()
method that is required now. And of course set the delegate
property to context.coordinator
.
Quite a lot of steps to be done and still not finished yet. Now the last part. We need to add one more @Binding
method for tracking URLTextField
text and we need to update that text manually through textFieldDidChangeSelection()
delegate method. And also we need to use DispatchQueue
in our textFieldDidChangeSelection()
method or we will get an error while typing.
Modifying state during view update, this will cause undefined behavior.
So there is finished code you can use for such cases.
Final thoughts
Of course it's a lot of code just for creating TextField
and as I mentioned previously for the most time you probably will be good for using SwiftUI TextField
, but when I had a need to create more advanced UITextField
where I can have a full power of UITextField
delegate methods it wasn't so easy to understand for me how to implement it. So I wanted to write about it and strenghten my understanding on using UIViewRepresentable
protocol.
Any critique, comments are highly welcome.
Follow on Twitter.
Link on full project code on GitHub.
Top comments (0)