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

Swift 如何在CADisplayLink动画期间更新视图,swift,swiftui,cadisplaylink,Swift,Swiftui,Cadisplaylink,我正在尝试使用CADisplayLink实现一个简单的动画。黑色方块应该在屏幕上缓慢移动 但是正方形看起来是静止的,因为当step()增加testX和testY时,正方形的主体不会更新 据我所知(我是Swift新手),我正确地使用了@ObservedObject范式,所以我不明白为什么视图不会刷新 如何使方块的身体随动画一起更新 我的代码在下面,谢谢你的帮助 class MyAnimations: NSObject, ObservableObject { @Published var t

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

但是正方形看起来是静止的,因为当
step()
增加testX和testY时,
正方形的
主体
不会更新

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

如何使
方块
身体
随动画一起更新

我的代码在下面,谢谢你的帮助

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

据我所知,您所需要的只是
observateObject的一个共享实例

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

这是因为您的
displaylink
是在堆栈上创建的,所以在退出函数后立即销毁。你需要让它成为你的财产

下面是经过修改的测试代码。使用Xcode 12/iOS 14进行测试

类MyAnimations:NSObject,ObservableObject{
@已发布的var testX:Double=0
@已发布的变量testY:Double=0

private var displaylink:CADisplayLink!//您是否在任何地方创建CADisplayLink?您需要将它放到某个地方,例如添加修饰符
.onAppear{self.animation.createDisplayLink()}
。是的,我已经在调用createDisplayLink()从某个地方,很抱歉造成混淆。动画运行时,只是Squares()从不更新。我实际上已经从其他地方调用了createDisplayLink(),这在我发布的代码中没有显示,抱歉!我已经确认动画正在运行--只是Squares()而已不随动画一起更新。这可能是实例问题。您有两个
ObservedObject
实例,一个无法与另一个对话,因此您必须通过使用
@EnvironmentObject
或为单例模式添加
sharedInstance
变量来共享它。我将在一分钟内更新代码。I tr我尝试了两种方法——单例模式和@EnvironmentObject——但都不适用于我。没有错误或其他任何东西,只是一个固定的黑色正方形,和以前一样。您的更多代码可能有助于找到解决方案。它不适用于我。太令人沮丧了!我正在为iOS 13.6使用Xcode 11.7。
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()
        }
    }
}