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 |
Tags
- Human interface guide
- ios
- swift documentation
- HIG
- Protocol
- uiscrollview
- 리펙터링
- swiftUI
- 리팩토링
- combine
- Observable
- collectionview
- uitableview
- RxCocoa
- 스위프트
- clean architecture
- 애니메이션
- Refactoring
- rxswift
- 클린 코드
- UITextView
- 리펙토링
- Clean Code
- Xcode
- map
- UICollectionView
- SWIFT
- tableView
- MVVM
- ribs
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] DispatchQueue.main.sync 사용 시 주의사항 (Deadlock) 본문
iOS 응용 (swift)
[iOS - swift] DispatchQueue.main.sync 사용 시 주의사항 (Deadlock)
jake-kim 2021. 7. 5. 23:30Deadlock (교착 상태)
- 두 개 이상의 process 및 thread가 서로 상대방의 작업이 끝나기만을 기다리고 있어서 task들을 처리하지 못하는 상태
ex) deadlock
- Serial Queue인 상황: 한 번에 하나의 작업만 가능 > 내부에 sync한 작업이 존재 > deadlock 발생
let testQueue = DispatchQueue(label: "testQueue") // concurrent선언하지 않았으므로 디폴트인 Serial Queue
testQueue.async {
testQueue.sync {
// 외부 블록이 완료되기 전에 내부 블록이 시작되지 않는 상태
// 외부 블록은 내부 블록이 완료되기를 기다리는 상태
}
// 영원히 실행되지 않는 부분
}
- 해결 방법: Serial Queue > Concurrent Queue 변경
let testQueue = DispatchQueue(label: "testQueue", attributes: .concurrent)
DispatchQueue.main.sync의 deadlock
- DispatchQueue.main은 프로그램의 메인 스레드에서 작업을 실행하는 전역적으로 사용 가능한 serial queue
- DispatchQueue.main는 concurrent queue가 아님을 주의
- DispatchQueue.main은 run loop와 함께 동작
- run loop의 다른 이벤트 처리와 조율해주는 역할
- DispatchQueue.main.sync를 호출하게 되면 끊임없이 앱의 이벤트 처리를 하고 있던 main thread가 sync호출에 의해 멈추게 되고 deadlock 발생
- DispatchQueue.main.sync 사용 경우
- background thread에서 이루어지는 작업들 사이에 순서에 맞게 main thread에서 작업이 이루어져야 할 때 사용
- Background thread 내에서 사용하는 것이 아니면 DispatchQueue.main.sync 사용을 지양
DispatchQueue.global().async {
// UI 업데이트 전 실행되는 코드
DispatchQueue.main.sync {
// UI 업데이트
}
// UI 업데이트 후 실행되는 코드
}
DispatchQueue.main.sync 사용 예제2 - Apple 문서
- 사용처: Background Thread에서 작업이 진행되는 중 UI 업데이트 이루어져야 하는 상황
- TableView나 CollectionView에 셀을 추가하거나 제거하는 작업이 진행 중 > 네트워크 통신과 같은 다른 비동기 작업으로 인해 DataSource의 데이터가 변경 > (셀을 추가하거나 제거하는 작업이 아직 안끝난 상태) > DataSource의 데이터와 View가 일치하지 않아 에러 발생 > 방지위해 DispatchQueue.main.sync 사용
- 사진 앨범의 DataSource와 업데이트한 콜렉션 뷰의 데이터가 달라지는 상황을 방지하기 위해 DispatchQueue.main.sync사용
- PHPPhotoLibraryChangeObserver 애플 문서
// PHPhotoLibraryChangeObserver 애플 문서
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let collectionView = self.collectionView else { return }
DispatchQueue.main.sync {
if let albumChanges = changeInstance.changeDetails(for: assetCollection) {
assetCollection = albumChanges.objectAfterChanges! as! PHAssetCollection
navigationController?.navigationItem.title = assetCollection.localizedTitle
}
if let changes = changeInstance.changeDetails(for: fetchResult) {
fetchResult = changes.fetchResultAfterChanges
if changes.hasIncrementalChanges {
collectionView.performBatchUpdates({
if let removed = changes.removedIndexes where removed.count > 0 {
collectionView.deleteItems(at: removed.map { IndexPath(item: $0, section:0) })
}
if let inserted = changes.insertedIndexes where inserted.count > 0 {
collectionView.insertItems(at: inserted.map { IndexPath(item: $0, section:0) })
}
if let changed = changes.changedIndexes where changed.count > 0 {
collectionView.reloadItems(at: changed.map { IndexPath(item: $0, section:0) })
}
changes.enumerateMoves { fromIndex, toIndex in
collectionView.moveItem(at: IndexPath(item: fromIndex, section: 0),
to: IndexPath(item: toIndex, section: 0))
}
})
} else {
collectionView.reloadData()
}
}
}
}
* 참고
https://developer.apple.com/documentation/photokit/phphotolibrarychangeobserver
'iOS 응용 (swift)' 카테고리의 다른 글
[iOS - swift] SnapKit (스냅킷, 오토레이아웃) 필수로 알아야 하는 것 (0) | 2021.07.11 |
---|---|
[iOS - swift] 코드로 xib파일을 얻는 Protocol 정의 (StoryboardInstantiable) (0) | 2021.07.11 |
[iOS - swift] 코드에서 이미지, 색상 확인 방법 Literal (#ImageLiteral, colorLiteral) (0) | 2021.07.05 |
[iOS - swift] NSExpression (0) | 2021.07.03 |
[iOS - swift] NSPredicate (핸드폰 번호, 이메일, 패스워드 정규성 검사, CoreData 쿼리) (0) | 2021.07.03 |
Comments