何时以及如何在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)
    }
}