何时以及如何在Swift中使用@noreturn属性?

时间:2016-06-29 11:46:18

标签: swift noreturn

我在else流的上下文中读取了关键字guard-else之后用大括号括起来的代码块,必须调用标有noreturn属性的函数或使用{转移控件{1}},returnbreakcontinue

最后一部分很清楚,虽然我不太了解第一部分。

首先,即使你没有声明任何返回类型,任何函数都会返回一些东西(至少是一个空元组)。其次,我们何时可以使用throw函数?文档是否表示某些核心内置方法标有noreturn

  

保护声明的else子句是必需的,必须要么调用   标有noreturn属性或传输程序的函数   使用其中一个来控制守卫声明的封闭范围   以下陈述:

noreturn

这是source

3 个答案:

答案 0 :(得分:11)

  

首先,即使你没有声明任何返回类型,任何函数都会返回一些东西(至少是一个空元组)。

(@ 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]]__attribute__((noreturn))作为GCC扩展,或者_Noreturn表示 Clang编译器。)

如果它也终止,您可以使用@noreturn标记自己的功能 进程无条件,,例如通过调用其中一个内置函数,例如

@noreturn func myFatalError() {
    // Do something else and then ...
    fatalError("Something went wrong!")
}

现在,您可以在guard语句的else子句中使用您的函数:

guard let n = Int("1234") else { myFatalError() }

@noreturn函数也可用于标记"不应该的情况 发生"并指出编程错误。一个简单的例子 (摘自Missing return UITableViewCell):

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell: MyTableViewCell

    switch (indexPath.row) {
    case 0:
        cell = tableView.dequeueReusableCellWithIdentifier("cell0", forIndexPath: indexPath) as! MyTableViewCell
        cell.backgroundColor = UIColor.greenColor()
    case 1:
        cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! MyTableViewCell
        cell.backgroundColor = UIColor.redColor()
    default:
        myFatalError()
    }
    // Setup other cell properties ...
    return cell
}

如果没有myFatalError()标记为@noreturn,编译器会 抱怨默认情况下缺少回报。

更新:在Swift 3(Xcode 8 beta 6)中@noreturn属性 已被Never返回类型替换,因此上面的示例 现在写成

func myFatalError() -> Never  {
    // Do something else and then ...
    fatalError("Something went wrong!")
}

答案 1 :(得分:1)

简单的游乐场,看看它是如何运作的......

//: 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

答案 2 :(得分:0)

例如,考虑一个异步操作,该操作返回值或结果类型错误。我们通常将其写为foolows。

enum Result<Value, Error> {
    case success(Value)
    case failure(Error)
}

func fetch(_ request: URLRequest,
          completion: (Result<(URLResponse, Data), Error>) -> Void) {
    // ...
}

现在,如果您知道一个始终返回值的函数,则永远不会出错,那么我们可以编写:

func alwaysSucceeds(_ completion: (Result<String, Never>) -> Void) {
    completion(.success("yes!"))
}

当编译器看到从不时,它不会强制您写出所有切换用例,因此您可以按以下方式跳过.failure。

alwaysSucceeds { (result) in
    switch result {
    case .success(let string):
        print(string)
    }
}

Ref:https://nshipster.com/never/