我试图通过创建UITouch扩展来切换UIResponder生命周期事件。下面是描述touchesBegan实现的摘录。

 public extension UIResponder {

   private enum TouchPhase: String {
    case begin
    case move
    case end
    case cancel
    //computed property
    var phase: String {
        return self.rawValue
    }
}

    @objc func swizztouchesBegan(_ touches: Set<UITouch>, with event:
            UIEvent?) {
         print("swizztouchesBegan event called!")
         let touch = touches.first! as UITouch
         self.createTouchesDict(for: touch, event: event, phase: .begin)
         self.swizztouchesBegan(touches, with: event)
     }

    static func swizzleTouchesBegan() {
       let _: () = {
            let originalSelector =
        #selector(UIResponder.touchesBegan(_:with:))
            let swizzledSelector =
        #selector(UIResponder.swizztouchesBegan(_:with:))
             let originalMethod = class_getInstanceMethod(UIResponder.self, originalSelector)
             let swizzledMethod = class_getInstanceMethod(UIResponder.self, swizzledSelector)
    method_exchangeImplementations(originalMethod!, swizzledMethod!)
    }()
 }
}

然后我在我的应用程序中调用它,就像这样-
 [UIResponder swizzleTouchesBegan]; //my app is a mix of Objective-C and Swift

我看到的是-“swizztouchesbeated事件被调用!”打印出来,我就可以创建触摸元数据的字典。但是,它看起来并没有调用原始实现,例如,假设在我的代码中的某个地方,在表视图控制器中,我编写了以下代码-
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    print("AM I GETTING CALLED?")
}

这个重写的touchesStarted没有被调用-可能是什么问题?我已经通过再次调用swizzle实现从swizzle实现内部调用了原始实现(从而确保调用了原始实现)
PS/addition:我可以通过重写UIView扩展中的touch方法来让它工作,如下所示。有人能指出,如果有任何缺点使用这种方法比刷子之一?
public extension UIView {

private enum TouchPhase: String {
    case begin
    case move
    case end
    case cancel
    //computed property
    var phase: String {
        return self.rawValue
    }
}
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    print("overriding touches began event!")
    let touch = touches.first! as UITouch
    self.createTouchesDict(for: touch, event: event, phase: .begin)
    super.touchesBegan(touches, with: event)
}

open override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("overriding touches moved event!")
    let touch = touches.first! as UITouch
    self.createTouchesDict(for: touch, event: event, phase: .move)
    super.touchesMoved(touches, with: event)

}

open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("overriding touches ended event!")
    let touch = touches.first! as UITouch
    self.createTouchesDict(for: touch, event: event, phase: .end)
    super.touchesEnded(touches, with: event)

}

  open override func touchesCancelled(_ touches: Set<UITouch>, with
 event: UIEvent?) {
    print("overriding touches canceled event!")
    let touch = touches.first! as UITouch
    self.createTouchesDict(for: touch, event: event, phase: .cancel)
    super.touchesCancelled(touches, with: event)

    }
  }

最佳答案

在我看来,你总是在刷选择器,而没有检查是否已经这样做了。
这是一个关于你如何做到这一点的例子。

extension UIResponder {

    static let swizzleIfNeeded: () = {
        swizzle(originalSelector: #selector(touchesBegan(_:with:)), to: #selector(swizztouchesBegan(_:with:)))
    }()

    static func swizzle(originalSelector: Selector, to swizzledSelector: Selector) {
        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
        } else {
            method_exchangeImplementations(originalMethod!, swizzledMethod!);
        }
    }

    @objc func swizztouchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("swizztouchesBegan event called!")
        let touch = touches.first! as UITouch
        self.createTouchesDict(for: touch, event: event, phase: .begin)
        self.swizztouchesBegan(touches, with: event)
    }
}

然后在你的应用程序中,委托完成了(例如)
UIResponder.swizzleIfNeeded

关于ios - 困惑的UIResponder Touch事件未调用原始方法实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51254471/

10-14 21:25
查看更多