これらを使用して遅延との相互作用を支援するためのヒントを指定するためにアニメーションを使用します。
let delay = 1.8 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
//call the method which have the steps after delay.
self.rain.alpha = 0
UIView.animateWithDuration(5, animations: {
self.rain.alpha = 1
})
self.tip.startAnimating()
}
ただし、アニメーションを開始する前にユーザーが画面に触れた場合は、この遅延プロセスを停止する必要があります。
iOS8およびOSX Yosemiteは、実行を開始する前にキャンセルできるdispatch_block_cancel
を導入しました
次のように、クラスで1つの変数を宣言します。
var block: dispatch_block_t?
block
変数を初期化し、それをdispatch_after
で提供します。
block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS) {
print("I executed")
}
let time: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(5 * NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue(), block!)
その後、次のようにキャンセルできます。
dispatch_block_cancel(block!)
Swift3.0の例DispatchQueueのキャンセルまたは停止
var dispatchQueue: DispatchQueue?
var dispatchWorkItem: DispatchWorkItem?
func someOnClickButtonStart() {
self.dispatchQueue = DispatchQueue.global(qos: .background) // create queue
self.dispatchWorkItem = DispatchWorkItem { // create work item
// async code goes here
}
if self.dispatchWorkItem != nil {
self.dispatchQueue?.asyncAfter(
deadline: .now() + .seconds(1),
execute: self.dispatchWorkItem!
) // schedule work item
}
}
func someOnClickButtonCancel() {
if let dispatchWorkItem = self.dispatchWorkItem {
dispatchWorkItem.cancel() // cancel work item
}
}
Swiftでdispatch_afterをキャンセルするために私が書いた一般的な解決策は次のとおりです。
typealias cancellable_closure = (() -> ())?
func dispatch_after(#seconds:Double, queue: dispatch_queue_t = dispatch_get_main_queue(), closure:()->()) -> cancellable_closure {
var cancelled = false
let cancel_closure: cancellable_closure = {
cancelled = true
}
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC))), queue, {
if !cancelled {
closure()
}
}
)
return cancel_closure
}
func cancel_dispatch_after(cancel_closure: cancellable_closure) {
cancel_closure?()
}
使用法:
let doSomethingLater = dispatch_after(seconds: 3.0) {
something()
}
....
if shouldCancelForSomeReason {
cancel_dispatch_after(doSomethingLater)
}
デフォルトではメインキューで実行されますが、別のキューで実行するためのパラメーターを渡すことができます。
let doSomethingLater = dispatch_after(seconds: 3.0, queue: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
something()
}
ブール変数shouldCancelAnimation
を作成し、それをdispatch_after
ブロック内でテストして、アニメーションの実行を防ぐことができます。
var shouldCancelAnimation = false // property of class
func runAnimation()
{
let delay = 1.8 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
if !self.shouldCancelAnimation
{
self.rain.alpha = 0
UIView.animateWithDuration(5, animations: {
self.rain.alpha = 1
})
self.tip.startAnimating()
}
self.shouldCancelAnimation = false
}
}
func viewWasTouched() // This could be touches began or taprecognizer event
{
shouldCancelAnimation = true
}
Swift 4.xで共有するだけで、私はこれを行います:
_var block: DispatchWorkItem?
_
_self.block = DispatchWorkItem { self.go(self) }
// execute task in 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3), execute: self.block!)
_
次に、ブロックをキャンセルするには、self.block?.cancel()
このサンプルプロジェクトを試してください:
_import UIKit
class ViewController: UIViewController {
var block: DispatchWorkItem?
@IBAction func go(_ sender: Any) {
self.block?.cancel()
let vc2 = VC2()
self.navigationController?.pushViewController(vc2, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.block = DispatchWorkItem { self.go(self) }
// execute task in 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3), execute: self.block!)
}
}
class VC2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .green
}
}
_