clamp
Clamp
clamp
글쓰기 관리
전체 방문자
오늘
어제
  • 분류 전체보기 (509)
    • IOS (85)
    • SwiftUI+TCA+Combine (9)
    • RxSwift + MVVM (56)
    • Clean Architecture (12)
    • SWIFT (56)
    • iOS - TDD (2)
    • 디자인패턴 (4)
    • CS (56)
      • 알고리즘 (29)
      • 운영체제 (15)
      • 자료구조 (2)
      • 네트워킹 (4)
      • 기타 (6)
    • 회고 (0)
    • Firebase (18)
    • SwiftUI (10)
    • iOS - UIKit (11)
    • iOS - 오픈소스 (6)
    • 코딩테스트 (166)
      • 프로그래머스 (164)
    • 정보처리기사 (14)
    • GitHub (2)
글쓰기 / 관리자

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ㅅ
  • uikit
  • Swift
  • Q

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
clamp

Clamp

IOS

[iOS] KVO(Key-Value Observing)

2023. 4. 10. 10:04

KVO(Key-Value-Observiing)란?

 

  • KVO는 A객체에서 A의 변경사항을 B객체에게 알리기 위해 사용하는 코코아 프로그래밍 패턴이다.
  • KVO를 사용하면 다른 개체의 특정 속성이 변경될 때 알림을 받도록 객체를 등록할 수 있다.
  • 프로퍼티 옵저버인 willSet과 didSet이랑 유사하지만 외부에 관찰자를 추가하는것이 다르다.
  • 또한 Objective-C 런타임에 의존하기 때문에 순수한 Swift에서는 그리 좋지 않다고한다...?
  • 따라서 NSObject를 상속받는 클래스로 정의해주어야 하며, 각각의 프로퍼티에는 @objc dynamic 이라는 표시를 해야한다.
  • RxSwift와 유사한 느낌이다?

 

Observing을 위한 Setup

class Address {
    var town: String
    
    init(town: String) {
        self.town = town
    }
}

town의 변경을 다른 객체에게 알리고 싶을 경우 해야하는 작업이 2가지 있다.

 

1. NSObject 상속: NSObject를 상속한 클래스에서만 KVO를 사용할 수 있다. (class 에서만 사용가능하다)

2. observe하려는 프로퍼티에 @objc 어트리뷰트와 dynamic modifier를 추가해야한다.

 

class Address: NSObject {
    @objc dynamic  var town: String
    
    init(town: String) {
        self.town = town
    }
}

 

Observer 정의

observe 하려는 프로퍼티가 변경되는지 지켜보려면 observer가 필요하다.

 

var address = Address(town: "대전광역시")

// \. <-- KeyPath 객체의 속성을 참조하는데 사용되는 경로표현식
// observe내부 구문이 옵저버가 된다.
address.observe(\.town, options: [.old, .new]) { object, change in
    print(change.oldValue, change.newValue)
}

address.town = "서울특별시"

// Optional("대전광역시") Optional("서울특별시")

1. town의 값을 "서울특별시"로 바꿈

2. 프로퍼티에 변경사항이 생기면

3. observer의 change handler가 호출되며

4. handler 내에서 oldValue와 newValue를 가져올 수 있다.

5. 변경 내용은 두번쨰로 전달되는 change로 전달된다.

 

그래서 

Optional("대전광역시") Optional("서울특별시")

가 출력된다.

 

option에는 [.old, .new] 가 추가되어 있는데 변경 내용이 필요없다면 option을 주지 않으면 된다.

 

option[

  • .old: 변경 전의 값
  • .new:  변경 후의 값
  • .initial: 초기화 시에도 observer가 불리게 할건지 라는 뜻!! 초기화시에 호출되게되면 oldValue는 nil이고 newValue는 초기화된 값이 전달된다.
  • .prior: 이전의 상태와 지금의 상태를 다주는 옵션?

 

object에는 현재 address의 town값이 들어간다.

var address = Address(town: "대전광역시")

// \. <-- KeyPath 객체의 속성을 참조하는데 사용되는 경로표현식
address.observe(\.town, options: [.old, .new]) { object, change in
    print(object.town)
}

address.town = "서울특별시"
address.town = "강원도"

// 서울특별시
// 강원도

 

궁금한점?

1. 성능상의 단점이 생긴다?

 struct의 경우 프로퍼티 옵저버를 사용하면 Static dispatch를 사용하게 되어 성능상 이점이 있다.

 

class인 경우 class는 기본적으로 dynamic dispatch를 사용하는데 dynamic을 붙힘으로써 무조건 dinamic dispatch를 사용하게 되는가?

 

하지만 NSObject를 상속하면 Objective-C 런타임에 의존하게되고, Objective-C는 Message Dispatch를 사용하게되는데 클래스 자체가 Message Dispatch를 사용하게된다면 Address클래스는 Dynamic인가 Message인가 모르겠다.

저작자표시 비영리 동일조건 (새창열림)
    'IOS' 카테고리의 다른 글
    • [iOS] Realm과 사용법
    • [iOS] some키워드?
    • [iOS] URLSessionTask failed with error: The resource could not be loaded because the App Transport Security policy requires the use of a secure connection. HTTP접근 허용
    • [iOS] SnapKit
    clamp
    clamp
    주니어 iOS개발자의 발악!!!!!!!

    티스토리툴바