何时以及如何在Swift中使用@noreturn属性?
在何时以及如何在Swift中使用@noreturn属性?,swift,noreturn,Swift,Noreturn,在guard else流的上下文中,我阅读了关键字else后用大括号括起来的代码块,必须使用return、break、continue或throw调用标有noreturn属性的函数或传输控件 最后一部分很清楚,但我不太理解第一部分 首先,即使没有声明任何返回类型,任何函数都会返回某些内容(至少是一个空元组)。其次,我们什么时候可以使用noreturn函数?文档是否建议一些核心的内置方法用noreturn标记 guard语句的else子句是必需的,并且必须调用 用noreturn属性或传输程序标记
guard else
流的上下文中,我阅读了关键字else
后用大括号括起来的代码块,必须使用return
、break
、continue
或throw
调用标有noreturn
属性的函数或传输控件
最后一部分很清楚,但我不太理解第一部分
首先,即使没有声明任何返回类型,任何函数都会返回某些内容(至少是一个空元组)。其次,我们什么时候可以使用noreturn
函数?文档是否建议一些核心的内置方法用noreturn
标记
guard语句的else子句是必需的,并且必须调用
用noreturn属性或传输程序标记的函数
使用
以下声明:
return
break
continue
throw
这是你的电话号码
首先,即使没有声明任何返回类型,任何函数都会返回某些内容(至少是一个空元组)
(@noreturn已过时;请参阅下面的Swift 3更新。)
不,有些函数会立即终止进程
并且不要返回给打电话的人。这些是用Swift标记的
使用@noreturn
,例如
@noreturn public func fatalError(@autoclosure message: () -> String = default, file: StaticString = #file, line: UInt = #line)
@noreturn public func preconditionFailure(@autoclosure message: () -> String = default, file: StaticString = #file, line: UInt = #line)
@noreturn public func abort()
@noreturn public func exit(_: Int32)
可能还有更多
(注:其他编程语言中也存在类似的注释。)
或编译器,如C++11中的[[noreturn]]
,\uuuuuu属性((noreturn))
作为GCC扩展,或
叮当作响。)
如果函数也终止,您可以使用@noreturn
标记自己的函数
进程无条件地执行,例如通过调用一个内置函数,例如
@noreturn func myFatalError() {
// Do something else and then ...
fatalError("Something went wrong!")
}
现在,您可以在guard
语句的else子句中使用函数:
guard let n = Int("1234") else { myFatalError() }
@noreturn
函数也可用于标记“不应”的情况
“发生”并指示编程错误。一个简单的例子
(摘自:
如果没有标记为@noreturn
的myFatalError()
,编译器将
在默认情况下,投诉缺少退货
更新:在Swift 3(Xcode 8 beta 6)中,
@noreturn
属性
已替换为从不
返回类型,因此上面的示例
现在将写为
func myFatalError() -> Never {
// Do something else and then ...
fatalError("Something went wrong!")
}
简单的操场,看看它是如何工作的
//: Playground - noun: a place where people can play
import Foundation
@noreturn func foo() {
print("foo")
exit(1)
}
var i: Int?
guard let i = i else {
foo()
}
print("after foo") // this line will never executed
//prints foo and finish
例如,考虑在结果类型中返回值或错误的ASSCONC操作。我们通常这样写
enum Result<Value, Error> {
case success(Value)
case failure(Error)
}
func fetch(_ request: URLRequest,
completion: (Result<(URLResponse, Data), Error>) -> Void) {
// ...
}
alwaysSucceeds { (result) in
switch result {
case .success(let string):
print(string)
}
}
Ref:看一看:还有一个永远不会返回的
UIApplicationMain
(尽管它可能因为向后兼容而没有标记)。Obj-C中的一个问题是,编译器无法识别像[NSException raise]
这样的调用,并且在它们之后还必须有返回值。@Sulthan:可能吧。你不会在guard语句中调用UIApplicationMain())@MartinR:我知道我可以将其用于自定义函数,我在发布之前尝试过:-)我的问题是:开发人员用这种方式标记函数有什么意义吗?我在寻找一个用例:-)@IanBell:这个用例是你可以在一个保护语句的else子句中使用你的自定义函数,编译器知道它永远不会返回。我补充了另一个例子。如果没有@noreturn
属性,两个示例都无法编译如果您没有无条件终止进程的函数,那么您就不需要它@IanBell使用它有很多原因,你可以在一个多线程的应用程序上工作,比如说一个进行网络下载的应用程序,在这个下载过程中,你有一些东西让防护失效。如果函数返回,它将触发一个完成事件,这是您不希望看到的,但是您还需要使线程暂时保持活动状态。现在想象一下这个代码存在的几个地方,你不想写重复的else条件,你可以在所有这些条件下使用这个函数,这样你的线程就可以在不触发完成事件的情况下死亡。我知道它是如何工作的,谢谢,但我要找的是一个具体的,这个属性非常有用的真实示例:-)@IanBell所以,您可以看到示例…:-)。试着想象一下,foo()在退出之前进行了一些清理,甚至将一些数据传输到服务器或任何您想要的地方。这项任务可能非常复杂,这取决于你。这里也一样。。。@noreturn(现在是“永不”)怎么会有用。。。真的,在一个真实的例子中…@IanBell作为另一个让我来到这里的例子是:通常在一个guard语句中,在失败场景的结尾有一个返回值
。。但是这次在我的失败中,我写了一个预处理失败
,编译器给我一个警告:“永远不会执行”在返回行上…因为预处理失败实际上标志着代码执行的结束
func alwaysSucceeds(_ completion: (Result<String, Never>) -> Void) {
completion(.success("yes!"))
}
alwaysSucceeds { (result) in
switch result {
case .success(let string):
print(string)
}
}