Creating in SwiftUI UITextField Representable
Tags: swift, swiftui, ios
Published: 2021-04-21 02:25:02

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](https://i.imgur.com/INpWyix.png)
3. Create project name and make sure that you have selected `SwiftUI` interface and life cycle.
![Project name](https://i.imgur.com/3WsBSd8.png)

## 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](https://i.imgur.com/ROIzyQD.png)
2. Save as `URLTextField.swift`
![Save as URLTextField.swift](https://i.imgur.com/uE2qq8P.png)

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

{% gist https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb 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 https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb file=URLTextField_2.swift %}

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

{% gist https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb file=ContentView_1.swift %}
![URLTextField](https://i.imgur.com/YpIbqo7.png)
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 https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb 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 https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb file=ContentView_2.swift %}

It looks good, we have `@State` property wrapper that is passed to our `URLTextField` `@Binding`. 
{% gist https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb 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 https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb 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 https://gist.github.com/Sangsom/24c3dc68b371fe8475796735905777eb file=URLTextField_6.swift %}

And here you can see result.
![URLTextField](https://media.giphy.com/media/OC9nORubT4NJbMHwN8/giphy.gif)

## 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](https://twitter.com/domanovdev).
Link on full project code on [GitHub](https://github.com/Sangsom/URLTextField-Representable).