Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- Observable
- 리펙터링
- Clean Code
- 리팩토링
- uiscrollview
- ribs
- collectionview
- uitableview
- swiftUI
- 스위프트
- ios
- Refactoring
- clean architecture
- 애니메이션
- rxswift
- swift documentation
- Xcode
- RxCocoa
- MVVM
- 리펙토링
- 클린 코드
- HIG
- UICollectionView
- Human interface guide
- UITextView
- combine
- SWIFT
- Protocol
- tableView
- map
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] NSOperation, Operation, BlockOperation, Custom Operation 사용 방법 (Concurrency) 본문
iOS 응용 (swift)
[iOS - swift] NSOperation, Operation, BlockOperation, Custom Operation 사용 방법 (Concurrency)
jake-kim 2022. 1. 3. 23:39GCD대신 NSOperation 사용하는 경우 (= GCD에서 구현하기 어려운 기능)
- 작업 중 cancel 기능이 필요한 경우
- 작업 시작전에 특별한 다른 작업이 먼저 실행되게끔 하고 싶은 경우
- 작업들의 실행에 우선순위를 주어서 실행 순서를 정하고 싶은 경우
- Operation을 서브클래싱하여 작업을 cancel, start하는 것과 같이 작업에 대한 상태를 관리하고 싶은 경우
NSOperation
- NSOperation은 직접 사용할 수 없는 추상 클래스이므로 NSOperation 서브 클래스로 사용
- addDependency(op:)메소드를 통해, 어떤 작업 전 다른 것이 먼저 실행됨을 보장할 때 사용 가능
- queue의 실행 우선 순위를 정할 수 있는 장점
public enum NSOperationQueuePriority : Int { case VeryLow case Low case Normal case High case VeryHigh }
- 지정된 대기열에 대한 특정 작업이나 모든 작업을 cancen() 메소드를 통해 취소 가능
- 내부의 상태 프로퍼티 finished, ready 를 통해 작업의 진행 상황을 확인 가능
- NSOperation에는 작업이 완료되면 완료 블록이 호출되도록 설정하는 옵션이 존재
NSOperation의 상태
- isReady: instantiated 시 해당 상태로 전환
- isExecuting: start() 메소드 호출 시 해당 상태로 전환
- isFinished: 작업이 끝난 경우
- isCncelled: cancel() 메소드 호출 시 해당 상태로 전환
Operation의 사용 1. BlockOperation (Operation의 구현체 중 하나)
- 하나 이상의 block 객체를 동시에 실행하기 위해 있는 그대로 사용하는 클래스
- sync + concurrency
- 사용: BlockOperation() 객체 사용
let operation = BlockOperation()
operation.addExecutionBlock {
print("a is main thread? (\(Thread.isMainThread))")
for i in 0...3 {
print("a(\(i))")
}
}
operation.addExecutionBlock {
print("b is main thread? (\(Thread.isMainThread))")
for i in 0...3 {
print("b(\(i))")
}
}
operation.start()
/*
b is main thread? (false)
a is main thread? (true)
a(0)
b(0)
a(1)
a(2)
a(3)
b(1)
b(2)
b(3)
*/
Operation의 사용 2. Custom Operation
- Operation을 서브클래싱하여 main() 부분을 구현
- 위에서 확인한 것과 같이 Main Thread에서 operation을 실행시키므로, main thread에서 동작
class MyOperation: Operation {
override func main() {
print("is main thread? (\(Thread.isMainThread))")
for i in 0...900000 {
print(i)
}
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let operation = MyOperation()
operation.start()
/*
is main thread? (true)
0
1
2
3
4
...
*/
}
- background에서 동작하게끔 하는 방법: start()를 재정의하여 main()부가 background thread에서 불리도록 설계
- cancel일 경우 작업을 취소
class MyConcurrentOperations: Operation {
override func start() {
Thread.init(block: main).start() // 첫번째 실행도 background에서 동작하도록 start() 메소드 내부에서 main을 실행하도록 설계
}
override func main() {
print("is main thread? (\(Thread.isMainThread))")
for i in 0...900000 {
guard isCancelled == false else { return }
print(i)
}
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let operation = MyConcurrentOperations()
operation.start()
sleep(1)
operation.cancel()
/*
is main thread? (false)
0
1
2
3
4
...
23123
*/
}
- 이 밖에도 isAsynchronous, isExecuting, 등의 프로퍼티 사용 가능
// 출처: https://medium.com/shakuro/nsoperation-and-nsoperationqueue-to-improve-concurrency-in-ios-e31ee79c98ef
class AsynchronousOperation: Operation {
enum State: String {
case Ready
case Executing
case Finished
private var keyPath: String {
get {
return "is" + self.rawValue
}
}
}
var state: State = .Ready {
willSet {
willChangeValue(forKey: newValue.rawValue)
willChangeValue(forKey: newValue.rawValue)
}
didSet {
didChangeValue(forKey: oldValue.rawValue)
didChangeValue(forKey: oldValue.rawValue)
}
}
override var isAsynchronous: Bool {
get {
return true
}
}
override var isExecuting: Bool {
get {
return state == .Executing
}
}
override var isFinished: Bool {
get {
return state == .Finished
}
}
override func start() {
if self.isCancelled {
state = .Finished
} else {
state = .Ready
main()
}
}
override func main() {
if self.isCancelled {
state = .Finished
} else {
state = .Executing
//Asynchronous logic (eg: n/w calls) with callback {
}
}
}
* 참고
'iOS 응용 (swift)' 카테고리의 다른 글
Comments