원블루의 블로그
[Swift] Extension에 Stored Property 추가하는 법 (Associated Object) 본문
swift 개발을 하면서 class extension을 사용할 일이 많습니다.
extention은 굉장히 편리한 기능이긴 하지만 Stored Property(저장 프로퍼티)를 추가할 수 없다는 한계가 있습니다.
이때 Objectivie-C에서 제공하는 Associated Object 기능을 사용하면 Stored Property를 추가한 것 같은 Computed Property를 만들 수 있습니다.
작동원리
Associated Object는 대상 객체와 분리된 별도의 객체로서, 포인터 키를 통해 동적으로 대상 객체에 연결하여 구현됩니다.
UserDefaults와 동일하지는 않지만 비슷한 구조라고 생각하면 이해가 쉽습니다.
1. 포인터 키를 참조자로 대상 객체에 retain 시켜서 Associated Object를 저장합니다.
2. 이때, objc_setAssociatedObject와 objc_getAssociatedObject 함수를 통해 대상 객체에 Associated Object를 연결하거나, 연결된 Associated Object를 가져옵니다.
3. Computed Property를 선언하고 get, set을 위 함수들을 통해 구현하여 Stored Property 처럼 쓸 수있게 구현합니다.
Associated Object 함수 정리
주요함수
// 객체에 연관된 값을 연결
public func objc_setAssociatedObject(_ object: Any, // 값을 사용할 대상 객체
_ key: UnsafeRawPointer, // 고유 식별자 키
_ value: Any?, // 설정할 값
_ policy: objc_AssociationPolicy) // 메모리 관리정책
// 객체에 연관된 값을 반환
public func objc_getAssociatedObject(_ object: Any, // 값을 사용하는 대상 객체
_ key: UnsafeRawPointer) -> Any? // 고유 식별자 키
// 객체에 연관된 모든 값을 제거
// 필요한 값만 제거 하고 싶을 때는 objc_setAssociatedObject을 nil로 설정하여 제거한다.
public func objc_removeAssociatedObjects(_ object: Any) // 값을 사용하는 대상 객체
메모리 관리 정책
- .OBJC_ASSOCIATION_ASSIGN: 객체에 대한 약한 참조를 유지합니다.
- .OBJC_ASSOCIATION_RETAIN_NONATOMIC: 객체에 대한 강한 참조를 유지하며, 원자성을 보장하지 않습니다.
- .OBJC_ASSOCIATION_COPY_NONATOMIC: 값을 복사하여 보관하며, 원자성을 보장하지 않습니다.
- .OBJC_ASSOCIATION_RETAIN: 객체에 대한 강한 참조를 유지하며, 원자성을 보장합니다.
- .OBJC_ASSOCIATION_COPY: 값을 복사하여 보관하며, 원자성을 보장합니다.
예제
UIView extension에 String 변수를 추가하는 예제 코드입니다.
import UIKit
extension UIView {
private struct AssociatedKeys {
static var customString = "customString"
}
var customString: String? {
get {
return withUnsafePointer(to: &AssociatedKeys.customString) {
return objc_getAssociatedObject(self, $0) as? String
}
}
set {
withUnsafePointer(to: &AssociatedKeys.customString) {
objc_setAssociatedObject(self, $0, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
}
다음 포스트
2024.07.02 - [iOS 개발] - [Swift][Associated Object] UIView에 GestureRecognizer 쉽게 붙이기 + Highlight 인식하기
'iOS 개발' 카테고리의 다른 글
Xcode16 에서 iOS13, iOS14 Could not locate device support files 빌드 디버깅 불가 오류 (0) | 2024.10.02 |
---|---|
[Swift] 스와이프로 이전 화면 이동하기 NavigationController Pop Gesture (0) | 2024.09.13 |
[Swift] UILabel의 attributedText에 lineHeight 줄간격 설정하기 (0) | 2024.08.22 |
[Swift] 다국적 사용자 대응 DateFormatter 불기력 서기력(그레고리) 변환 정리 (0) | 2024.07.05 |
[Swift][Associated Object] UIView에 GestureRecognizer 추가 코드 간략화 + Highlight 인식하기 (0) | 2024.07.02 |