【问题标题】:How do you access UIViewControllerRepresentable NavigationBar property?你如何访问 UIViewControllerRepresentable NavigationBar 属性?
【发布时间】:2020-06-24 18:09:47
【问题描述】:

在 SwiftUI 中,如果您使用 NavigationLink() 转换为 UIViewControllerRepresentable,您会怎么做;例如,添加按钮或更改导航栏上的标题属性。

这就是我现在正在做的事情:

import SwiftUI

/// Controls the actual action performed by the button upon taps.
struct CatagoryButton: View {

    @State var isPresenting :Bool = false

    var company : Company?
    var text : String

    var body: some View {

        NavigationLink(destination: UIKitWrapper(company: self.company, storyboardPointer: self.text)
            .navigationBarTitle(self.text)
            .edgesIgnoringSafeArea(.all),
                       isActive: self.$isPresenting,

                       label: {
            Button(action: {
                self.isPresenting.toggle()

            }){

                ZStack {

                    ButtonShadowLayer(text: text)

                    GradientBackground()
                        .mask(ButtonBaseLayer())

                    CircleAndTextLayer(text: text)
                }
            }
        })
    }
}

这是我的可表示的结构。

import SwiftUI

/// Wraps UIKIT instance in a representable that swiftUI can present.
struct UIKitWrapper: UIViewControllerRepresentable {

    //Specify what type of controller is being wrapped in an associated type.
    typealias UIViewControllerType = UIViewController

    //Company property passed from parent view. Represents the company the user selected from main view.
    private var company : Company

    //Determines which viewcontroller will be presented to user. This string corresponds to the name of the storyboard file in the main bundle.
    private var storyboardPointer : String

    init(company: Company?, storyboardPointer: String) {

        guard let company = company else {fatalError()}

        self.company = company
        self.storyboardPointer = storyboardPointer
    }

    func makeUIViewController(context: Context) -> UIViewControllerType {

        //Find user defined storyboard in bundle using name.
        let storyboard = UIStoryboard(name: storyboardPointer, bundle: .main)

        //Downcast returned controller to protocol AccessControllerProtocol. This step is required because we are not sure which storyboard will be accessed. Potential storyboard controllers that can be called all conform to this protocol. 
        //FIXME: Remove fatalError and create error enum asap.
        guard let viewController = storyboard.instantiateInitialViewController() as? AccessControllerProtocol else { fatalError() }

        //Assign user selected company object to instance property on incoming viewController.
        viewController.company = company

        //Return UINavigationController with storyboard instance view controller as root controller.
        return viewController
    }

    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {

    }
}

最后,这是使用可表示的类之一。

import UIKit

class OrdersViewController: UIViewController, AccessControllerProtocol {

    var company : Company!
    @IBOutlet var companyNameLabel : UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        setBackgroundColor()
        companyNameLabel.text = company.name
        self.navigationController?.navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.tapRightBarButton))]
    }

    func setBackgroundColor(){

        let backgroundGradient = BackgroundGradientSetter()
        let viewWithGradient = backgroundGradient.setGradientToView(with: [DarkBlueHue_DEFAULT,LightBlueHue_DEFAULT], size: view.bounds)

        view.addSubview(viewWithGradient)
        view.sendSubviewToBack(viewWithGradient)
    }

    @objc func tapRightBarButton(){

    }
}

无论我做什么,这个按钮都不会出现。我不确定是否需要将其放入 makeCoordinator() 中,或者是否只是缺少某些东西。如果有人有见识,请告诉我!

【问题讨论】:

    标签: ios swift navigation uikit swiftui


    【解决方案1】:

    如果它在 viewDidLoad 中不可用,请尝试在 viewWillAppear() 中调用您的 setupNavigation()

    【讨论】:

      【解决方案2】:

      在您的情况下,navigationControllerviewDidLoad 上尚不可用,请尝试在下面的演示模块中进行

      经过测试并适用于 Xcode 11.2 / iOS 13.2

      class MyUIController: UIViewController {
      
          override func viewDidAppear(_ animated: Bool) {
              super.viewDidAppear(animated)
              self.navigationController?.navigationBar.topItem?.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.onAdd(_:)))
          }
      
          override func viewWillDisappear(_ animated: Bool) {
              super.viewWillDisappear(animated)
              // might be needed to remove injected item here
          }
      
          @objc func onAdd(_ sender: Any?) {
              print(">> tapped add")
          }
      }
      
      struct MyInjector: UIViewControllerRepresentable {
          func makeUIViewController(context: UIViewControllerRepresentableContext<MyInjector>) -> MyUIController {
              MyUIController()
          }
      
          func updateUIViewController(_ uiViewController: MyUIController, context: UIViewControllerRepresentableContext<MyInjector>) {
          }
      }
      
      struct DemoNavigationBarUIButton: View {
          var body: some View {
              NavigationView {
                  MyInjector()
                      .navigationBarTitle("Demo")
              }
          }
      }
      
      struct DemoNavigationBarUIButton_Previews: PreviewProvider {
          static var previews: some View {
              DemoNavigationBarUIButton()
          }
      }
      

      【讨论】:

      • 试过了,仍然没有任何反应。
      • @ScottLeonard,查看更新的答案和完整的测试工作代码。
      • 好的,问题是我需要使用:self.navigationController?.navigationBar.topItem?.rightBarButtonItem 而不是 self.navigationController?.navigationItem.rightBarButtonItems 感谢您的帮助。
      • 我会给你这个功劳。但是,您的解决方案也没有回答这个问题,因为它有很多不需要的步骤,也没有解决这是在使用 NavigationLink 进行转换的情况下。由于正在访问的属性发生了变化,因此该解决方案很简单。因此,如果您可以更新您的答案以反映这一点,以便其他人最终不会对他们的代码进行大量不必要的更改,谢谢。
      猜你喜欢
      • 2013-09-18
      • 1970-01-01
      • 2018-09-06
      • 1970-01-01
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      相关资源
      最近更新 更多