【问题标题】:Is it possible to assign a ViewController to a SwiftUI view?是否可以将 ViewController 分配给 SwiftUI 视图?
【发布时间】:2021-11-12 01:41:53
【问题描述】:

我正在使用 SwiftUI 应用协议构建一个 SwiftUI 应用。

我需要访问一些 UIKIt 函数,尤其是控制 NavigationView 的函数,如下所示:https://stackoverflow.com/a/56555928/13727105

显然,为此我需要将我的 SwiftUI 视图与 ViewController 绑定。

我尝试过以下操作:

ContentView.swift

struct ContentView: View {
    
    var body: some View {
        ZStack {
            ContentViewIntegratedController() // <- here
            NavigationView{
                ScrollView {
                    Text("Content View")
                        .navigationTitle("Content View")

                }
            }
        }
    }
}

class ContentViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

struct ContentViewIntegratedController: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> some UIViewController {
        return ContentViewController()
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType,
                                context: UIViewControllerRepresentableContext<ContentViewIntegratedController>) {}
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


但调用ContentViewIntegratedContoller(在第 5 行)似乎会创建一个新的预览而不是修改现有的。

有没有集成 ViewController 来修改 SwiftUI 视图?

我不想做的事:

  • 创建一个包含 SwiftUI 视图的 Storyboards 应用
  • ContentViewIntegratedViewController 创建一个故事板视图。

是否有任何替代方法可以访问这些功能而无需将 ViewController 添加到我的 SwiftUI 视图?

TIA。

【问题讨论】:

  • @Andrew 我做到了。 ContentViewIntegratedViewController 扩展了 UIViewControllerRepresentable。但它似乎仍然不起作用。
  • 如果您想要基于 Storyboards 的应用程序,您应该使用基于 UIKit 的模板创建项目,然后使用 UIHostingController 将 SwiftUI 视图集成到其中
  • 查看链接的问题,您想要做的比简单地使用带有 SwiftUI 的 UIKit 视图更棘手。您想要访问支持NavigationView 的导航控制器的属性。我认为这是不可能的。

标签: ios swift swiftui uiviewcontroller uikit


【解决方案1】:

纯 SwiftUI 无法直接检测 largeinline 显示模式之间的变化。但是,使用SwiftUI-Introspect,您可以下拉到 UIKit 来解决这个问题。

我通过获取大标题的视图并检测alpha 属性何时更改来解决此问题。这会在标题从 large 更改为 inline 的确切时刻发生变化,反之亦然。

代码:

struct ContentView: View {
    @State private var observer: NSKeyValueObservation?
    @State private var title: String = "Large Title"

    var body: some View {
        NavigationView {
            ScrollView {
                Text("Hello world!")
            }
            .navigationTitle(title)
        }
        .introspectNavigationController { nav in
            let largeTitleView = nav.navigationBar.subviews.first { view in
                String(describing: type(of: view)) == "_UINavigationBarLargeTitleView"
            }
            observer = largeTitleView?.observe(\.alpha) { view, change in
                let isLarge = view.alpha == 1
                title = isLarge ? "Large Title" : "Inline title"
            }
        }
    }
}

结果:

【讨论】:

  • 这种方法确实有效,但紧凑的标题会在一瞬间变为大标题,这是我想要避免的。有一个名为 Toolbar 的新 [插入 Swift 行话]。有没有办法观察工具栏的alpha值的变化?
  • @PraantoSamadder 我不相信有办法解决这个问题。这是由于 导航栏显示模式更改后调用了观察者。
【解决方案2】:
    struct ContentView: View {
    var body: some View {
        ContentViewIntegratedController(view: YourView())
            .ignoresSafeArea()
    }
    }




--------------------------------------------------------------
    struct YourView: View {
    var body: some View {
        ScrollView{
        Text("Hello, World!")
        }
    }}
------------------------------------------------------
    import Foundation
    import SwiftUI

    struct ContentViewIntegratedController :UIViewControllerRepresentable{
    
    var view: YourView
    
    init(view:YourView) {
        self.view = view
    }
    
    func makeUIViewController(context: Context) -> UINavigationController{
        
        let childView = UIHostingController(rootView: view)
        let controller =     UINavigationController(rootViewController:childView)
        let appearance = UINavigationBarAppearance()
        let searchController = UISearchController()
        
        
        searchController.searchBar.barStyle = .black
        
        appearance.backgroundColor = UIColor(Color(.red))
        appearance.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
        appearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
        
        
        controller.navigationBar.topItem?.compactAppearance = appearance
        controller.navigationBar.topItem?.scrollEdgeAppearance = appearance
        controller.navigationBar.topItem?.standardAppearance = appearance
        

        controller.navigationBar.topItem?.title = "navigation bar"
        controller.navigationBar.prefersLargeTitles = true
        
        searchController.searchBar.searchTextField.attributedPlaceholder = NSAttributedString(string: "Rechercher...", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
        searchController.searchBar.setValue("Annuler", forKey: "cancelButtonText")
        
        
        searchController.searchBar.showsBookmarkButton = true
        searchController.searchBar.searchTextField.leftView?.tintColor = .white
        
        let sfConfiguration = UIImage.SymbolConfiguration(pointSize: 30)
        let barCodeIcon = UIImage(systemName: "barcode.viewfinder")?.withTintColor(.white, renderingMode: .alwaysOriginal).withConfiguration(sfConfiguration)
    

        searchController.searchBar.setImage(barCodeIcon, for: .bookmark, state:.normal)
        searchController.obscuresBackgroundDuringPresentation = false
  

        let attributes = [NSAttributedString.Key.foregroundColor : UIColor.white]
        UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(attributes, for: .normal)
       
        controller.navigationBar.topItem?.hidesSearchBarWhenScrolling = false
        controller.navigationBar.topItem?.searchController = searchController
        
        return controller
        
    }
    
    
    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
        
    }}

【讨论】:

    猜你喜欢
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    • 1970-01-01
    相关资源
    最近更新 更多