59 lines
1.8 KiB
Swift
59 lines
1.8 KiB
Swift
|
|
//
|
|||
|
|
// CombineExt.swift
|
|||
|
|
// Crush
|
|||
|
|
//
|
|||
|
|
// Created by Leon on 2025/8/7.
|
|||
|
|
//
|
|||
|
|
|
|||
|
|
import Combine
|
|||
|
|
import UIKit
|
|||
|
|
|
|||
|
|
extension UITextField {
|
|||
|
|
var textPublisher: AnyPublisher<String?, Never> {
|
|||
|
|
NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: self)
|
|||
|
|
.map { ($0.object as? UITextField)?.text }
|
|||
|
|
.eraseToAnyPublisher()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
extension UITextView {
|
|||
|
|
var textPublisher: AnyPublisher<String?, Never> {
|
|||
|
|
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<A, B, P1: Publisher, P2: Publisher>(
|
|||
|
|
_ 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()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|