我正在尝试使用CADisplayLink
实现一个简单的动画。黑色正方形应该在屏幕上缓慢移动。
但是正方形看起来是静止的,因为body
递增testX和testY时Squares
的{{1}}不会得到更新。
据我所知(我是Swift的新手),我正确地使用了step()
范例,所以我不明白为什么视图不会刷新。
如何获得@ObservedObject
的{{1}}和动画一起更新?
下面是我的代码,谢谢您的帮助!
Squares
答案 0 :(得分:0)
据我所知,您需要的是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
}
}
}
答案 1 :(得分:0)
这是因为您的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()
}
}
}