UIGestureRecognizers 的闭包实现

4
我在想,是否可以使用块来初始化 UIGestureRecognizer,而不必为其创建单独的函数。
我认为,在Swift 3中,这是针对计时器引入的。
由于它对我不起作用,因此我已经实现了类似于这里发布的代码。
这是我的代码:
class TapGestureRecognizer: UITapGestureRecognizer {
    private var closure: (() -> ())?

    init() {
        super.init(target: TapGestureRecognizer.self, action: #selector(self.runAction))
    }

    convenience init(for view: UIView, block: @escaping (() -> Void)) {
        self.init()
        closure = block
        view.addGestureRecognizer(self)
    }

    func runAction() {
        print("executed")
        if closure == nil { return }
        closure!()
    }    
}

当我像这样创建一个 TapGestureRecognizer
TapGestureRecognizer(block: { _ in
    print("tapped")
})

我遇到了以下错误:

应用程序因未捕获的异常而终止,原因是:在0x105941598类中发送给+[MyApp.TapGestureRecognizer runAction]方法的选择器未被识别

你有什么想法吗?


1
可能是UIGestureRecognizer with closure的重复问题。 - JAL
我不相信有一个内置的公共API可以做到这一点,但是您可以使用链接的文章构建自己的API。 - JAL
我已经编辑了我的问题@JAL。 - LinusGeffarth
1
撤回了我的关闭投票并添加了一个答案。 - JAL
请参考这个答案:https://dev59.com/BaHia4cB1Zd3GeqPMwRh#43485387 - Mannopson
@Mannopson 我不明白那与这个问题有什么关系。 - JAL
1个回答

4
你的问题在于你的目标是 TapGestureRecognizer 类本身。你的 runAction 方法是一个实例方法,但是你告诉 super.init 它是一个类方法,因此会导致失败: +[MyApp.TapGestureRecognizer runAction]。你可以通过使 runAction 成为类方法来解决这个问题。
你也可以在初始化后删除类上的目标并添加实例:
init() {
    super.init(target: TapGestureRecognizer.self, action: #selector(runAction))
    self.removeTarget(TapGestureRecognizer.self, action: #selector(runAction))
    self.addTarget(self, action: #selector(runAction))
}

或者你可以将需要执行的闭包封装在另一个对象中。


如果我在convenience init内自动将其添加到视图中,则编译器会发出警告,即“未使用初始化程序的结果”。(当然,它仍然可以工作。)有什么办法可以消除这个警告吗?我不想在创建视图时手动添加它...另外,let _ = 也不是完美的解决方案。 - LinusGeffarth
没错。我在谈论这样的代码:TapGestureRecognizer(for: view, block: { _ in print("tapped") }),它会自动将识别器添加到其init函数内部的视图中。 - LinusGeffarth
作为一种优化:Swift 不会自动将该实例方法转换为类方法吗?我想我把这个优化机制和其他东西混淆了...记不清是什么了 :/ - mfaani
我写错了我的问题:我的问题是:为什么runAction不是一个类方法?因为它前面没有class吗?好的,我明白了!但是Swift难道不聪明到足以将不使用任何属性的方法优化为类方法吗? - mfaani
1
@Honey,为什么Swift会将实例方法优化为类方法?这将是一种可怕的优化。编译器不知道这些方法将如何被调用,特别是在Objective-C世界中,任何对象都可以发送或接收任何消息,因为我们继承自“NSObject”。 - JAL
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接