杨锴
2024-08-14 909e20941e45f8712c012db602034b47da0bfdb0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//
//  NSTextView+Rx.swift
//  RxCocoa
//
//  Created by Cee on 8/5/18.
//  Copyright © 2018 Krunoslav Zaher. All rights reserved.
//
 
#if os(macOS)
 
import Cocoa
import RxSwift
 
/// Delegate proxy for `NSTextView`.
///
/// For more information take a look at `DelegateProxyType`.
open class RxTextViewDelegateProxy: DelegateProxy<NSTextView, NSTextViewDelegate>, DelegateProxyType, NSTextViewDelegate {
 
    #if compiler(>=5.2)
    /// Typed parent object.
    /// 
    /// - note: Since Swift 5.2 and Xcode 11.4, Apple have suddenly
    ///         disallowed using `weak` for NSTextView. For more details
    ///         see this GitHub Issue: https://git.io/JvSRn
    public private(set) var textView: NSTextView?
    #else
    /// Typed parent object.
    public weak private(set) var textView: NSTextView?
    #endif
 
    /// Initializes `RxTextViewDelegateProxy`
    ///
    /// - parameter textView: Parent object for delegate proxy.
    init(textView: NSTextView) {
        self.textView = textView
        super.init(parentObject: textView, delegateProxy: RxTextViewDelegateProxy.self)
    }
 
    public static func registerKnownImplementations() {
        self.register { RxTextViewDelegateProxy(textView: $0) }
    }
 
    fileprivate let textSubject = PublishSubject<String>()
 
    // MARK: Delegate methods
 
    open func textDidChange(_ notification: Notification) {
        let textView: NSTextView = castOrFatalError(notification.object)
        let nextValue = textView.string
        self.textSubject.on(.next(nextValue))
        self._forwardToDelegate?.textDidChange?(notification)
    }
 
    // MARK: Delegate proxy methods
 
    /// For more information take a look at `DelegateProxyType`.
    open class func currentDelegate(for object: ParentObject) -> NSTextViewDelegate? {
        object.delegate
    }
 
    /// For more information take a look at `DelegateProxyType`.
    open class func setCurrentDelegate(_ delegate: NSTextViewDelegate?, to object: ParentObject) {
        object.delegate = delegate
    }
 
}
 
extension Reactive where Base: NSTextView {
 
    /// Reactive wrapper for `delegate`.
    ///
    /// For more information take a look at `DelegateProxyType` protocol documentation.
    public var delegate: DelegateProxy<NSTextView, NSTextViewDelegate> {
        RxTextViewDelegateProxy.proxy(for: self.base)
    }
 
    /// Reactive wrapper for `string` property.
    public var string: ControlProperty<String> {
        let delegate = RxTextViewDelegateProxy.proxy(for: self.base)
 
        let source = Observable.deferred { [weak textView = self.base] in
            delegate.textSubject.startWith(textView?.string ?? "")
        }.take(until: self.deallocated)
 
        let observer = Binder(self.base) { control, value in
            control.string = value
        }
 
        return ControlProperty(values: source, valueSink: observer.asObserver())
    }
 
}
 
#endif