首页 > 解决方案 > 防止在 UIRepresentableView 中调用 updateUIView()?

问题描述

我需要先更改 a 中的布尔值,UIRepresentableView然后再将其从 中删除,ContentView但找不到方法,因为我无法改变结构属性。

为什么我需要那个?因为我需要防止updateUIView()在视图发布之前被最后一次调用。

所以这可能是一个XY问题......无论如何,我迷路了。


我有一个这样的模型:

class PlayerModel: NSObject, ObservableObject {

    @Published var lottie: [LottieView]

这是哪里LottieView

struct LottieView: UIViewRepresentable {
    var name: String
    var loopMode: LottieLoopMode = .playOnce
    
    func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
        let view = UIView()
        return view
    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
        uiView.subviews.forEach({ sub in
            sub.removeFromSuperview()
        })
        
        let animationView = AnimationView()
        animationView.translatesAutoresizingMaskIntoConstraints = false
        uiView.addSubview(animationView)

        NSLayoutConstraint.activate([
            animationView.widthAnchor.constraint(equalTo: uiView.widthAnchor),
            animationView.heightAnchor.constraint(equalTo: uiView.heightAnchor)
        ])

        animationView.animation = Animation.named(name, animationCache: LRUAnimationCache.sharedCache)
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = loopMode
        animationView.play()
    }
}

在我的ContentView我只显示一个LottieView如果在已发布的数组中有一个最近的:

struct ContentView: View {

    @ObservedObject var model: PlayerModel
    
    var body: some View {
        NavigationView {
            VStack {
                // ...
                
                if let lottie = model.lottie.last {
                    lottie
                }
                
                // ...
            }
        }
    }

}

现在这可以正常工作了,但是当我在模型中LottieView从已发布的数组中删除最后updateUIView()一个时,SwiftUI 会最后一次调用 func,导致在从视图中删除之前再次重新创建动画LottieView,从而导致可见的闪烁.

LottieView所以我想我会添加一个布尔值,我可以在从已发布数组中删除最后一个之前更新它,并在中执行 if/else updateUIView(),但是......这甚至可能吗?我找不到办法。

理想情况下,我将只创建动画视图makeUIView()并且什么都不做,updateUIView()但这是不可能的,我需要先删除子视图,否则之前显示的动画不会被新的动画替换。

标签: swiftuilottieuiviewrepresentable

解决方案


虽然我仍然希望有人为我的问题提供适当的解决方案,或者告诉我另一种做事方式,但我找到了一种解决方法。

在模型中,我之前通过执行清空已发布的数组

lottie = []

但如果我们这样做:

lottie.removeAll()

我们再也看不到闪烁了(但updateView()仍然被称为!!)。


推荐阅读