Pau*_*w11 5 exception objective-c swift
我希望在Swift中有一个函数返回一个Bool但是throw如果发生异常也可以.
例如:
func doSomething(value: Int) throws -> Bool {
if (value > 0) {
return true
} else if (value == 0) {
throw NSError(domain: "SwiftClass", code: 0, userInfo: nil)
}
return false
}
Run Code Online (Sandbox Code Playgroud)
这很好,来自Swift,但如果我尝试使用Objective-C中的这个函数,编译器就找不到该方法.我知道throws要求Objective-C函数签名更改为doSomething:x error:&error,如果我将返回类型更改为Void-
func doSomething(value: Int) throws -> Void {
if (value == 0) {
throw NSError(domain: "SwiftClass", code: 0, userInfo: nil)
} else if (value < 0) {
throw NSError(domain: "SwiftClass", code: -1, userInfo: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
但这有不同的语义.在第一个例子中,NSError如果出现问题,我只需处理异常(或非零).使用此代码,我必须捕获异常(或检查错误)并确定它是真正的问题还是只是有效的"假"情况.
是否真的不可能使用具有在Objective-C上下文中抛出的非void返回的Swift函数?
正如我的评论中所指出的,我不清楚为什么这不起作用.该文档没有给出任何建议,这不应该工作,但它也没有明确说明它应该.我阅读文档说它应该有效.
话虽如此,我们可以将它包装在一个可以从Objective-C调用的方法中,方法是将返回类型更改为结果Void并使用inout参数:
func doSomething(value: Int) throws -> Bool {
if (value > 0) {
return true
} else if (value < 0) {
return false
} else {
throw NSError(domain: "SwiftClass", code: 0, userInfo: nil)
}
}
func doSomething(value: Int, inout result: Bool) throws {
do {
result = try doSomething(value)
} catch let error {
// If need be, assign some default value to result.
throw error
}
}
Run Code Online (Sandbox Code Playgroud)
或者,根据你的评论,如果我们返回一个可以桥接到Objective-C类(显然不包括Bool)的值,编译器会很高兴,所以我们可以这样包装它:
@objc func doSomething(value: Int) throws -> NSNumber {
do {
return try doSomething(value)
} catch let error {
throw error
}
}
Run Code Online (Sandbox Code Playgroud)
在解决这个问题时,很明显为什么只有当我们返回一个可以映射到Objective-C类的值时,这才有效.
编译器不允许您从标有@objc和的方法返回一个可选项throws.为什么?因为虽然在Swift方面,我们使用try语义来调用方法,但Objective-C中的方法完全不同. nil用于表示失败.
所以尝试在Swift中创建一个带有此签名的方法:
@objc func doSomething(value: Int) throws -> NSNumber?
Run Code Online (Sandbox Code Playgroud)
生成此警告:
抛出方法不能标记为@objc,因为它返回一个可选类型'NSNumber?'的值; 'nil'表示没有Objective-C
最后,我仍然非常建议您将Swift方法编写为返回签名Bool并编写返回的包装器方法,NSNumber以便我们仍然可以使用最准确类型的Swift方法.
此外,如果你注意到,Bool 可以愉快地自动装箱NSNumber.我的包装器方法被写为返回类型NSNumber,但我正在包装的方法返回类型Bool,但Swift非常乐意Bool从应该返回的方法返回NSNumber.问题很可能是默认情况下,如果未指定,Swift将Bool转换为Objective-C BOOL,这是一个非类.
如果你的返回类型是,Objective-C将无法区分三种可能的情况BOOL.它只有两个可能的BOOL方法返回:YES或NO.随着Bool映射到NSNumber,它可以返回@YES,@NO和nil.
如果是我的话,NSNumber对我来说不够严格.我可能会被鼓励为此编写自己的包装类.
@objc class BooleanObject: NSObject, BooleanType {
let boolValue: Bool
init(_ boolValue: Bool) {
self.boolValue = boolValue
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,该BooleanType协议意味着Swift仍然非常乐意使用这种类型的变量,就好像它们是常规变量一样Bool.
let b = BooleanObject(true)
if b {
// b's boolValue property is true
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1005 次 |
| 最近记录: |