【问题标题】:UIScrollView in SwiftUI, issues navigating using UIHostingControllerSwiftUI 中的 UIScrollView,使用 UIHostingController 导航时出现问题
【发布时间】:2020-11-12 07:35:46
【问题描述】:

我需要从 SwiftUI 中的 UIScrollView 拉取刷新功能。所以我有一个基本的UIViewRepresentable 将 UIKit 组件改编为 SwiftUI。但是通过使用UIHostingController,我无法离开屏幕导航,因为我猜它现在管理导航。查看 Apple 的文档,UIHostingController 旨在用于将 SwiftUI 视图引入 UIKit,而不是相反。但是从 RefreshableScrollView 中删除 UIHostingController 不会在屏幕上呈现 ScrollView。

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

// 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()
        }
    }
}

【问题讨论】:

    标签: ios swift uiviewcontroller swiftui uikit


    【解决方案1】:

    NavigationLinkNavigationView 内部工作(除了 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")
           }
        }
      }
    }
    

    【讨论】:

    • 我无法点击 NavigationLink,看起来 UIHostingController 仍然处于活动状态。如果我使用NavigationLink(isActive: $active, destination: Text("Destination")),当我单击它时,我可以看到active 布尔值发生了变化,但视图本身并没有改变。这对您在本地有效吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    相关资源
    最近更新 更多