티스토리 뷰
https://developer.apple.com/documentation/foundation/operation
Operation
싱글 tast와 관련된 코드와 데이터를 나타내는 추상 클래스
Overview
Operation은 추상클래스이기 때문에 직접 사용하지말고 subclass하거나 시스템에서 지정한 subclasses (NSInvocationOperation or BlockOperation)를 사용해야합니다.
추상적이지만 작업의 기본 구현에는 작업의 안전한 실행을 조정하기 위한 중요한 로직이 포함되어 있습니다.
이러한 기본 로직이 있으면 다른 시스템 객체와 올바르게 작동하는데 필요한 glue code가 아니라 실제 작업 구현에 집중할 수 있습니다.
operation은 한 번만 실행가능합니다.
즉 한 번 실행하면 다시 실행하는데 사용할 수 없습니다.
일반적으로 operation 큐에 추가하여 실행합니다.
operation 큐는 작업을 직접 실행하거나, secondary 스레드에서 실행하거나, GCD를 사용하여 간접적으로 실행합니다.
operation 큐를 사용하지 않으려면 start()메서드를 호출해서 직접 실행할 수 있습니다.
operation을 직접 실행하면 준비 상태가 아닌데 예외를 실행하기 때문에 코드에 부하가 많이 갑니다.
isReady프로퍼티는 operation의 준비 상태를 보고합니다.
Operation Dependencies
의존성은 특정 순서로 작업을 실행하는 편리한 방법입니다.
addDependency(_:) 와 removeDependency(_:) 메서드를 사용해서 의존성을 추가하고 제거할 수 있습니다.
기본적으로 의존성이 있는 operation은 모든 의존하는 operation의 실행을 완료할 때까지 준비되지 않은 것으로 간주됩니다.
그러나 마지막 의존하는 operation이 완료되면 작업 객체가 준비되고 실행될 수 있게 됩니다.
NSOperation에 의해 지원되는 의존성은 의존하는 작업의 성공 실패를 구분하지 않습니다.
즉 작업을 취소하면 작업이 완료된 것과 유사하게 표시합니다.
의존하는 작업이 취소되거나 성공적으로 완료하지 못 한 경우 의존성이 있는 operation을 진행할지 여부는 사용자가 결정합니다.
이렇게 하려면 operation 객체에 몇 가지 추가적인 오류 추적하는 기능을 통합해야 할 수 있습니다.
Asynchronous Versus Synchronous Operations
oepration 큐에 추가하지 않고 수동으로 실행할 계획인 경우 동기 또는 비동기 방식으로 실행되도록 설계할 수 있습니다.
oepration는 기본적으로 동기입니다.
동기 작업에서는 oepration이 작업을 실행할 별도의 스레드를 생성하지 않습니다.
코드에서 직접 동기 oepration의 start()메서드를 호출하면 operation가 즉시 현재 스레드에서 즉시 실행됩니다.
start()메서드가 호출자에게 control을 반환할 때쯤 작업이 완료됩니다.
비동기 operation의 start() 메서드를 호출하면 해당 operation이 완료되기 전에 해당 메서드가 반환될 수 있습니다.
비동기 operation는 별도의 스레드에서 작업을 스케줄링하는 역할을 합니다.
이 operation 는 새 스레드를 직접 시작하거나, 비동기 메서드를 호출하거나, 블록을 디스패치 큐에 제출하여 실행할 수 있습니다.
control이 호출자에게 반환될 때 operation이 진행 중인지는 중요하지 않으며 진행 중일 수 있다는 점이 중요합니다.
항상 큐를 이용해서 operation을 실행할 계획이면 동기로 정의하는 것이 더 간단합니다.
operation을 수동으로 실행한다면 operation을 비동기로 정의하고자 하고 싶어서겠죠.
진행중인 작업의 상태를 모니터링해야하고 상태 변화를 KVO 노티피케이션을 사용해서 보고해야 하기 때문에 비동기 operation을 정의하는것은 더 많은 작업을 필요로합니다.
하지만 수동으로 실행된 operation이 호출 스레드를 블락하지 않는 경우 비동기 oepration을 정의하는 것이 유용합니다.
operation을 operation큐에 추가할 경우, 큐는 isUnsynchronous 프로퍼티를 무시하고 항상 start()메서드를 호출합니다.
따라서 operation을 항상 operation큐에 추가하여 실행하는 경우에는 작업을 비동기식으로 만들 필요가 없습니다.
let operationQueue = OperationQueue()
func operationStart() {
//#1
operationQueue.addOperation {
for i in 1...5 {
print("❤️", i)
}
}
//#2
let blockOperation = BlockOperation {
for i in 1...5 {
print("💚", i)
}
}
operationQueue.addOperation(blockOperation)
//#3
blockOperation.addExecutionBlock {
for i in 1...5 {
print("💛", i)
}
}
//#4
blockOperation.completionBlock = {
print("DONE")
}
}
#1
OperationQueue 에 작업을 직접 추가할 때는 addOperation을 사용합니다.
#2
BlockOperation 클래스를 사용해서 concurrent(동시) 실행할 작업을 만들 수 있습니다.
operation은 OperationQueue에 추가할 수 있습니다.
#3
BlockOperation에는 addExecutionBlock을 사용해서 실행할 작업을 추가할 수 있습니다.
#4
completionBlock을 이용해서 operation이 종료된 후 작업을 수행할 수 있습니다.
let blockOperation = BlockOperation {
for i in 1...5 {
print("💚", i)
}
}
blockOperation.start()
operation은 큐에 넣지 않고 직접 start() 메서드를 사용해서 실행할 수 있습니다.
Dependencies
func dependentOperationStart() {
var operations = [Operation]()
let op1 = BlockOperation {
for i in 1...5 {
print("❤️", i)
}
}
let op2 = BlockOperation {
for i in 1...5 {
print("💚", i)
}
}
let op3 = BlockOperation {
for i in 1...5 {
print("💛", i)
}
}
op1.addDependency(op2)
op2.addDependency(op3)
operations.append(op1)
operations.append(op2)
operations.append(op3)
op1.completionBlock = {
print("DONE - op1")
}
op2.completionBlock = {
print("DONE - op2")
}
op3.completionBlock = {
print("DONE - op3")
}
operationQueue.addOperations(operations, waitUntilFinished: false)
}
waitUntilFinished
ture일 때, 현재 스레드가 operation이 모두 끝날 때까지 block됩니다.
flase일 때, operation이 큐에 추가되고 호출자에게 즉시 control이 반환됩니다.
op3 이 끝나면 op2를 실행하고 op2가 끝나면 op1이 실행됩니다.
completionBlock은 operation이 끝나면 실행되기 때문에 다른 operation의 실행과는 관계 없습니다.
의존성이 있는 operation이 꼭 같은 큐에 들어갈 필요는 없습니다.
(데이터는 backgroundQueue에 추가하고, ui는 mainQueue에 추가)
'iOS' 카테고리의 다른 글
[iOS] UIView layer로 뷰 그리기, 그림자 (0) | 2021.01.29 |
---|---|
[iOS] frame과 bounds (1) | 2021.01.20 |
[iOS] DispatchWorkItem, DispatchGroup 알아보기 (0) | 2021.01.18 |
[iOS] DispatchQueue 알아보기 - SerialQueue, ConcurrentQueue, QoS, concurrentPerform (0) | 2021.01.18 |
[iOS] DispatchQueue 알아보기 (0) | 2021.01.18 |