我想在Swift中做一些我习惯在其他多种语言中做的事情:用自定义消息抛出运行时异常。例如(在Java中):

throw new RuntimeException("A custom message here")

我知道我可以抛出符合ErrorType协议的枚举类型,但我不希望必须为抛出的每种类型的错误定义枚举。理想情况下,我希望能够尽可能地模拟上面的示例。我考虑创建一个实现ErrorType协议的自定义类,但我甚至不知道该协议需要什么。想法吗?


当前回答

我想对所提议的一些解决办法提出一些变通建议:

public enum MyError: Error {
    var localizedDescription: String {
        get {
            switch(self) {
                case .network(let message, let code):
                    return "\(message) (\(code))"
                case .invalidInput(message: let message):
                    return message
            }
        }
    }
    case network(message: String, code: Int)
    case invalidInput(message: String)
}

它需要更多的工作来创建,但它提供了所有世界中最好的:

它是一个枚举,所以可以在switch语句中使用。 所有错误都必须创建一个消息,即使对于相同类型的错误也可以是不同的消息(与扩展String的枚举不同) 它在localizedDescription下提供了每个开发人员都期望的消息。

其他回答

最简单的解决方案,没有额外的扩展,枚举,类等:

NSException(name:NSExceptionName(rawValue: "name"), reason:"reason", userInfo:nil).raise()

看看这个很酷的版本。其思想是同时实现String和ErrorType协议,并使用错误的rawValue。

enum UserValidationError: String, Error {
  case noFirstNameProvided = "Please insert your first name."
  case noLastNameProvided = "Please insert your last name."
  case noAgeProvided = "Please insert your age."
  case noEmailProvided = "Please insert your email."
}

用法:

do {
  try User.define(firstName,
                  lastName: lastName,
                  age: age,
                  email: email,
                  gender: gender,
                  location: location,
                  phone: phone)
}
catch let error as User.UserValidationError {
  print(error.rawValue)
  return
}

根据@Nick keets的回答,这里有一个更完整的例子:

extension String: Error {} // Enables you to throw a string

extension String: LocalizedError { // Adds error.localizedDescription to Error instances
    public var errorDescription: String? { return self }
}

func test(color: NSColor) throws{
    if color == .red {
        throw "I don't like red"
    }else if color == .green {
        throw "I'm not into green"
    }else {
        throw "I like all other colors"
    }
}

do {
    try test(color: .green)
} catch let error where error.localizedDescription == "I don't like red"{
    Swift.print ("Error: \(error)") // "I don't like red"
}catch let error {
    Swift.print ("Other cases: Error: \(error.localizedDescription)") // I like all other colors
}

最初发表于我的swift博客:http://eon.codes/blog/2017/09/01/throwing-simple-errors/

如果你不需要捕捉错误,你想立即停止应用程序,你可以使用一个fatalError: fatalError("自定义消息在这里")

斯威夫特4:

按:

https://developer.apple.com/documentation/foundation/nserror

如果你不想定义一个自定义异常,你可以使用一个标准NSError对象,如下所示:

import Foundation

do {
  throw NSError(domain: "my error domain", code: 42, userInfo: ["ui1":12, "ui2":"val2"] ) 
}
catch let error as NSError {
  print("Caught NSError: \(error.localizedDescription), \(error.domain), \(error.code)")
  let uis = error.userInfo 
  print("\tUser info:")
  for (key,value) in uis {
    print("\t\tkey=\(key), value=\(value)")
  }
}

打印:

Caught NSError: The operation could not be completed, my error domain, 42
    User info:
        key=ui1, value=12
        key=ui2, value=val2

这允许您提供一个自定义字符串(错误域),加上一个数字代码和一个字典,其中包含您需要的所有其他类型的数据。

注意:这是在OS=Linux (Ubuntu 16.04 LTS)上测试的。