swift 如何使用UIViewRepresentable协调器委托

yhuiod9q  于 2022-12-03  发布在  Swift
关注(0)|答案(1)|浏览(162)

我正在SwiftUI项目中使用Pulley一个用UIKit编写的Map抽屉库。我在项目中通过UIHostingController使用SwiftUI ListView,但我希望在抽屉位置未打开时禁用滚动,为此,我非常确定需要使用Pulley提供的一个委托函数(drawerPositionDidChange)但我不确定如何在协调器中使用委托,或者我是否应该尝试使用委托,也许我只需要使用某种类型的状态变量?
视图控制器中的委托

@objc public protocol PulleyDelegate: AnyObject {
    
    /** This is called after size changes, so if you care about the bottomSafeArea property for custom UI layout, you can use this value.
     * NOTE: It's not called *during* the transition between sizes (such as in an animation coordinator), but rather after the resize is complete.
     */

    @objc optional func drawerPositionDidChange(drawer: PulleyViewController, bottomSafeArea: CGFloat)
}

这是我尝试使用委托的UIViewRepresentable。

import SwiftUI

    struct DrawerPosition: UIViewControllerRepresentable {
        
        @Binding var bottomSafeArea: CGFloat?
        
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }

        func makeUIViewController(context: Context) -> some UIViewController {
            let vc = PulleyViewController()

            vc.delegate = context.coordinator
            
            return vc
        }
        
        func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
            // Updates the state of the specified view controller with new information from SwiftUI.
        }
        
        class Coordinator: NSObject, PulleyDrawerViewControllerDelegate {
            
            var parent: DrawerPosition
            
            init (_ parent: DrawerPosition) {
                self.parent = parent
            }
            
            func drawerPositionDidChange(drawer: PulleyViewController, bottomSafeArea: CGFloat){
                self.parent.bottomSafeArea = bottomSafeArea
            
            }
        }    
    }

要禁用滚动的ListView。

import SwiftUI

struct ListView: View {
    
    @State private var bottomSafeArea: CGFloat?
    
    var body: some View {
        ScrollViewReader { proxy in
            VStack {
                Button("Jump to #50") {
                    proxy.scrollTo(50)
                }
                List(0..<100, id: \.self) { i in
                   Text("Example")
                        .id(i)
               }.scrollDisabled(bottomSafeArea == 0 ? true : false)

            }
        }
    }
}

class ListViewVHC: UIHostingController<ListView> {
    required init?(coder: NSCoder) {
        super.init  (coder: coder, rootView: ListView())
    }
}

struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        ListView()
    }
}
qyswt5oh

qyswt5oh1#

以下是设置协调员的正确方法:

func makeCoordinator() -> Coordinator {
        Coordinator()
    }

    func makeUIViewController(context: Context) -> PullyViewController {
        context.coordinator.pullyViewController
    }
    
    func updateUIViewController(_ uiViewController: PullyViewController, context: Context) {
        // Updates the state of the specified view controller with new information from SwiftUI.
        context.coordinator.bottomSafeAreaChanged = { bottomSafeArea in
            self.bottomSafeArea = bottomSafeArea
        }

    }

class Coordinator: NSObject, PulleyDrawerViewControllerDelegate {
      lazy var pullyViewController: PulleyViewController = {
          let vc = PulleyViewController()
          vc.delegate = self
          return vc
      }()

      var bottomSafeAreaChanged: ((CGFloat) -> Void)?

      func drawerPositionDidChange(drawer: PulleyViewController, bottomSafeArea: CGFloat){
            bottomSafeAreaChanged?(bottomSafeArea)    
      }

相关问题