SwiftUI中的UIScrollView,使用UIHostingController

时间:2020-07-22 17:09:08

标签: ios swift uiviewcontroller swiftui uikit

我需要从SwiftUI中的UIScrollView刷新功能。因此,我对UIKit组件进行了基本的UIViewRepresentable改编成SwiftUI。但是通过使用UIHostingController,我无法从屏幕上导航出来,因为我猜测它现在可以管理导航了。查看苹果的文档,UIHostingController旨在用于将SwiftUI视图带入UIKit,而不是相反。但是从RefreshableScrollView中删除UIHostingController并不会在屏幕上呈现ScrollView。

我有什么方法可以在SwiftUI中成功使用UIScrollView而没有导航问题或没有UIHostingController

// ContentView.swift
struct ContentView: View {
    var body: some View {
        VStack {
            GeometryReader { geometry in
                RefreshableScrollView(size: geometry.size, refresh: self.refresh) {
                    Text("Placeholder text")
                }
            }
        }
        NavigationLink(destination: Text("Destination")) {
            Text("Click me")
        }
    }

    func refresh() {
        print("refreshing")
    }
}

// RefreshableScrollView.swift
import SwiftUI
import UIKit

struct RefreshableScrollView<Content: View>: UIViewRepresentable {
    var width: CGFloat
    var height: CGFloat
    var refresh: () -> Void
    var refreshViewController: UIHostingController<Content>
    
    init(size: CGSize, refresh: @escaping () -> Void, @ViewBuilder content: () -> Content) {
        self.width = size.width
        self.height = size.height
        self.refresh = refresh
        self.refreshViewController = UIHostingController(rootView: content())
    }
    
    func makeUIView(context: Context) -> UIScrollView {
        let scrollView = UIScrollView()
        scrollView.refreshControl = UIRefreshControl()
        scrollView.refreshControl?.addTarget(
            context.coordinator,
            action: #selector(Coordinator.handleRefreshControl(sender:)),
            for: .valueChanged
        )
        refreshViewController.view.frame = CGRect(x: 0, y: 0, width: self.width, height: self.height)
        scrollView.addSubview(self.refreshViewController.view)
        return scrollView
    }
    
    func updateUIView(_ uiView: UIScrollView, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject {
        var refreshScrollView: RefreshableScrollView
        
        init(_ refreshScrollView: RefreshableScrollView) {
            self.refreshScrollView = refreshScrollView
        }
        
        @objc func handleRefreshControl(sender: UIRefreshControl) {
            self.refreshScrollView.refresh()
            sender.endRefreshing()
        }
    }
}

1 个答案:

答案 0 :(得分:0)

NavigationLink可以在NavigationView内部运行(watchOS除外),因此请按以下方式嵌入

var body: some View {
  NavigationView {
    VStack {
        GeometryReader { geometry in
            RefreshableScrollView(size: geometry.size, refresh: self.refresh) {
                Text("Placeholder text")
            }
        }
        NavigationLink(destination: Text("Destination")) {
           Text("Click me")
       }
    }
  }
}