1

I have an app which main framework was developed using uikit, and some of its pages were written by SwiftUI and embedded into uikit for display through UIHostingController. Now there is a Swiftui page with TextField, and I want to listen for changes in FocusState to facilitate some operations.

The window init code is as bellow:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        
        let vc1 = ViewController()
        // vc2 is the vc I want, but can not get the change of FocusState
        let vc2 = UINavigationController(rootViewController: ViewController()) 
        let vc3 = UINavigationController(rootViewController: UIHostingController(rootView: ContentView()))

        let tabBarVC = UITabBarController()
        tabBarVC.viewControllers = [vc1, vc2, vc3]
        
        if let tabbarItems = tabBarVC.tabBar.items {
            for i in 0..<tabbarItems.count {
                let item = tabbarItems[i]
                item.title = "Tab\(i+1)"
            }
        }
        
        window?.rootViewController = tabBarVC
        window?.makeKeyAndVisible()
        return true
    }

Then is the UIKit vc:

import UIKit
import SwiftUI

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let contentView = ContentView()
        let hostVC = UIHostingController(rootView: contentView)
        guard let hostView = hostVC.view else {
            return
        }
        view.addSubview(hostView)
        hostView.frame = view.frame
        // Do any additional setup after loading the view.
    }
}

And this is the SwiftUI View:

struct ContentView: View {
    @State var inputText: String = ""
    @FocusState var isFocused: Bool
    
    var body: some View {
        VStack {
            TextField("Input Textfield", text: $inputText)
                .focused($isFocused)
                .onChange(of: isFocused) { newValue in
                    // <- here to get the change of focus flag, only vc1 and vc3 print here , vc2 did nothing
                    print("focused is \(isFocused)")
                }
                .padding(50)
            Button(action: {
                // after click button ,only vc1 and vc3 and focus in TextField
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute:
                {
                    self.isFocused = true
                })
                
            }) {
                Text("Focus")
            }
        }
    }
}

What I expect is that when TextField enters or exits the editing state, FocusState can change, but in reality, only FocusStates in vc1 and vc3 can be listened to, while FocusStates in vc2 cannot. Due to some business reasons, I must use vc2 type to display the page here, and cannot use vc1 or vc3 type to display the page. Is there a way to listen for changes in FocusState in vc2?

mars
  • 109
  • 5
  • 21
  • @Asperi Need your help~ – mars Apr 28 '23 at 17:07
  • Have you been able to solve this? have you also experience in your app that only the hosting viewcontroller seems to get the focus back and not the swiftui content. VO is able to navigate swiftui controls but I haven't been able to set swiftui controls to focus. – mushcraft Jul 07 '23 at 10:05

0 Answers0