0

I am using swiftUI. And I used NotificationCenter to move textfield when keyboard appears by using keyboardWillShowNotification and keyboardWillHideNotification. But every time I touch textfield and call keyboard, keyboardWillShowNotification is sended twice but keyboardWillHideNotification is sended only once. And I can't find reason for it

The code of custom view that I have problem is below

import SwiftUI
import Combine

class KeyboardObserver:ObservableObject{
    @Published var activeState:Bool = false
    var subscribeCount = 0
    func setNotification(){
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object:nil)
        subscribeCount += 1
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc func keyboardWillShow(notification: Notification){
        print("before appear state: \(activeState), subCount: \(subscribeCount)")
        activeState = true
        print("after appear state: \(activeState), subCount: \(subscribeCount)")
    }

    @objc func keyboardWillHide(notification: Notification){
        activeState = false
        print("disappear state: \(activeState), subCount: \(subscribeCount)")
    }
}

struct MovingTextfield: View {
    @State var active: Bool = false
    @ObservedObject var observer = KeyboardObserver()
    @Binding var keywordValue: String
    
    var body: some View {
        VStack{
            
            Text("\(active)")
            Text("\(observer.activeState)")
            
            HStack{
                Spacer()
                TextField("\(Text("text input").font(.title))", text: $keywordValue)
                    .foregroundStyle(.black).font(.title)
                    .multilineTextAlignment(.center)
                    .disableAutocorrection(true)
                    
                Spacer()
            }
        }
            .onAppear{
                observer.setNotification()
                print("setting complete")
            }
    }
}

And ContentView is below

import SwiftUI

struct ContentView: View {
    @State var keywordValue = "ABCDEFG"
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
            MovingTextfield(keywordValue: $keywordValue)
        }
        .padding()
    }
}

#Preview {
    ContentView()
}

I found out that keyboardWillShowNotification is called twice. since the selected that I named keyboardWillShow was called twice. And I could not go further.

2
  • It may not solve your issue, but you should never use @ObservedObject where you own the object -- it should be @StateObject
    – jnpdx
    Commented Jul 10 at 2:32
  • Could not replicate your issue, the keyboardWillShow is only called once in my tests. On MacOS 15, Xcode 16, target iOS-18, tested on real ios device. Note, as mentioned you should use @StateObject private var observer = KeyboardObserver() and use @State private var ... Commented Jul 10 at 4:48

0

Browse other questions tagged or ask your own question.