GCD를 사용하여 Delay Call 취소
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3, DispatchWorkItem{print("I'm here!")})
// , 3
item.cancel()
Block을 DispatchWorkItem 대상에 봉한 다음 cancle을 보내서 실행 중인 Block을 취소할 수 있습니다.
여기서는 GCD의 delay call을 직접 캡슐화합니다.
오리지널 버전:
import Foundation
typealias Task = (_ cancle : Bool) -> Void
func delay(_ time: TimeInterval, task: @escaping() -> ()) -> Task? {
func dispatch_later(block: @escaping()->()) {
let t = DispatchTime.now() + time
DispatchQueue.main.asyncAfter(deadline: t, execute: block)
}
var closure : (() -> Void)? = task
var result : Task?
let delayedClosure : Task = {
cancle in
if let internalClosure = closure {
if cancle == false {
DispatchQueue.main.async(execute: internalClosure)
}
}
closure = nil
result = nil
}
result = delayedClosure
dispatch_later {
if let delayedClosure = result {
delayedClosure(false)
}
}
return result
}
func cancle(_ task: Task?) {
task?(true)
}
마지막 사용 코드는 다음과 같습니다.
let task = delay(3){print("I will be cancle")}
cancle(task)
만약 단번에 똑똑히 보았다면 아래의 분석을 볼 필요가 없었을 것이다.
스스로 쓰다
취소할 Block을 먼저 정의합니다.
typealias Task = (_ cancle : Bool) -> Void
func cancle(_ task: Task?) {
task?(true)
}
핵심은task를 delayed Closure라는 클립에 봉인하는 것입니다. delayed Closure가 실행될 때result가 비어 있는지 확인하고, 비어 있지 않으면 계속 실행합니다. cancle가false이면task를 실행하고,result를 비어 있습니다. 나중에 시간이 되면 delayed Closure를 호출할 때result가 비어 있기 때문에task를 실행하지 않습니다.
func delay(_ time: TimeInterval, task: @escaping()->()) -> Task? {
var result : Task?
let delayedClosure: Task = {cancle in
if result != nil {
if cancle == false {
DispatchQueue.main.async {
task()
}
}
result = nil
}
}
result = delayedClosure
return result
}
delay에서 실행 지연을 정의하는 하위 방법dispatchlater, delayedClosure를 dispatch로 포장later에서 호출할 수 있는 클립:
func delay(_ time: TimeInterval, task: @escaping()->()) -> Task? {
var result : Task?
func dispatch_later(block: @escaping()->()) {
let t = DispatchTime.now() + time
DispatchQueue.main.asyncAfter(deadline: t, execute: block)
}
let delayedClosure: Task = {cancle in
if result != nil {
if cancle == false {
DispatchQueue.main.async {
task()
}
}
result = nil
}
}
result = delayedClosure
dispatch_later {
delayedClosure(false)
}
return result
}
여기까지만 하면 실행 지연과task 취소가 가능합니다.
원판의 다음 문장:
var closure : (() -> Void)? = task
task에 가변 변수 closure에 값을 부여한 다음 delayed Closure에서 closure를 포획하고 Result와 함께 비우면 delayed Closure가 실행된 후 이 task를 즉시 방출할 수 있습니다.그렇지 않으면 Task가 반환되면서 캡처된 변수가 제거됩니다.그래서 이것은 단지 최적화일 뿐이다.그리고
if result != nil
의 판단을 디스패치에later가 호출한 클립에서 코드는 원판과 같다.OC 버전:
Task delay(NSTimeInterval time, Blk task) {
__block Task result;
__block Blk closure = task;
Task delayClosure = ^(BOOL cancle) {
if (closure) {
Blk internalClosure = closure;
if (!cancle) {
dispatch_async(dispatch_get_main_queue(), ^{
internalClosure();
});
}
closure = nil;
}
result = nil;
};
result = delayClosure;
dispatch_delay(time, ^{
if (result) {
result(false);
}
});
return result;
}
void dispatch_delay(NSTimeInterval time, Blk block) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), block);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.