시작
공식문서에서 MapKit의 Annotation 예제를 살펴보던 중
@objc dynamic var
라는 키워드가 나오더라고요.
MKAnnotation - coordinate 공식문서
Realm에서도 이런 키워드를 봤던 거 같은데,
그래서 오늘 간단히 한번 정리해 보고 넘어가려고 글을 적게 됐습니다.
정적(static) / 동적(dynamic) 디스패치
들어가기 전에 간단히 차이섬을 알아봅시다.
👉 정적(static) 디스패치
컴파일러가 컴파일 시점에 호출해야 할,
메서드의 실제 위치를 미리 알고 있기 때문에, 매우 빠르게 동작합니다.
컴파일 타임에 결정이 되기 때문에, 상대적으로 속도 빠릅니다.
모든 구조체는 이와 같이 동작합니다.
대신 클래스에서는 상속을 못하게 되므로 객체지향 프로그래밍의
다형성을 구현하지 못하죠.
👉 동적(dynamic) 디스패치
런타임 시점에 호출될 메서드 또는 속성을 결정합니다.
(오직 class에서만 사용 가능)
정적 디스패치와 반대로
런타임 시점에 호출할 메서드를 알아내기 때문에,
상속 관계에서 오버라이드(override)한 자식 클래스의 메서드를 호출가능 해집니다.
대신 어떤 메서드가 호출될지 정확히 모르므로 성능 및 속도가 떨어지죠.
조금 더 자세하게 말하면,
각 클래스는 vTable을 생성하여 이를 객체의 인스턴스에 연결합니다.
객체가 메서드를 호출할 때마다 해당 vTable에서는
"부모 메서드인가? 자식 메서드인가?" 위치를 찾은 후 메서드를 실행하게 되므로
속도가 상대적으로 떨어지게 되는 거죠.
동적(dynamic) 디스패치가 필요하지 않은 경우의 최적화 방법으로는
final 키워드를 사용 ("override가 필요 없다" 명시적으로 표시. 최적화 가능),
private 키워드 사용(내부에서만 참조를 보장) 등이 있습니다.
@objc dynamic
swift에서는 기본적으로 정적 디스패치를 사용하지만,
Objective-C의 동적 디스패치 기능을 사용하기 위해 사용됩니다.
Objective-C와 상호 운영성을 유지하게 도와주죠.
@objc dynamic var
를 사용하게 되면
런타임 시 동적으로 동작이 결정이 되므로 프로퍼티가 변경되었을 때,
KVO(Key-Value Observing)를 통해 관찰이 가능해집니다.
런타임에서 프로퍼티의 값이 변경될 때마다,
시스템이 자동적으로 프로퍼티 관찰자(@objc dynamic var
)를 호출하고 값을 업데이트할 수 있습니다.
하지만 동적으로 처리되므로 컴파일러가 해당 프로퍼티를 최적화할 수 없다고 하네요.
당연히 성능상 이유로도 남용해서는 안 되겠죠?
간단히 KVO(Key-Value Observing) 코드를 봅시다.
// Objective-C에서 처리를 하므로 NSObject를 상속 해줘야 합니다.
class CustomMap: NSObject {
@objc dynamic var coordinate: Double
init(coordinate: Double) {
self.coordinate = coordinate
}
}
var map = CustomMap(coordinate: 5)
// coordinate 값이 변할 때 observe handler가 동작 합니다
// options을 통해 사용하고 싶은 기능을 추가하면 된다.
// .old(이전 값), .new(변한 값), .prior(이전/현재 여부), .initial(처음 생성 값)
map.observe(\.coordinate, options: [.old, .new, .initial]) { object, change in
// isPrior의 값이 true면 이전값을 false면 현재값을 나타냄
print(object.coordinate, change.isPrior)
// 이전 값, 변한 현재 값 (만약 이전 값이 없으면 nil)
print(change.oldValue, change.newValue)
}
// 5.0 false --- 이전 값(object.coordinate, change.isPrior)
// nil Optional(5.0) --- initial 사용 시(change.oldValue, change.newValue)
// 값을 변경 하게 되면
map.coordinate = 10
// 10.0 false --- 현재 값(object.coordinate, change.isPrior)
// Optional(5.0) Optional(10.0) --- change.oldValue, change.newValue
참고
https://myssun0325.tistory.com
Key-Value Observing Programming Guide
'UIKit > Swift' 카테고리의 다른 글
[iOS/Swift] NavigationController의 ToolBar를 코드로 만들어 봅시다 (0) | 2023.04.10 |
---|---|
[iOS/Swift] Life Cycle의 loadView (0) | 2023.03.31 |
[iOS/Swift] 유닛 테스트(Unit Test) 사용 방법 (2) | 2023.02.20 |
[iOS/Swift] 디버깅을 통해 메모리 누수를 찾아보자(Debug, Memory Leaks) (0) | 2023.02.17 |
[iOS/Swift] MVVM 패턴의 Data Binding에 대해서 알아보자! (Closure, Observable, Combine) (0) | 2023.02.14 |