티스토리 뷰
GCD | Operation |
- 간단한 일 - 메소드 위주 사용하는 작업 |
- 복잡한 일 - 데이터와 기능을 캡슐화한 객체 취소 / 순서지정 / 일시정지 (상태추적) |
Operation
• Single-Shot-Object
- 인스턴스화 → 작업을 한번만 실행가능하게 합니다
- 동일한 작업을 반복해야 하는 경우 매번 새로운 1인스턴스를 생성해야 합니다.
• 기본적으로 sync(동기)로 실행합니다.
• 동일한 작업을 반복해야 하는 경우 매번 새로운 인스턴스를 생성해야 합니다.
Operation 의 고유기능
- 취소
- 순서지정 (의존성)
- 상태 체크 (state machine)
- KVO notifications
- Qos 수준
- 우선순위 고려
- completionBlock 제공
- completion closure 내장
사용방법
input, output, main() 으로 구성하면 되며, 흐름은 아래와 같습니다.
input - 재료
main - 작업
output - 결과물
상황 | input (재료) | main() (작업) | output (결과물) |
url로 압축 파일 다운 이미지 압축파일을 압축해제 기존 이미지를 흐릿하게 편집 |
url 이미지 압축파일 이미지 |
데이터 다운로드 압축풀기 이미지 필터 적용하기 |
압축 파일 이미지 (필터된) 이미지 |
코드예시
// 기존 사진 -> 흐릿하게 변경
class TiltShiftOperation: Operation {
var inputImage: UIImage?
var outputImage: UIImage?
override func main() {
{
outputImage = tiltShift(image: inputImage)
}
}
}
let inputImage = UIImage(named: "사진.jpg")
// 오퍼레이션 인스턴스화 - 한번만 실행할 수 있는 Single-shot 객체
let tsOp = TiltShiftOperation()
tsOp.inputImage = inputImage
ts.Op.start()
// 기존 사진에서 뿌옇게 처리된 사진으로 변환됨
ts.Op.outputImage
Operartion 의 메소드, 변수
start()
- OperationQueue에 넣지 않고 독립적으로 실행할 수 있게 하는 메소드
cancel()
- 실행중인 operation을 취소 시키는 메소드
- isCancelled = true 로 변환
Operation의 4가지 상태 (LifeCycle)
• isReady
- Operation을 인스턴스화 (객체화) 하는 시점에 isReady = true 가 됩니다.
• isExecuting
- start() 메소드를 호출해 작업이 시작된 경우를 말합니다.
• isCancelled
- isFinished 이전 상태 ( isReady, isExecuting )에서 변경 가능 합니다.
• isFinished
- 작업이 완료된 경우 isFinished = true 로 변경되고 Queue에서 해당 Operation은 제거됩니다.
OperationQueue
일반적으로 Operation을 담아서 사용하는 OperationQueue (Class)
- 몇개의 Thread를 사용할건지 구체적으로 설정이 가능합니다.
- maxConcurrentOperationCount = -1 (기본값) (여러 Thread를 시스템이 알아서 사용)
- maxConcurrentOperationCount = 1 ( Serial )
- maxConcurrentOperationCount = 2 ( 2개의 Thread 사용)
- QoS(서비스 품질) 설정
- 기본값은 background 로 되어 있으나 구체적으로 설정 가능 합니다.
아래와 같이 설정
- queue.qualityOfService = .userInteractive
- queue.qualityOfService = .userInitiated
- queue.qualityOfService = .default
- queue.qualityOfService = .utility
- queue.qualityOfService = .background
- 기본값은 background 로 되어 있으나 구체적으로 설정 가능 합니다.
- Operation 추가 방법
- 클로저, 오퍼레이션, 오퍼레이션 배열 (*waitUntilFinished 인자가 존재)
- 오퍼레이션을 오퍼레이션큐에 넣었을때는 Thread에 배정되었을때 isExecuting 상태가 됩니다.
*waitUntilFinished - 오퍼레이션 큐에 있는 작업들이 다 끝날때 까지 기다립니다.
- 오퍼레이션이 한번 실행되거나, 취소되면 오퍼레이션큐를 떠남 (사라짐)
- 동기적으로 기다리는 메소드 존재 waitUntilAllOperationsAreFinished()
- 기능: 일시중지 - 재개 가능
- isSuspended = true / false 직접 설정 가능
- isSuspended = true : 기존에 실행되던 오퍼레이션은 계속 진행
- isSuspended = false : 작업재개
- isSuspended = true / false 직접 설정 가능
코드예시
// OperationQueue 생성
let printerQueue = OperationQueue()
printerQueue.maxConcurrentOperationCount = 3 // 3개의 작업이 비동기적으로 실행
// printerQueue.maxConcurrentOperationCount = 1 // 1개의 작업씩 차례대로 실행 (Serial)
// '클로저' 로도 사용할 수 있으나,
printerQueue.addOperation { print("Hello,"); sleep(3) }
printerQueue.addOperation { print("Hello,"); sleep(3) }
printerQueue.addOperation { print("This"); sleep(3) }
printerQueue.addOperation { print("is"); sleep(3) }
printerQueue.addOperation { print("Operation"); sleep(3) }
printerQueue.addOperation { print("Class"); sleep(3) }
// 아래처럼 사용할 수도 있습니다.
printerQueue.addOperation(op: Operation)
printerQueue.addOperations(ops: [Operation], waitUntilFinished: Bool)
// waitUntilFinished: true 일때
// [Operation] 이 다 끝날때 까지 기다립니다.
만약 오퍼레이션에서 완료하고 필요한 작업이 UI관련 작업이었다면 아래 두 가지 방법으로 사용하시면 됩니다.
DispatchQueue.main 또는 OperationQueue.main
BlockOperation
다른말로 closure Operation 이라고도 하며, DispatchGroup과 유사하게 동작 합니다.
사용방법
var result: Int?
// BlockOperation 생성
let summationOperation = BlockOperation {
result = 2 + 3
sleep(3)
}
// 오퍼레이션을 상속했으니 start() 메소드도 사용가능 합니다.(내부의 block들은 concurrent하게 동작하지만, 감싸고 있는 오퍼레이션 자체는 동기적으로 동작)
summationOperation.start()
result
코드예시
// BlockOperation 생성
let multiPrinter = BlockOperation()
multiPrinter.completionBlock = {
print("===모든 출력의 완료!===")
}
// addExecutionBlock에 작업들이 들어가지만 Block 내부에서 아래 5개의 명령어가 '비동기'적으로 실행 됩니다.
multiPrinter.addExecutionBlock { print("Hello,"); sleep(2) }
multiPrinter.addExecutionBlock { print("This"); sleep(2) }
multiPrinter.addExecutionBlock { print("is"); sleep(2) }
multiPrinter.addExecutionBlock { print("Operation"); sleep(2) }
multiPrinter.addExecutionBlock { print("Class"); sleep(2) }
multiPrinter.start()
// Block 내부의 작업은 '비동기'적으로 처리 됩니다.
// Class
// This
// Operation
// is
// Hello,
// ===모든 출력의 완료!===
실 사용 예시
let blockOperation = BlockOperation()
for (idx, name) in someArray.enumerated() {
blockOperation.addExecutionBlock {
// 작업 로직
}
}
blockOperation.completionBlock = {
// blockOperation의 작업들이 다 완료되면 실행되는 코드
}
비동기 오퍼레이션
비동기 오퍼레이션을 사용하려면 아래의 코드를 사용하면 됩니다.
class AsyncOperation: Operation {
// Enum 생성
enum State: String {
case ready, executing, finished
// KVO notifications을 위한 keyPath설정
fileprivate var keyPath: String {
return "is\(rawValue.capitalized)"
} // isReady/isExecuting/isFinished
}
// 직접 관리하기 위한 상태 변수 생성
var state = State.ready {
willSet {
willChangeValue(forKey: newValue.keyPath)
willChangeValue(forKey: state.keyPath)
}
didSet {
didChangeValue(forKey: oldValue.keyPath)
didChangeValue(forKey: state.keyPath)
}
}
}
extension AsyncOperation {
// 상태속성은 모두 read-only
override var isReady: Bool {
return super.isReady && state == .ready
}
override var isExecuting: Bool {
return state == .executing
}
override var isFinished: Bool {
return state == .finished
}
override var isAsynchronous: Bool { // 무조건 true로 리턴
return true
}
override func start() {
if isCancelled {
state = .finished
return
}
main()
state = .executing
}
override func cancel() {
super.cancel()
state = .finished
}
}
Quiz.
Q: Operation은 기본적으로 sync, async 둘 중 어떤걸로 설정이 되어있는지?
A: sync
Q: Operation의 상태 4 가지?
A: isReady, isExecuting, isCancelled, isFinished
Q: OperationQueue의 기본 QoS는?
A: .background
a
Q: maxConcurrentOperationCount 프로퍼티의 역할은?
A: 지정해 놓은 숫자 만큼 Operation이 동시에 몇개 까지 실행할 수 있는지 설정.
Q: maxConcurrentOperationCount 의 값이 1일 경우 ?
A: Serial 하게 동작
참고
'iOS' 카테고리의 다른 글
[iOS] TextField 앞 뒤로 공백 있을시 제거 - trimmingCharacters(in:) (0) | 2022.05.01 |
---|---|
[Swift] 초기화 (Initialization) 3/3 - init?, init!, required init (0) | 2022.04.29 |
[iOS] label 속성 (0) | 2022.04.24 |
[Swift] 초기화 (Initialization) 2/3 - convenience, designated initializer (0) | 2022.04.22 |
[Swift] 초기화 (Initialization) 1/3 (0) | 2022.04.20 |
- Total
- Today
- Yesterday
- CS 네트워크
- Swift
- swift programmers
- Swift Error Handling
- swift reduce
- Swift Leetcode
- ios
- swift protocol
- Swift init
- Combine: Asynchronous Programming with Swift
- Swift RIBs
- Swift 프로퍼티
- Swift joined
- Swift final
- Swift 프로그래머스
- Swift joined()
- Swift ModernRIBs
- RTCCameraVideoCapturer
- removeLast()
- RIBs tutorial
- 원티드 프리온보딩
- iOS error
- Swift 내림차순
- Class
- swift (programmers)
- Swift 알고리즘
- 2023년 회고
- Swift inout
- swift 고차함수
- swift property
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |