From b2ab778817b789d54dd255e99d7affc980413fca Mon Sep 17 00:00:00 2001 From: kamikuo Date: Fri, 20 May 2022 15:46:37 +0800 Subject: [PATCH 1/2] add editing status publishers for UITextField and UITextView --- .../Controls/UITextField+Combine.swift | 15 ++++++++ .../Controls/UITextView+Combine.swift | 37 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/Sources/CombineCocoa/Controls/UITextField+Combine.swift b/Sources/CombineCocoa/Controls/UITextField+Combine.swift index 96b6c72..891c586 100644 --- a/Sources/CombineCocoa/Controls/UITextField+Combine.swift +++ b/Sources/CombineCocoa/Controls/UITextField+Combine.swift @@ -33,5 +33,20 @@ public extension UITextField { var didBeginEditingPublisher: AnyPublisher { controlEventPublisher(for: .editingDidBegin) } + + /// A publisher emitting on end the editing. + var didEndEditingPublisher: AnyPublisher { + controlEventPublisher(for: .editingDidEnd) + } + + /// A publisher emits on first responder changes + var isFirstResponderPublisher: AnyPublisher { + Just(()) + .merge(with: didBeginEditingPublisher, didEndEditingPublisher) + .map { [weak self] in + self?.isFirstResponder ?? false + } + .eraseToAnyPublisher() + } } #endif diff --git a/Sources/CombineCocoa/Controls/UITextView+Combine.swift b/Sources/CombineCocoa/Controls/UITextView+Combine.swift index 283cd58..4ead047 100644 --- a/Sources/CombineCocoa/Controls/UITextView+Combine.swift +++ b/Sources/CombineCocoa/Controls/UITextView+Combine.swift @@ -30,5 +30,42 @@ public extension UITextView { } var textPublisher: AnyPublisher { valuePublisher } + + /// Combine wrapper for `textViewDidBeginEditing(_:)` + var didBeginEditingPublisher: AnyPublisher { + let selector = #selector(UITextViewDelegate.textViewDidBeginEditing(_:)) + return delegateProxy.interceptSelectorPublisher(selector) + .map { _ in () } + .eraseToAnyPublisher() + } + + /// Combine wrapper for `textViewDidEndEditing(_:)` + var didEndEditingPublisher: AnyPublisher { + let selector = #selector(UITextViewDelegate.textViewDidEndEditing(_:)) + return delegateProxy.interceptSelectorPublisher(selector) + .map { _ in () } + .eraseToAnyPublisher() + } + + /// A publisher emits on first responder changes + var isFirstResponderPublisher: AnyPublisher { + Just(()) + .merge(with: didBeginEditingPublisher, didEndEditingPublisher) + .map { [weak self] in + self?.isFirstResponder ?? false + } + .eraseToAnyPublisher() + } + + @objc override var delegateProxy: DelegateProxy { + TextViewDelegateProxy.createDelegateProxy(for: self) + } +} + +@available(iOS 13.0, *) +private class TextViewDelegateProxy: DelegateProxy, UITextViewDelegate, DelegateProxyType { + func setDelegate(to object: UITextView) { + object.delegate = self + } } #endif From fff465fbf8034bea267d5a5f4c69311a8217deea Mon Sep 17 00:00:00 2001 From: KamiKuo Date: Wed, 1 Mar 2023 14:48:17 +0800 Subject: [PATCH 2/2] add selectedRangePublisher --- Sources/CombineCocoa/Controls/UITextView+Combine.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/CombineCocoa/Controls/UITextView+Combine.swift b/Sources/CombineCocoa/Controls/UITextView+Combine.swift index 4ead047..decd5ad 100644 --- a/Sources/CombineCocoa/Controls/UITextView+Combine.swift +++ b/Sources/CombineCocoa/Controls/UITextView+Combine.swift @@ -57,6 +57,16 @@ public extension UITextView { .eraseToAnyPublisher() } + /// A publisher emits on selected range changes + var selectedRangePublisher: AnyPublisher { + let selector = #selector(UITextViewDelegate.textViewDidChangeSelection(_:)) + return delegateProxy.interceptSelectorPublisher(selector) + .compactMap { [weak self] _ in + self?.selectedRange + } + .eraseToAnyPublisher() + } + @objc override var delegateProxy: DelegateProxy { TextViewDelegateProxy.createDelegateProxy(for: self) }