How to detect when a TextField loses the focus in SwiftUI for iOS?

Viewed 18769
TextField("Name", text: $name)

I found this method

func focusable(_ isFocusable: Bool = true, onFocusChange: @escaping (Bool) -> Void = { _ in }) -> some View

but it's only available for MacOS, How could I do something similar for iOS ?

3 Answers

You can use the initializer init(_:text:onEditingChanged:onCommit:) present in textfield. There you will be getting an action triggered when you begin editing and end editing. You can find out the minimal example below.

import SwiftUI

struct ContentView: View {
    @State private var greeting: String = "Hello world!"
    var body: some View {
        TextField("Welcome", text: $greeting, onEditingChanged: { (editingChanged) in
            if editingChanged {
                print("TextField focused")
            } else {
                print("TextField focus removed")
            }
        })
    }
}

Hope this helps.

iOS 15+

In iOS 15 we can detect changes with @FocusState:

@FocusState private var isFocused: Bool
...

var body: some View {
    Form {
        TextField("Name", text: $name)
            .focused($isFocused)
            .onChange(of: isFocused) { isFocused in
                // ...
            }
    }
}

This solution works for me. If you have in the app few types of textFields you easily can reuse this code and modify. Focus will work only for current field, since you can't take in focus more then one field - it's a good solution. (Tested in Xcode 13.2)

struct MyTextField: View {
    
    let placeholder: String
    
    @FocusState private var focusState: Bool
    
    @Binding var text: String
    @Binding var enabled: Bool
    
    @State private var isFocused: Bool = false
    
    var body: some View {
        TextField(placeholder, text: $text)
            .focused($focusState)
            .onChange(of: focusState, perform: { newValue in
                print(newValue)
                isFocused = newValue
            })
    }
}
Related