English 中文(简体)
页: 1 • 与UIHostingController s nav Bar公司合作
原标题:SwiftUI s new NavigationStack API doesn t work well with UIHostingController s nav bar

我有一台家庭调查仪,我用UIHostingController将我的一些屏幕移至快速倡议。 我曾经能够重新使用同样的“公民自由联盟”。 但是,在转向“导航信号灯”之后,我就不得不重复同样的行为。

这里是一部完全可再现的法典。


import UIKit
import SwiftUI

struct ListView: View {
  
  @State var selectedString: String? = nil
  
  var body: some View {
    let details = ["foo", "bar", "baz"]

    // No need to wrap under NavigationView, otherwise will have double Nav Bar
    // This will use the UIKit s nav bar
    List {
      ForEach(details, id: .self) { detail in
        let destination = Text("This is a detailed page for (detail)")
          .navigationTitle("Detail page")
        
        NavigationLink(
          detail,
          destination: destination,
          tag: detail,
          selection: $selectedString)
      }
    }
    .navigationTitle("List page")
  }
}

struct ListViewWithNewAPI: View {
  @State var selectedString: String? = nil
  
  var body: some View {
    let details = ["foo", "bar", "baz"]
    
    NavigationStack {
      List(details, id: .self, selection: $selectedString) { detail in
        NavigationLink(detail, value: detail)
      }
      .navigationDestination(item: $selectedString) { detail in
        Text("This is a detailed page for (detail)")
          .navigationTitle("Detail page")
      }
      .navigationTitle("List page")
      .navigationBarTitleDisplayMode(.inline)
    }
  }
}

class ViewController: UIViewController {

  @objc
  private func tapButton1() {
    let listVC = UIHostingController(rootView: ListView())
    navigationController?.pushViewController(listVC, animated: true)
  }
  
  @objc
  private func tapButton2() {
    let listVC = UIHostingController(rootView: ListViewWithNewAPI())
    navigationController?.pushViewController(listVC, animated: true)
  }
  
  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    let button1 = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
    button1.backgroundColor = .green
    button1.addTarget(self, action: #selector(tapButton1), for: .touchUpInside)
    view.addSubview(button1)
    
    let button2 = UIButton(frame: CGRect(x: 100, y: 300, width: 100, height: 100))
    button2.backgroundColor = .red
    button2.addTarget(self, action: #selector(tapButton2), for: .touchUpInside)
    view.addSubview(button2)
   
    navigationItem.title = "UIKit title"
  }
}

故事板的档案相当大部分是初步项目,但我把VC置于一夫 v之下。

“entergraph

在上述代码中,<代码>ListView 采用经修改的<代码>Navigation 观点与<条码> 查询/编码>良好,<条码> 。

这里有一个视频,比较了2项行为。 请使用样本代码和环绕,看我们是否能够利用新版本实现原始行为。

“enter

最佳回答

导航 Stack取代导航 观点。 在你的法典中,你把UIHostingController推向一个导航主计长。 然而,清单中“With NewAPI”的观点含有导航标准。 这意味着,你现在有两层导航屏障,导致不受欢迎的行为。

解决这一问题有三个不同的选择:

  1. 一种选择是将导航主计长从你的故事板上除名。 你不能在故事板上直接使用UIHostingController,因为它使用通用名词,但你可以把该信封装在一(不设纳伊夫吉斯会计)国际笔记中。 或者,你可以完全摆脱故事板,通过快速评估器的生命周期。 然后,你可以把《清单》中的法典作为人使用。

  2. 您可以继续使用“链接导航”(视线:标签),该导航系统不作解释,并且继续与航空测量局合作。 不幸的是,这意味着没有基于方案或价值的导航。

struct ListViewWithNewAPI: View {
    @State var selectedString: String? = nil
    
    var body: some View {
        let details = ["foo", "bar", "baz"]
        
        List(details, id: .self, selection: $selectedString) { detail in
            NavigationLink {
                Text("This is a detailed page for (detail)")
                    .navigationTitle("Detail page")
            } label: {
                Text(detail)
            }
            
        }
            .navigationTitle("List page")
            .navigationBarTitleDisplayMode(.inline)
    }
}
  1. If you need to keep the UINavigationController (because of other UIKit-based code) AND you want programmatic/value-based navigation, you could do the following:

快速倡议使用的导航模型

class NavigationModel {
    var navigationController: UINavigationController?
    
    func push<V: View>(@ViewBuilder _ view: () -> V) {
        let vc = UIHostingController(rootView: view())
        navigationController?.pushViewController(vc, animated: true)
    }
}

增加导航 主计长对模型的介绍,并将模型反馈给您。

// property of ViewController
private let navigationModel = NavigationModel()

@objc
private func tapButton2() {
    navigationModel.navigationController = navigationController
    let rootView = ListViewNavigation(navigationModel: navigationModel)
    let hc = UIHostingController(rootView: rootView)
    navigationController?.pushViewController(hc, animated: true)
}

This is how you use the navigation model

struct ListViewNavigation: View {
    let navigationModel: NavigationModel
    
    let details = ["foo", "bar", "baz"]
    
    var body: some View {
        List(details, id: .self) { detail in
            Button(action: { navigateTo(detail) }) {
                Text("Go to (detail)")
            }
        }
    }
    
    func navigateTo(_ detail: String) {
        navigationModel.push {
            Text("This is a detail page for (detail)")
        }
    }
}
问题回答

我也遇到了这一双重导航问题(国际航道测量局驾驶UIHostingController,其根基 观点载于<代码>NavigationStack。 关于我的使用案例I,really希望保留方案.navigationDestination(<type>);{...}NavigationStack导航,主要因为我需要保持目的地观点“lazy”(即:NavigationLink(<destination> <label>)方法,除非我去做重大 ha笑的话。

我还需要为电离层的其他非航道部分保留探空机。 因此,我的解决办法是,在《航海倡议》的眼光中掩盖“国库”的 n,然后在《航海统计》内 em回子。 然而,对我的需求来说,这种估计是无缝的。

@available(iOS 16.0, *)
struct MyView: View {
    @Environment(.dismiss) private var dismiss

    var body: some View {
        NavigationStack {
            VStack {
                Text("Blah blah blah...")
            }
            // SwiftUI navigation bar properties
            .navigationTitle("My View")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                // Emulate a back button to take us back to the UIKit controller
                ToolbarItem(placement: .topBarLeading) {
                    Button {
                        dismiss()
                    } label: {
                        Image(systemName: "chevron.left")
                    }

                }
            }
        }
        .toolbar(.hidden, for: .navigationBar) // Hide UIKit navigation bar
    }
}

我还需要一名定制的UIHostingController,以便在从快速倡议的角度来看回统一概念一时,重新展示Kit导航条。

@available(iOS 16.0, *)
class MyViewHostingController: UIHostingController<MyView> {
    private var wasNavigationBarHidden: Bool?
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override init(rootView: MyView) {
        super.init(rootView: rootView)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        wasNavigationBarHidden = navigationController?.isNavigationBarHidden
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        // Re-display the navigation bar
        if let wasNavigationBarHidden,
            let navigationController,
           navigationController.isNavigationBarHidden != wasNavigationBarHidden
        {
            navigationController.isNavigationBarHidden = wasNavigationBarHidden
        }
    }
}





相关问题
List Contents of Directory in a UITableView

I am trying to list the contents of Ringtones directory in a TableView, however, I am only getting the last file in the directory in ALL cells, instead of file per cell. This is my code: - (...

iPhone NSUserDefaults persistance difficulty

In my app i have a bunch of data i store in the NSUserdefaults. This information consists of an NSObject (Object1) with NSStrings and NSNumbers and also 2 instances of yet another object (Object2). ...

Writing a masked image to disk as a PNG file

Basically I m downloading images off of a webserver and then caching them to the disk, but before I do so I want to mask them. I m using the masking code everyone seems to point at which can be found ...

Resize UIImage with aspect ratio?

I m using this code to resize an image on the iPhone: CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0); UIGraphicsBeginImageContext(screenRect.size); [value drawInRect:screenRect blendMode:...

Allowing interaction with a UIView under another UIView

Is there a simple way of allowing interaction with a button in a UIView that lies under another UIView - where there are no actual objects from the top UIView on top of the button? For instance, ...

热门标签