RxSwift를 이제 막 배우고 있는데 여러가지 의문이 들었습니다.
그래서 소스코드를 조금 살펴보고 결론을 내렸습니다. 아래는 제가 공부한 내용이고 말투는 편하게 하겠습니다.
우선 먼저 이해해야할 것들부터 보자.
Reactive.swift파일은 아래와 같다.
/* Reactive.swift */
public struct Reactive<Base> {
/// Base object to extend.
public let base: Base
/// Creates extensions with base object.
///
/// - parameter base: Base object.
public init(_ base: Base) {
self.base = base
}
}
/// A type that has reactive extensions.
public protocol ReactiveCompatible {
/// Extended type
associatedtype ReactiveBase
@available(*, deprecated, message: "Use `ReactiveBase` instead.")
typealias CompatibleType = ReactiveBase
/// Reactive extensions.
static var rx: Reactive<ReactiveBase>.Type { get set }
/// Reactive extensions.
var rx: Reactive<ReactiveBase> { get set }
}
extension ReactiveCompatible {
/// Reactive extensions.
public static var rx: Reactive<Self>.Type {
get {
return Reactive<Self>.self
}
set {
// this enables using Reactive to "mutate" base type
}
}
/// Reactive extensions.
public var rx: Reactive<Self> {
get {
return Reactive(self)
}
set {
// this enables using Reactive to "mutate" base object
}
}
}
import class Foundation.NSObject
/// Extend NSObject with `rx` proxy.
extension NSObject: ReactiveCompatible { }
우선 ReactiveCompatible를 보도록 하자. extension 부분을 보면 public var rx: Reactive로 선언된 Computed Property를 볼 수 있다. get에는 return Reactive(self)이다.
즉 ReactiveCompatible를 채택할 class에 rx라는 Computed Property를 추가하는데, 그 프로퍼티는 Reactive라는 struct이다. 그리고 이 struct는 앞의 class 타입의 base 프로퍼티를 가지게 된다.
/* 예시 코드 */
extension AClass: ReactiveCompatible { }
let aClass = AClass()
print(type(of: aClass.rx.base)) // AClass가 출력된다.
예를 들어, AClass에 ReactiveCompatible를 채택하면, 이 AClass의 인스턴스(aClass)에는 rx 프로퍼티로 접근할 수 있는 어떤 struct의 인스턴스가 생기고 이 인스턴스는 AClass타입의 base를 갖는다.
(aClass.rx).base라고 생각하면 편하다. 괄호 안 부분이 Reactive라는 struct의 인스턴스이다.
다시 윗쪽의 Reactive.swift파일로 돌아가자. 맨 밑에줄을 보면
extension NSObject: ReactiveCompatible { } 이 있다.
즉 모든 NSObject에 rx속성을 추가하는 것이다. rx속성은 Computed Property이기 때문에 NSObject를 상속받는 모든 class는 자기 자신의 타입을 갖는 rx.base를 가지게 될것이다.
자 이제 UIButton+Rx.swift파일을 보자. 딴건 필요없고 제일 윗쪽을 보면,
/* UIButton+Rx.swift */
extension Reactive where Base: UIButton {
/// Reactive wrapper for `TouchUpInside` control event.
public var tap: ControlEvent<Void> {
return controlEvent(.touchUpInside)
}
}
이렇게 되어있는데 Reactive에 tap속성을 확장시킨 것이다.
설명하면, UIButton의 인스턴스는 rx속성을 가진다(NSObject의 후손이기 때문에). 이때 button.rx는 Reactive 구조체의 인스턴스인데 이 구조체가 tap 속성을 가지므로 확장된 tap은 button.rx.tap처럼 rx로 접근하게 되는 것이다.