提问人:안은노 提问时间:8/15/2023 更新时间:8/15/2023 访问量:51
组合 Cocoa UIView 自定义扩展不起作用
combine cocoa uiview custom extension does not work
问:
我不知道为什么我的扩展 UIView tabPublisher 不起作用。
我读了 swift combine cocoa 库。并想做 UIView 扩展。(Swift combine cocoa 没有给出 UIView 扩展。
另一个关于自定义uiview扩展的例子,使用限制使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()
}
上述代码存在于可可组合中 https://github.com/CombineCommunity/CombineCocoa/blob/main/Sources/CombineCocoa/CombineControlTarget.swift
下面的代码是我的自定义 UIView 扩展。
extension UIView {
var tabPublisher: AnyPublisher<UITapGestureRecognizer, Never> { // this is problem
UITapGestureRecognizer().tabGesturePublisher
}
}
我的代码有什么问题? 手势不起作用。
答:
0赞
Matic Oblak
8/15/2023
#1
我相信您正在寻找的解决方案可能如下:
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)
评论
0赞
안은노
8/15/2023
感谢您的回复。但是每次调用点击事件时,此代码都会附加手势和分离。哎呀?
0赞
Matic Oblak
8/16/2023
@안은노 并非每次调用 tap 事件时。但每次调用时,它都会附加一个新手势。因此,在大多数情况下,每个视图只应调用一次。tapPublisher
下一个:在 SWIFT 中向下投射
评论