防止 updateUIView 在 @State var 更改时更新视图

Posted

技术标签:

【中文标题】防止 updateUIView 在 @State var 更改时更新视图【英文标题】:Prevent updateUIView to update view when @State var changes 【发布时间】:2021-12-28 23:14:11 【问题描述】:

在阅读了其他问题和 google 之后,我认为可以肯定地说,只要 UIViewRepresentable 中的任何@state/@Binding var 发生更改,无论如何都会触发 updateUIView。就我而言,我不想在一个特定的@State var 上触发 updateUIView。

我在我的应用程序中使用谷歌地图,我使用@state/@Binding var 将一些位置列表数据传递给 UIViewRepresentable,updateUIView 执行列表迭代并在 mapView 上使用GMSCameraUpdate.fit(bounds,withPadding: 15.0) 显示位置标记。

现在我正在使用协调器来使用 GMSMapViewDelegate 方法,例如拖动、willMove 和 idleAt。我想在相机移动后触发 idleAt 后立即将一个 @State var 的布尔值传递回我的内容视图。布尔值被发送回 contentView,我可以触发我的 API 以获取新的位置数据列表并将其传递给 @State var。但是由于 bool 是一个 @State var 并且它已更新,因此仍会使用旧数据列表触发 updateUIView 并将相机移回旧位置边界。这个 updateUIView 甚至在 API 调用被触发之前就被触发了。

如何在不触发 updateUIView 的情况下将 bool 发送回我的 contentView?

UIView 可表示的代码

struct MapsView: UIViewRepresentable 

@Binding var list : [LocationObj]
@Binding var shouldRefresh: Bool

func makeUIView(context: Context) -> GMSMapView 

func updateUIView(_ mapView: GMSMapView, context: Context)
    var bounds = GMSCoordinateBounds()
    for location in list
    
    mapView.animate(with: GMSCameraUpdate.fit(bounds,withPadding: 15.0))



func makeCoordinator() -> Coordinator 
    Coordinator(owner: self, refresh: $shouldRefresh)


class Coordinator: NSObject, GMSMapViewDelegate 
    
    let owner: MapsView
    var mShouldRefresh: Binding<Bool>

    init(owner: MapsView, refresh: Binding<Bool>) 
        self.owner = owner
        self.mShouldRefresh = refresh
    

func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) 
   // after moving camera and calculating the difference
    mShouldRefresh.wrappedValue = true

现在回到 contentView

@State var shouldRefresh = true

MapsView(list: $locationList, shouldRefresh: $shouldRefresh)

【问题讨论】:

那么不要使用绑定,而是可以注入闭包并调用它,不会调用更新,因为可表示不再依赖于该状态。 @Asperi 我不明白闭包在这里是如何工作的。你能写一些代码sn-p吗? 【参考方案1】:

这是可能的方法的草图(内联编写,未经测试,因此可能是错字 - 编译器错误修复由您负责):

struct MapsView: UIViewRepresentable 

    @Binding var list : [LocationObj]
    var callback: (Bool) -> Void           // << here !!

    func makeUIView(context: Context) -> GMSMapView

    func updateUIView(_ mapView: GMSMapView, context: Context)
        var bounds = GMSCoordinateBounds()
        for location in list

        mapView.animate(with: GMSCameraUpdate.fit(bounds,withPadding: 15.0))

    

    func makeCoordinator() -> Coordinator 
        Coordinator(owner: self)
    

    class Coordinator: NSObject, GMSMapViewDelegate 

        let owner: MapsView

        init(owner: MapsView) 
            self.owner = owner
        

        func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition)
            // after moving camera and calculating the difference
            owner.callback(true)      // << here !!
        
    

和类似的用法

@State var shouldRefresh = true

MapsView(list: $locationList) 
    self.shouldRefresh = $0

【讨论】:

感谢您的时间,我会尝试更新。 我以MapsView(workersList: $locationList, callback: self.shouldRefresh = $0) 尝试了这个关闭,但updateUIView 仍然被解雇。有什么想法吗?

以上是关于防止 updateUIView 在 @State var 更改时更新视图的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI MapKit 的 updateUIView 中添加“.setRegion”?

iOS 14 SwiftUI UIViewRepresentable updateUIView 没有检测到 ObservedObject 的变化?

SwiftUI 不断更新坐标位置

为什么@EnvironmentObject强制重新初始化视图?

OpenID Connect 服务器流中的“state”参数可以防止啥攻击?

防止将重复的对象添加到 state react redux