作为AnyObject的Swift闭包

时间:2015-01-29 10:11:10

标签: ios objective-c swift objective-c-runtime

我试图使用这个方法:class_addMethod()在Obj-c中使用如下:

class_addMethod([self class], @selector(eventHandler), imp_implementationWithBlock(handler), "v@:");

我在Swift中使用它是这样的:

class_addMethod(NSClassFromString("UIBarButtonItem"), "handler", imp_implementationWithBlock(handler), "v@:")

这是UIBarButtonItem的扩展名,您可能已经想到了。

imp_implementationWithBlock采用AnyObject!

类型的参数

如何将()->()投射到AnyObject

我试图像这样投了它:handler as AnyObject但它给我一个错误说:()->() does not conform to protocol 'AnyObject'

7 个答案:

答案 0 :(得分:9)

  

如何将()->()投射到AnyObject

警告:此答案包含Swift中的无证件和不安全功能。我怀疑这是通过AppStore审查。

let f: ()->() = {
    println("test")
}

let imp = imp_implementationWithBlock(
    unsafeBitCast(
        f as @objc_block ()->(),
        AnyObject.self
    )
)

答案 1 :(得分:8)

您可以编写一个包装器,然后将其传递给函数

class ObjectWrapper<T> {
    let value :T
    init(value:T) {
       self.value = value
    }
}

let action = ObjectWarpper(value: {()->() in    
    // something
})

答案 2 :(得分:5)

在Swift 2中,您应该使用@convention而不是@objc_block。见Type Attribute

func swizzle(type: AnyClass, original: Selector, methodType: MethodType, block: () -> Void) {
    let originalMethod = method(type, original: original, methodType: methodType)

    let castedBlock: AnyObject = unsafeBitCast(block as @convention(block) () -> Void, AnyObject.self)

    let swizzledImplementation = imp_implementationWithBlock(castedBlock)
    // More code goes here
}

答案 3 :(得分:4)

你不能。您只能将其投射到Any

  • AnyObject可以表示任何类类型的实例。
  • Any可以表示任何类型的实例,包括函数类型。

Apple Inc.“Swift编程语言。”iBooks。 https://itun.es/de/jEUH0.l

答案 4 :(得分:2)

这对我有用:

let myBlock: @objc_block () -> Void = { 
}
var mf : AnyObject = unsafeBitCast(myBlock, AnyObject.self)

答案 5 :(得分:0)

使用Any object (所有类型隐式符合的协议)

 let aBlock: (view: View) -> Void = { view in /**/ }

 let block:Any? = aBlock

答案 6 :(得分:0)

在Swift 4.x中(我认为也可以在3.x中使用),只需将闭包声明为@convention(block)就足以解决兼容性问题:

// define the new implementation
let handler: @convention(block) (UIBarButtonItem) -> Void = { _ in }

// inject it into the class
class_addMethod(NSClassFromString("UIBarButtonItem"), sel_registerName("handler"), imp_implementationWithBlock(handler), "v@:")

尽管从Swift 3开始,如果引用来自Objective-C,AnyObject会转换为Any,因此即使没有@convention(block)部分,代码也可以编译。运行时崩溃,因为编译器不会将Swift闭包转换为Objective-C块。