繁体   English   中英

如何在 CADisplayLink 动画期间更新视图

[英]How to update a view during a CADisplayLink animation

我正在尝试使用CADisplayLink实现一个简单的动画。 黑色方块应该在屏幕上缓慢移动。

但是正方形看起来是静止的,因为当step()增加 testX 和 testY 时Squaresbody没有得到更新。

据我所知(我是 Swift 新手),我正确使用了@ObservedObject范例,所以我不明白为什么视图不会刷新。

如何让Squaresbody与动画一起更新?

我的代码如下,感谢您的帮助!

class MyAnimations: NSObject, ObservableObject {
    @Published var testX: Double = 0
    @Published var testY: Double = 0
    
    func createDisplayLink() {
        let displaylink = CADisplayLink(target: self, selector: #selector(step))
        
        displaylink.add(to: .current, forMode: RunLoop.Mode.default)
    }
         
    @objc func step(link: CADisplayLink) {
        testX += 0.5
        testY += 0.5
    }
    
}



struct Squares: View {
    @ObservedObject var animation = MyAnimations()
    
    var body: some View {
        Path { path in
            path.addRect(CGRect(x: self.animation.testX, y: self.animation.testY, width: 50, height: 50))
        }
            .fill(Color.black)
    }
}


struct SomeOtherView: View {
    var body: some View {
        Squares()
    }
}

这是因为你displaylink是在栈创建的,就这么被毁了从函数退出之后。 你需要让它成为财产。

这是修改后的测试代码。 使用 Xcode 12 / iOS 14 测试。

演示

class MyAnimations: NSObject, ObservableObject {
    @Published var testX: Double = 0
    @Published var testY: Double = 0

    private var displaylink: CADisplayLink!       // << here !!
    func createDisplayLink() {
        if nil == displaylink {
            displaylink = CADisplayLink(target: self, selector: #selector(step))
            displaylink.add(to: .current, forMode: RunLoop.Mode.default)
        }
    }

    @objc func step(link: CADisplayLink) {
        testX += 0.5
        testY += 0.5
    }

}



struct Squares: View {
    @ObservedObject var animation = MyAnimations()

    var body: some View {
        Path { path in
            path.addRect(CGRect(x: self.animation.testX, y: self.animation.testY, width: 50, height: 50))
        }
        .fill(Color.black)
        .onAppear {
            animation.createDisplayLink()
        }
    }
}

从我看来,您只需要一个ObservableObject的共享实例

class MyAnimations: NSObject, ObservableObject {
    @Published var testX: Double = 0
    @Published var testY: Double = 0
    
    static let sharedInstance: MyAnimations = MyAnimations()//Singleton Pattern
    func createDisplayLink() {
        let displaylink = CADisplayLink(target: self, selector: #selector(step))
        
        displaylink.add(to: .current, forMode: RunLoop.Mode.default)
    }
    
    @objc func step(link: CADisplayLink) {
        testX += 0.5
        testY += 0.5
    }
    
}
struct Squares: View {
    //@ObservedObject var animation = MyAnimations.sharedInstance//Singleton Pattern
    @EnvironmentObject var animation: MyAnimations
    var body: some View {
        VStack{
            Button("Move", action: {
                animation.createDisplayLink()
            })
            Path { path in
                path.addRect(CGRect(x: self.animation.testX, y: self.animation.testY, width: 50, height: 50))
            }
            .fill(Color.black)
        }
    }
}


struct SomeOtherView: View {
    @ObservedObject var animation = MyAnimations()
    //@ObservedObject var animation = MyAnimations.sharedInstance//Singleton Pattern
    var body: some View {
        VStack{
            Button("Trigger to Create", action: {
                animation.createDisplayLink()
            })//Sample Trigger
            Squares()
                .environmentObject(animation)//Omit if using Singleton
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM