如何在 Swift 3.0 中停止来自 运行 的函数
How to stop a Function from Running in Swift 3.0
我有一个函数可以开始异步播放 运行 动画(在后台)。使用完成处理程序(见下文)无限期地调用此动画。有没有办法在按下另一个按钮时关闭此功能?
这是我的代码:
func showAnimation() {
UIView.animate(withDuration: 1, animations: {
animate1(imageView: self.Anime, images: self.animation1)
}, completion: { (true) in
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.showAnimation() // replay first showAnimation
}
})
}
然后按下另一个按钮,我们关闭上述功能
showAnimation().stop();
谢谢
有很多方法可以做到这一点。最简单的是在 asyncAfter
块中检查一个布尔值 属性 (你应该正确地使其成为原子),如果它是真的,不要再调用 showAnimation()
.
您可以做的另一件事,也是我喜欢为更复杂的任务做的事情,是使用 OperationQueue
而不是 DispatchQueue
。这允许您单独或一次取消操作,甚至暂停整个队列(显然不要暂停主队列或对其调用 removeAllOperations()
,因为那里可能有其他不相关的操作到你的代码)。
您可以在 class 中添加一个 属性 作为标志,指示动画是否应该 运行。
var runAnimation = true
func showAnimation() {
if !runAnimation { return }
UIView.animate(withDuration: 1, animations: {
animate1(imageView: self.Anime, images: self.animation1)
}, completion: { (true) in
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
if runAnimation {
self.showAnimation() // replay first showAnimation
}
}
})
}
然后在按钮处理程序中停止动画,您只需执行以下操作:
runAnimation = false
请注意,这不会停止当前 运行ning 1 秒的动画。这只会阻止任何更多的动画。
您可以在您的函数之外提供一个变量,然后观察它的值并处理您的任务。我可以给你一个解决方案:
class SomeClass {
private var shouldStopMyFunction: Bool = false // keep this private
public var deadline: TimeInterval = 0
func stopMyFunction() {
shouldStopMyFunction = true
}
func myFunction(completionHanlder: @escaping (String)->()) {
// -------
var isTaskRunning = true
func checkStop() {
DispatchQueue.global(qos: .background).async {
if self.shouldStopMyFunction, isTaskRunning {
isTaskRunning = false
completionHanlder("myFunction is forced to stop! ")
} else {
//print("Checking...")
checkStop()
}
}
}
checkStop()
// --------
// Start your task from here
DispatchQueue.global().async { // an async task for an example.
DispatchQueue.global().asyncAfter(deadline: .now() + self.deadline, execute: {
guard isTaskRunning else { return }
isTaskRunning = false
completionHanlder("My job takes \(self.deadline) seconds to finish")
})
}
}
}
并实施:
let anObject = SomeClass()
anObject.deadline = 5.0 // seconds
anObject.myFunction { result in
print(result)
}
let waitingTimeInterval = 3.0 // 6.0 // see `anObject.deadline`
DispatchQueue.main.asyncAfter(deadline: .now() + waitingTimeInterval) {
anObject.stopMyFunction()
}
waitingTimeInterval = 3.0
的结果:myFunction is forced to stop!
waitingTimeInterval = 6.0
的结果:My job takes 5.0 seconds to finish
我有一个函数可以开始异步播放 运行 动画(在后台)。使用完成处理程序(见下文)无限期地调用此动画。有没有办法在按下另一个按钮时关闭此功能?
这是我的代码:
func showAnimation() {
UIView.animate(withDuration: 1, animations: {
animate1(imageView: self.Anime, images: self.animation1)
}, completion: { (true) in
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.showAnimation() // replay first showAnimation
}
})
}
然后按下另一个按钮,我们关闭上述功能
showAnimation().stop();
谢谢
有很多方法可以做到这一点。最简单的是在 asyncAfter
块中检查一个布尔值 属性 (你应该正确地使其成为原子),如果它是真的,不要再调用 showAnimation()
.
您可以做的另一件事,也是我喜欢为更复杂的任务做的事情,是使用 OperationQueue
而不是 DispatchQueue
。这允许您单独或一次取消操作,甚至暂停整个队列(显然不要暂停主队列或对其调用 removeAllOperations()
,因为那里可能有其他不相关的操作到你的代码)。
您可以在 class 中添加一个 属性 作为标志,指示动画是否应该 运行。
var runAnimation = true
func showAnimation() {
if !runAnimation { return }
UIView.animate(withDuration: 1, animations: {
animate1(imageView: self.Anime, images: self.animation1)
}, completion: { (true) in
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
if runAnimation {
self.showAnimation() // replay first showAnimation
}
}
})
}
然后在按钮处理程序中停止动画,您只需执行以下操作:
runAnimation = false
请注意,这不会停止当前 运行ning 1 秒的动画。这只会阻止任何更多的动画。
您可以在您的函数之外提供一个变量,然后观察它的值并处理您的任务。我可以给你一个解决方案:
class SomeClass {
private var shouldStopMyFunction: Bool = false // keep this private
public var deadline: TimeInterval = 0
func stopMyFunction() {
shouldStopMyFunction = true
}
func myFunction(completionHanlder: @escaping (String)->()) {
// -------
var isTaskRunning = true
func checkStop() {
DispatchQueue.global(qos: .background).async {
if self.shouldStopMyFunction, isTaskRunning {
isTaskRunning = false
completionHanlder("myFunction is forced to stop! ")
} else {
//print("Checking...")
checkStop()
}
}
}
checkStop()
// --------
// Start your task from here
DispatchQueue.global().async { // an async task for an example.
DispatchQueue.global().asyncAfter(deadline: .now() + self.deadline, execute: {
guard isTaskRunning else { return }
isTaskRunning = false
completionHanlder("My job takes \(self.deadline) seconds to finish")
})
}
}
}
并实施:
let anObject = SomeClass()
anObject.deadline = 5.0 // seconds
anObject.myFunction { result in
print(result)
}
let waitingTimeInterval = 3.0 // 6.0 // see `anObject.deadline`
DispatchQueue.main.asyncAfter(deadline: .now() + waitingTimeInterval) {
anObject.stopMyFunction()
}
waitingTimeInterval = 3.0
的结果:myFunction is forced to stop!
waitingTimeInterval = 6.0
的结果:My job takes 5.0 seconds to finish