如何快速将void块传递给objc_setAssociatedObject [英] How do I pass in a void block to objc_setAssociatedObject in swift

查看:144
本文介绍了如何快速将void块传递给objc_setAssociatedObject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过扩展程序向UIView添加轻击手势支持.使用Objective-C非常简单,但是尝试在runtime属性上设置void return块时出现以下错误.

I'm trying to add tap gesture support to UIView via an extension. This is pretty straight forward using Objective-C, but I'm getting the following error when trying to set the void return block on the runtime property.

错误:类型'()->无效'不符合协议'AnyObject'

error: type '() -> Void' does not conform to protocol 'AnyObject'

这是计算出的属性:

var tapAction: (() -> Void)? {

    get {
        objc_getAssociatedObject(self, &AssociatedKeys.SNGLSActionHandlerTapBlockKey)
    }

    set {

        objc_setAssociatedObject(
            self,
            &AssociatedKeys.SNGLSActionHandlerTapBlockKey,
            newValue,
            UInt(OBJC_ASSOCIATION_COPY_NONATOMIC)
        )
    }
}

我尝试将tapAction设置为typealias,但仍然收到相同的错误.

I've tried to set the tapAction as a typealias, but still receive the same error.

推荐答案

问题是闭包不是符合AnyObject的对象,因此不能像Swift那样存储它们.

The problem is closures are not objects that conform to AnyObject so you can't store them like that from Swift.

您可以考虑将闭包包装在具有单个属性的类中.像这样:

You could look into wrapping the closures in a class with a single property. Something like:

class ClosureWrapper {
  var closure: (() -> Void)?

  init(_ closure: (() -> Void)?) {
    self.closure = closure
  }
}

var tapAction: (() -> Void)? {
  get {
    if let cl = objc_getAssociatedObject(self, "key") as? ClosureWrapper {
      return cl.closure
    }
    return nil
  }

  set {
    objc_setAssociatedObject(
      self,
      "key",
      ClosureWrapper(newValue),
      UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    )
  }
}

这有点丑陋,可以使用一个不错的typealias,但这是实现它的一种方法.

It's a little ugly and could use a nice typealias but it's one way to do it.

这篇关于如何快速将void块传递给objc_setAssociatedObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆