Swift 闭包为 AnyObject
Swift closure as AnyObject
我正在尝试使用此方法: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'
你不能。您只能将其转换为 Any
。
AnyObject
可以表示任何 class 类型的实例。
Any
可以表示任何类型的实例,包括函数类型。
Apple Inc.“Swift 编程语言。”iBooks。 https://itun.es/de/jEUH0.l
How can I cast ()->()
into AnyObject
?
警告:此答案包含 Swift 中未记录和不安全的功能。我怀疑这是否通过了 AppStore 审核。
let f: ()->() = {
println("test")
}
let imp = imp_implementationWithBlock(
unsafeBitCast(
f as @objc_block ()->(),
AnyObject.self
)
)
这对我有用:
let myBlock: @objc_block () -> Void = {
}
var mf : AnyObject = unsafeBitCast(myBlock, AnyObject.self)
您可以编写一个包装器,然后将其传递给函数
class ObjectWrapper<T> {
let value :T
init(value:T) {
self.value = value
}
}
let action = ObjectWarpper(value: {()->() in
// something
})
在Swift2中,你应该使用@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
}
使用Any
对象(所有类型隐式遵守的协议)
let aBlock: (view: View) -> Void = { view in /**/ }
let block:Any? = aBlock
在 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
,因此即使没有 [=],代码也能编译11=] 部分,但是它会在运行时崩溃,因为编译器不会将 Swift 闭包转换为 Objective-C 块。
我正在尝试使用此方法: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'
你不能。您只能将其转换为 Any
。
AnyObject
可以表示任何 class 类型的实例。Any
可以表示任何类型的实例,包括函数类型。
Apple Inc.“Swift 编程语言。”iBooks。 https://itun.es/de/jEUH0.l
How can I cast
()->()
intoAnyObject
?
警告:此答案包含 Swift 中未记录和不安全的功能。我怀疑这是否通过了 AppStore 审核。
let f: ()->() = {
println("test")
}
let imp = imp_implementationWithBlock(
unsafeBitCast(
f as @objc_block ()->(),
AnyObject.self
)
)
这对我有用:
let myBlock: @objc_block () -> Void = {
}
var mf : AnyObject = unsafeBitCast(myBlock, AnyObject.self)
您可以编写一个包装器,然后将其传递给函数
class ObjectWrapper<T> {
let value :T
init(value:T) {
self.value = value
}
}
let action = ObjectWarpper(value: {()->() in
// something
})
在Swift2中,你应该使用@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
}
使用Any
对象(所有类型隐式遵守的协议)
let aBlock: (view: View) -> Void = { view in /**/ }
let block:Any? = aBlock
在 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
,因此即使没有 [=],代码也能编译11=] 部分,但是它会在运行时崩溃,因为编译器不会将 Swift 闭包转换为 Objective-C 块。