본문 바로가기

야곰커리어캠프_TIL

20220224 / D12 / KVO와 Notification의 장단점 및 Init과 self에대한 궁금증

- Reference

- https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#:~:text=Default%20Property%20Values,in%20this%20chapter.
- https://www.hackingwithswift.com/example-code/language/what-is-key-value-observing](https://www.hackingwithswift.com/example-code/language/what-is-key-value-observing)
- https://leechamin.tistory.com/505](https://leechamin.tistory.com/505)

 

# KVO
[정의]
- kvo란 다른 개체의 속성이 변경 될때 개체가 직접 알림을 받을 수 있도록하는 매커니즘이다.
[NOTE]
- KVO는 오브젝트-C의 최상위 클래스인 NSObject를 상속받은 것만 사용할 수 있어 class에대한 내용만 해당이된다. 그래서 일반적으로 class를 지칭할때 사용하는 객체라는 단어가 더 적합하여 객체라고 부른다.
[장점]
- 두 객체 사이의 정보를 맞춰주는 것이 쉽다.
- new/old 의 값을 얻을 수 있다.
[단점]
- NSObject를 상속받은 객체만 사용할 수 있다.
- 프로퍼티에 한해서만 값이 변경되는것을 지켜볼 수 있다.
- 서로를 알아야하기때문에 결합도가 높아 재사용성이 떨어진다.

@objc class Person: NSObject {
    @objc dynamic var name = "quokka"
}
let quokka = Person()

quokka.observe(\Person.name, options: .new) { person, change in
    print("하이루 \(person.name)")
}

quokka.name = "컼카"
quokka.name = "쿼카"


# Notification
[정의] 
나를 구독한 사람에게 이벤트가 발생했을때 나에대한 이벤트정보를 알려준다. (like 인스타 라이브 매커니즘)
[장점]
- 코드 구현이 비교적 쉽다.
- 다수의 객체들에게 동시에 알림을 줄 수 있다.
[단점]
- 신호를 알려는 주지만 value값을 잘 받았는지는 확인이 불가함
- 간접적으로 알림들 전달하기때문에 정보추적이 어렵다.
- post 이후에 정보를 받을 수 없다.

// 보고싶은 방송 매체를 정한다.
extension Notification.Name {
    static let knowingBro = Notification.Name("아는형님")
}

// 방송 매체 구독을 한다.
class Program {
    func post() {
        NotificationCenter.default.post(name: .knowingBro, object: nil)
    }
}

// 방송 시작 알림
class Observer {
    func add() {
        NotificationCenter.default.addObserver(self, selector: #selector(startMessage), name: .knowingBro, object: nil)
    }
    
    @objc func startMessage() {
        print("아는형님 방송이 시작되었어요~")
    }
}

let observer = Observer()
observer.add()
Program().post() // 아는형님 방송이 시작되었어요~


이해를 잘 한건지 모르겠음,,(졸리당)

# KVO vs Notification 을 나누는 기준
- 결합도를 느슨하게 중간매개체를 이용해 신호를 전달할 것이냐 직접적으로 누군지를 알고있는상태에서 전달할것이냐?

# 궁금증 해결


# self의 사용법
- self는 기본적으로 init시 프로퍼티이름이 겹치는 경우나 클로저, 함수형프로그래밍 사용중 어떠한 프로퍼티를 참조하는지 명시해주어야할 상황에 사용한다고 한다. 그외에는 팀의 컨벤션에따라서 써줘야하면 사용하고 아니면 마는정도로 협의해서 사용하면된다. 그런데 리뷰어 개굴의 견해는 기본적으로 self는 써주지않는다고한다. 오히려 가독성을 떨어트릴 수 있어 정말 위처럼 필요한 상황에만 명시한다.

# initialization [값이 있음을 보장해주는 역할이다. (단, 옵셔널은 예외)]
- 이니셜라이저란 공식문서에 의하면 타입(열거,구조,클래스)를 사용하기위해 인스턴스를 준비하는 과정이라고 알려져있는데 옵셔널이 아닌이상 기본값을 기입하거나 init으로 값을 초기화할 수 있게 seting해주어야한다.

[NOTE]
- 속성이 항상 동일한 초기값을 사용하는 경우 이니셜라이저 내에서 값으 설정하는 것보다 기본값을 제공해라라는 문구가 있다.
그에따른 근거는 3가지가 있었다.
1. 기본값을 지정하거나 init을 사용해주거나 결과는 동일하지만 기본값은 프로퍼티의 초기화 선언과 더 밀접하게 연결한다.
2. 그리고 더짧고 명확한 이니셜라이저를 만들고 기본값에서 프로퍼티 유형을 유추할 수 있다.
3. 또한 기본값을 사용하면 기본 이니셜라이저 및 이니셜라이저 상속을 더 쉽게 할 수 있다.

# struct에는 멤버와이즈 이니셜라이저가 제공이 되는 이유
- class는 상속이라는 기능이 존재한다. 상속이란 기존에 상속 받을 타입에 특성을 모두 가져온다. 그래서 상속을 받으면 상속받은 자신클래스의 프로퍼티 이니셜라이저를 작성하고 그 다음에 부모클래스의 이니셜라이저를 초기화해야하는 의무가 생긴다. 


예시)
init(a: String, b: String) {
	self.a = a
	self.b = b
	super.init()을 초기화한다.
}



하지만 struct는 상속의 기능을 지원하지않아 init에 대한 책임이 별로 없다. 그래서 struct는 굳이 상속기능도 없는데 기본값이 없으면 멤버와이즈 이니셜라이저를 제공해주자 ~ 라는 의미를 담고 있다고 야곰이 말했다.