我不知道为什么我的扩展 UIView tabPublisher 不起作用。
我读了 swift 组合可可库。并想做 UIView 扩展。(Swift 结合 cocoa 没有给出有关 UIView 扩展的信息。)
关于自定义 uiview 扩展的另一个例子,使用throttle 的 post make uiview 扩展。但我觉得这没有任何意义。
extension Combine.Publishers {
struct CustomTarget<Control: AnyObject>: Publisher {
// swiftlint: disable nesting
typealias Output = Void
typealias Failure = Never
// swiftlint: enable nesting
let control: Control
let addTargetAction: (Control, AnyObject, Selector) -> Void
let removeTargetAction: (Control, AnyObject, Selector) -> Void
init(
control: Control,
addTargetAction: @escaping (Control, AnyObject, Selector) -> Void,
removeTargetAction: @escaping (Control, AnyObject, Selector) -> Void) {
self.control = control
self.addTargetAction = addTargetAction
self.removeTargetAction = removeTargetAction
}
func receive<S>(subscriber: S) where S: Subscriber, S.Failure == Failure, S.Input == Output {
let subscription = Subscription(
subscriber: subscriber,
control: control,
addTargetAction: addTargetAction,
removeTargetAction: removeTargetAction)
subscriber.receive(subscription: subscription)
}
}
}
extension Combine.Publishers.CustomTarget {
class Subscription<S: Subscriber, Control: AnyObject>: Combine.Subscription where S.Input == Void {
private var subscriber: S?
weak private var control: Control?
let removeTargetAction: (Control, AnyObject, Selector) -> Void
let action = #selector(handleAction)
init(
subscriber: S,
control: Control,
addTargetAction: @escaping (Control, AnyObject, Selector) -> Void,
removeTargetAction: @escaping (Control, AnyObject, Selector) -> Void) {
self.subscriber = subscriber
self.control = control
self.removeTargetAction = removeTargetAction
addTargetAction(control, self, action)
}
func request(_ demand: Subscribers.Demand) {
}
func cancel() {
subscriber = nil
removeTargetAction(control!, self, action)
}
@objc func handleAction() {
_ = subscriber?.receive()
}
}
}
extension UITapGestureRecognizer {
var tabGesturePublisher: AnyPublisher<UITapGestureRecognizer, Never> {
gesturePublisher(for: self)
}
}
private func gesturePublisher<Gesture: UIGestureRecognizer>(for gesture: Gesture) -> AnyPublisher<Gesture, Never> {
Publishers.CustomTarget(
control: gesture,
addTargetAction: { gesture, target, action in
gesture.addTarget(target, action: action)},
removeTargetAction: { gesture, target, action in
gesture.removeTarget(target, action: action)
})
.subscribe(on: DispatchQueue.main)
.map { gesture }
.eraseToAnyPublisher()
}
以上代码存在于combine cocoa中存在 https://github.com/CombineCommunity/CombineCocoa/blob/main/Sources/CombineCocoa/CombineControlTarget.swift
下面的代码是我的自定义 UIView 扩展。
extension UIView {
var tabPublisher: AnyPublisher<UITapGestureRecognizer, Never> { // this is problem
UITapGestureRecognizer().tabGesturePublisher
}
}
我的代码有什么问题? 手势不起作用。
我相信您正在寻找的解决方案可能如下:
extension UIView {
var tapPublisher: AnyPublisher<UITapGestureRecognizer, Never> {
let recognizer = UITapGestureRecognizer()
addGestureRecognizer(recognizer)
return recognizer.tabGesturePublisher
}
}
您在案例中所做的是
var tabPublisher: AnyPublisher<UITapGestureRecognizer, Never> { // this is problem
let recognizer = UITapGestureRecognizer()
return recognizer.tabGesturePublisher
}
您创建了一个手势识别器,但未将其与当前视图关联。不见了
self.addGestureRecognizer(recognizer)
。因此,手势识别器永远不会触发,并且实际上会在方法执行后立即释放,因为没有任何内容保留它。