Rinalds Domanovs
Rinalds Domanov's Blog

Rinalds Domanov's Blog

Creating in SwiftUI UITextField Representable

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.

  1. Open Xcode.
  2. Choose an App template for your new project. New project
  3. Create project name and make sure that you have selected SwiftUI interface and life cycle. Project name

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.

  1. Create new file Command + N Create new file
  2. Save as URLTextField.swift Save as URLTextField.swift

Now create URLTextField struct that conforms to UIViewRepresentable protocol and don't forget to import SwiftUI framework for the protocol.

{% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=URLTextField_1.swift %}

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 our text field
  • updateUIView() - it's called whenever data in our text field will be changed

{% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=URLTextField_2.swift %}

Actually we can already use this component in our SwiftUI view. Let's add it to ContentView.swift file.

{% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=ContentView_1.swift %} URLTextField 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.

{% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=URLTextField_3.swift %}

And update our ContentView.swift file. Add @State property wrapper and pass it to our URLTextField in order to track typed text. {% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=ContentView_2.swift %}

It looks good, we have @State property wrapper that is passed to our URLTextField @Binding. {% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=URLTextField_4.swift %}

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. {% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=URLTextField_5.swift %}

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.

{% gist gist.github.com/Sangsom/24c3dc68b371fe84757.. file=URLTextField_6.swift %}

And here you can see result. URLTextField

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.

 
Share this