Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift closure as AnyObject

Im trying to use this method: class_addMethod() which in Obj-c is used like this:

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

And Im using it like this in Swift:

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

It is an extension for UIBarButtonItem as you might have figured out.

imp_implementationWithBlock takes a parameter of type AnyObject!

How can I cast ()->() into AnyObject ?

I've tried to cast it like this: handler as AnyObject but it gives me an error saying: ()->() does not conform to protocol 'AnyObject'

like image 472
Arbitur Avatar asked Jan 29 '15 10:01

Arbitur


3 Answers

How can I cast ()->() into AnyObject ?

Warning: This answer includes undocumented and unsafe feature in Swift. I doubt this passes AppStore review.

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

let imp = imp_implementationWithBlock(
    unsafeBitCast(
        f as @objc_block ()->(),
        AnyObject.self
    )
)
like image 102
rintaro Avatar answered Nov 18 '22 07:11

rintaro


You could write a wrapper, then pass it to the function

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

let action = ObjectWarpper(value: {()->() in    
    // something
})
like image 8
leavez Avatar answered Nov 18 '22 06:11

leavez


In Swift 2, you should use @convention instead of @objc_block. See 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
}
like image 6
onmyway133 Avatar answered Nov 18 '22 07:11

onmyway133