我正在尝试获取现有Objective C类的方法的结果,使用 performSelector
进行调用let result = controlDelegate.performSelector("methodThatReturnsBOOL") as? Bool
我需要将此结果转换为Bool类型的Swift。
上面提到的代码会发出警告
“从'未经管理!'中投下'不相关的类型'Bool'总是失败“
并且结果始终为“false”,即使方法返回YES。
有关将结果转换为Bool的建议吗?
methodThatReturnsBOOL的签名
- (BOOL)methodThatReturnsBOOL
{
return YES;
}
答案 0 :(得分:8)
已经有很长一段时间了,因为这仍然没有答案,所以我在此过程中添加了我所学到的知识。
要转换Objective C方法返回的BOOL
值,您只需使用
if let result = controlDelegate.performSelector("methodThatReturnsBOOL") {
print("true")
} else {
print("false")
}
如果需要,您还可以在此处将值true / false分配给Swift Bool
。
注意:我尝试使用Unmanaged<AnyObject>
直接将Bool
投射到takeRetainedValue()
,正如SO上的许多答案所建议的那样,但这似乎并不是在这种情况下工作。
答案 1 :(得分:1)
这是Swift 3中的解决方案,因为方法有点不同。此方法还检查Objective-C对象是否响应选择器,以避免崩溃。
import ObjectiveC
let selector = NSSelectorFromString("methodThatReturnsBOOL")
guard controlDelegate.responds(to: selector) else {
return
}
if let result = controlDelegate.perform(selector) {
print("true")
}
else {
print("false")
}
答案 2 :(得分:0)
在Swift中,您无法做自己想做的事情。我接受的解决方案的问题在于,它利用了0x0 恰好发生为nil
的想法。 Swift和Objective-C规范实际上并不能保证这一点。布尔值也是如此,因为0x0为false,0x1为true只是一个任意的实现决策。除了在技术上不正确之外,它也是糟糕的代码。无需考虑大多数平台(零位的32/64位)上的nil指针是什么,建议的设置就没有意义了。
在与WWDC '19的工程师交谈了一段时间之后,他建议您实际上可以使用valueFor(forKey:)
,其键为函数名称/选择器描述。这是可行的,因为Obj-C运行时实际上将使用给定的名称/键执行任何函数,以便评估表达式。由于仍需要Objective-C运行时的知识,所以这仍然有点麻烦,但是由于valueFor(forKey:)
返回了Any?
并可以转换为{{1} }或Int
完全没有问题。通过使用内置的强制转换而不是推测0x0或0x1的含义,我们避免了解释nil指针的整个问题。
示例:
Bool
...
@objc func doThing() -> Bool{
return true
}
答案 3 :(得分:0)
类似于我的答案here,可以用@convention(c)
代替:
let selector: Selector = NSSelectorFromString("methodThatReturnsBOOL")
let methodIMP: IMP! = controlDelegate.method(for: selector)
let boolResult: Bool = unsafeBitCast(methodIMP,to:(@convention(c)(Any?,Selector)->Bool).self)(controlDelegate,selector)
此特殊语法自Swift 3.1起可用,在Swift 3中也可以使用一个额外的变量。