简体   繁体   English

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

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

I'm trying to implement a simple animation using CADisplayLink .我正在尝试使用CADisplayLink实现一个简单的动画。 A black square should move slowly across the screen.黑色方块应该在屏幕上缓慢移动。

But the square appears stationary because the body of Squares doesn't get updated when step() increments testX and testY.但是正方形看起来是静止的,因为当step()增加 testX 和 testY 时Squaresbody没有得到更新。

From what I can gather (I'm new to Swift), I'm using the @ObservedObject paradigm correctly, so I don't understand why the view won't refresh.据我所知(我是 Swift 新手),我正确使用了@ObservedObject范例,所以我不明白为什么视图不会刷新。

How do I get Squares 's body to update along with the animation?如何让Squaresbody与动画一起更新?

My code is below, thanks for your help!我的代码如下,感谢您的帮助!

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

This is because your displaylink is created on stack, so destroyed right after quit from function.这是因为你displaylink是在栈创建的,就这么被毁了从函数退出之后。 You need to make it property.你需要让它成为财产。

Here is modified tested code.这是修改后的测试代码。 Tested with Xcode 12 / iOS 14.使用 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()
        }
    }
}

From what I see all you need is a shared instance of your ObservableObject从我看来,您只需要一个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