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
- Human interface guide
- Observable
- Protocol
- rxswift
- RxCocoa
- 스위프트
- combine
- uiscrollview
- MVVM
- ios
- 리펙터링
- Refactoring
- tableView
- UITextView
- swiftUI
- clean architecture
- Xcode
- 클린 코드
- ribs
- 리팩토링
- 리펙토링
- UICollectionView
- uitableview
- map
- collectionview
- SWIFT
- swift documentation
- 애니메이션
- Clean Code
- HIG
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] NSMapTable, weakCache 개념 (딕셔너리와 차이점, weak reference, thread safe) 본문
iOS 응용 (swift)
[iOS - swift] NSMapTable, weakCache 개념 (딕셔너리와 차이점, weak reference, thread safe)
jake-kim 2023. 8. 25. 01:53NSMapTable 개념
- key-value쌍으로 구송하는 컬렉션 타입 중 하나인 Dictionary와 유사하지만 memory 관리를 더욱 디테일하게 처리가 가능한 클래스
- 딕셔너리는 value type이지만 NSMapTable은 class타입이므로 reference type
- 딕셔너리는 key-value쌍으로 value에 object를 넣으면 strong reference로 잡히지만, NSMapTable은 통해 weak 설정이 가능
- NSMapTable은 멀티 스레드 환경에서도 안전하게 사용할 수 있는 thread safe 속성도 가지고 있는 장점이 존재
NSMapTable로 메모리 캐싱 구현
- NSMapTable의 Value 타입에 사용할 class 타입 CachedObject 정의 하나와 NSMapTable 타입인 cache 변수를 전역적으로 선언
- NSMapTable을 초기화 할 땐 여러가지 방법이 있는데 대표적인 방법은 strongToWeakObjects() 스태틱 함수 사용
- strongToWeakObjects: key값은 strong, Value값은 weak로 참조한다는 의미
import Foundation
class CachedObject: NSObject {
let value: Int
init(value: Int) {
self.value = value
}
}
let cache = NSMapTable<NSString, CachedObject>.strongToWeakObjects()
사용하는곳)
- viewDidLoad에서 cache에 setObject로 값을 세팅하고나서, 이 값들은 전역적으로 저장하는 상태
- 저장하다가 viewDidLoad에서 removeAll()을 수행
- viewDidAppear에서 과연 Value타입들이 살아 있는지 확인 > objects들은 메모리 해제 되었는지 확인
class ViewController: UIViewController {
var objects = [CachedObject]()
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...5 {
let key = "Key\(i)" as NSString
let object = CachedObject(value: i)
objects.append(object)
cache.setObject(object, forKey: key)
}
objects.removeAll()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
for i in 1...5 {
let key = "Key\(i)" as NSString
if let cachedObject = cache.object(forKey: key) {
print("캐시성공 > \(key): \(cachedObject.value)")
} else {
print("캐시실패 > \(key)")
}
}
}
}
- viewDidAppear에서 objects들은 메모리 해제된 상태
/*
캐시실패 > Key1
캐시실패 > Key2
캐시실패 > Key3
캐시실패 > Key4
캐시실패 > Key5
*/
- 만약 cache를 strongToStrongObjects()로 초기화하면 Value타입을 strong reference로 가지고 있으므로 메모리 해제되지 않음
//let cache = NSMapTable<NSString, CachedObject>.strongToWeakObjects()
let cache = NSMapTable<NSString, CachedObject>.strongToStrongObjects()
/*
캐시성공 > Key1: 1
캐시성공 > Key2: 2
캐시성공 > Key3: 3
캐시성공 > Key4: 4
캐시성공 > Key5: 5
*/
정리
- key-value쌍으로 O(1)로 데이터를 저장하는 자료구조는 Dictionary와 NSMapTable이 존재
- Dictionrary는 가장 간단한 형태
- NSMapTable은 weak로 reference를 잡을 수 있어서 메모리 관리 상 디테일하게 처리가 가능
- 따로 weak와 같은 메모리 관리와 thread safe하게 처리할 필요가 없는 데이터를 관리하고 싶은 경우 Dictionary를 사용하고 메모리 관리가 필요하다면 NSMapTable 사용
- weak var와 마찬가지로 NSMapTable도 weak reference로 key나 value를 관리하다보면 약간의 오버헤드가 있을 수 있음
* 전체 코드: https://github.com/JK0369/ExNSMapTable
* 참고
https://developer.apple.com/documentation/foundation/nspointerfunctionsoptions
https://developer.apple.com/documentation/foundation/nsmaptable
'iOS 응용 (swift)' 카테고리의 다른 글
Comments