问题
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'
回答1:
How can I cast
()->()intoAnyObject?
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
)
)
回答2:
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
})
回答3:
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
}
回答4:
You can't. You can only cast it to Any.
AnyObjectcan represent an instance of any class type.Anycan represent an instance of any type at all, including function types.
Apple Inc. „The Swift Programming Language.“ iBooks. https://itun.es/de/jEUH0.l
回答5:
This has worked for me:
let myBlock: @objc_block () -> Void = {
}
var mf : AnyObject = unsafeBitCast(myBlock, AnyObject.self)
回答6:
Use Any object (The protocol to which all types implicitly conform)
let aBlock: (view: View) -> Void = { view in /**/ }
let block:Any? = aBlock
回答7:
In Swift 4.x (I think works in 3.x too), simply declaring the closure as @convention(block) should be enough to address compatibility thing:
// 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@:")
Though, starting with Swift 3, AnyObject was converted to Any if the reference comes from Objective-C, so the code will compile even without the @convention(block) part, however it will crash at runtime as the compiler will not convert the Swift closure to an Objective-C block.
来源:https://stackoverflow.com/questions/28211973/swift-closure-as-anyobject