// // CombineExt.swift // Crush // // Created by Leon on 2025/8/7. // import Combine import UIKit extension UITextField { var textPublisher: AnyPublisher { NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: self) .map { ($0.object as? UITextField)?.text } .eraseToAnyPublisher() } } extension UITextView { var textPublisher: AnyPublisher { NotificationCenter.default .publisher(for: UITextView.textDidChangeNotification, object: self) .map { ($0.object as? UITextView)?.text } .eraseToAnyPublisher() } } extension Publishers { /* 使用: Publishers.eitherLatest(container.$whoIm, container.$birthdayDate) .sink { whoIm, birthday in // whoIm: String? // birthday: Date? print("更新 -> whoIm=\(whoIm ?? "nil"), birthday=\(birthday?.description ?? "nil")") } .store(in: &cancellables) */ /// 当任一上游(输出为 Optional)更新时触发,输出为两者的“最新快照” static func eitherLatest( _ p1: P1, _ p2: P2 ) -> AnyPublisher<(A?, B?), Never> where P1.Output == A?, P2.Output == B?, P1.Failure == Never, P2.Failure == Never { let left = p1.map { value -> (A?, B?) in (value, nil as B?) } let right = p2.map { value -> (A?, B?) in (nil as A?, value) } return Publishers.Merge(left, right) // 记住历史最新值:新的非 nil 覆盖对应位;nil 则沿用旧值 .scan((nil as A?, nil as B?)) { last, new in (new.0 ?? last.0, new.1 ?? last.1) } .eraseToAnyPublisher() } }