【问题标题】:UIViewRepresentable not updating Published / Binding properties in swiftuiUIViewRepresentable 不更新 swiftui 中的已发布/绑定属性
【发布时间】:2021-11-13 22:19:23
【问题描述】:

我正在尝试将 UIScrollView 包装在 SwiftUI 中以获得一些附加功能。我想访问 UIScrollView 的 contentOffset 属性并将其分配给某个属性(已发布 或绑定)在 SwiftUI 中,但 SwiftUI(我的 ContentView)没有检测到任何属性更改。你能帮我做对吗?

这是我的 UIScrollView

import SwiftUI
import UIKit

struct MyScrollView<Content: View>: UIViewRepresentable {
    
    @ObservedObject var viewModel: ViewModel
    @ViewBuilder var content: () -> Content
   
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UIScrollViewDelegate {
        var parent: MyScrollView

        init(_ parent: MyScrollView) {
            self.parent = parent
        }
        
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
           parent.viewModel.scrollviewContentOffset = scrollView.contentOffset.y
        }
        
    }
    
    func makeUIView(context: Context) -> UIScrollView {
        let scrollView = UIScrollView()
        
        scrollView.delegate = context.coordinator
        scrollView.isScrollEnabled = true
        
        let child = UIHostingController(rootView: content())
        scrollView.addSubview(child.view)
        
        let newSize = child.view.sizeThatFits(CGSize(width: UIScreen.screenWidth, height: UIScreen.screenHeight))
        child.view.frame = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
        
        scrollView.contentSize = newSize
        
        return scrollView
    }
    
    func updateUIView(_ uiView: UIScrollView, context: Context) {
        //
    }
    
    typealias UIViewType = UIScrollView
}

这是我的 ContentView

import SwiftUI

class ViewModel: ObservableObject {
    @Published var scrollviewContentOffset = CGFloat.zero
}

struct ContentView: View {
    
    @StateObject private var viewModel = ViewModel()
    
    var body: some View {
        MyScrollView(viewModel: viewModel) {
            ForEach(0..<100) { i in
                Text("\(i)")
                    .offset(y: viewModel.scrollviewContentOffset / CGFloat(i + 1)
            }
        }
    }
}

【问题讨论】:

    标签: ios swift swiftui uiscrollview uikit


    【解决方案1】:

    您在创建 MyScrollView 时仅捕获初始 content,而不是在视图模型更改时更新它。

    您需要在updateUIView 中设置更新的content。例如,您可以将hostingController 存储在Coordinator 中:

    struct MyScrollView<Content: View>: UIViewRepresentable {
    
        @StateObject var viewModel: ViewModel
        @ViewBuilder var content: () -> Content
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    
        class Coordinator: NSObject, UIScrollViewDelegate {
            let parent: MyScrollView
            var hostingController: UIHostingController<Content>!
    
            init(_ parent: MyScrollView) {
                self.parent = parent
            }
    
            func scrollViewDidScroll(_ scrollView: UIScrollView) {
                parent.viewModel.scrollviewContentOffset = scrollView.contentOffset.y
            }
    
        }
    
        func makeUIView(context: Context) -> UIScrollView {
            let scrollView = UIScrollView()
    
            scrollView.delegate = context.coordinator
            scrollView.isScrollEnabled = true
    
            let child = UIHostingController(rootView: content())
            context.coordinator.hostingController = child
            scrollView.addSubview(child.view)
    
            let newSize = child.view.sizeThatFits(CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
            child.view.frame = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
    
            scrollView.contentSize = newSize
    
            return scrollView
        }
    
        func updateUIView(_ uiView: UIScrollView, context: Context) {
            context.coordinator.hostingController.rootView = content()
        }
    }
    

    【讨论】:

    • 成功了,谢谢!
    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    相关资源
    最近更新 更多