结合cocoa uiview自定义扩展不起作用

问题描述 投票:0回答:1

我不知道为什么我的扩展 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
    }
}

我的代码有什么问题? 手势不起作用。

ios swift uiview gesture combine
1个回答
0
投票

我相信您正在寻找的解决方案可能如下:

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)
。因此,手势识别器永远不会触发,并且实际上会在方法执行后立即释放,因为没有任何内容保留它。

© www.soinside.com 2019 - 2024. All rights reserved.