在Swift 2中使用自定义消息抛出错误/异常的最简单方法?

问题描述 投票:110回答:9

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

throw new RuntimeException("A custom message here")

我知道我可以抛出符合ErrorType协议的枚举类型,但我不想为我抛出的每种类型的错误定义枚举。理想情况下,我希望能够尽可能地模仿上面的例子。我研究了创建一个实现ErrorType协议的自定义类,但我甚至无法弄清楚该协议需要什么(请参阅documentation)。想法?

ios swift swift2
9个回答
163
投票

最简单的方法可能是定义一个自定义enum,只有一个case附加了String

enum MyError: ErrorType {
    case runtimeError(String)
}

或者,从Swift 4开始:

enum MyError: Error {
    case runtimeError(String)
}

示例用法如下:

func someFunction() throws {
    throw MyError.runtimeError("some message")
}
do {
    try someFunction()
} catch MyError.runtimeError(let errorMessage) {
    print(errorMessage)
}

如果你想使用现有的Error类型,最常见的是NSError,你可以创建一个工厂方法来创建一个带有自定义消息的方法。


116
投票

最简单的方法是让String符合Error

extension String: Error {}

然后你可以抛出一个字符串:

throw "Some Error"

要使字符串本身成为错误的localizedString,您可以改为扩展LocalizedError

extension String: LocalizedError {
    public var errorDescription: String? { return self }
}

16
投票

@ nick-keets的解决方案是最优雅的,但它在测试目标中确实打破了以下编译时错误:

Redundant conformance of 'String' to protocol 'Error'

这是另一种方法:

struct RuntimeError: Error {
    let message: String

    init(_ message: String) {
        self.message = message
    }

    public var localizedDescription: String {
        return message
    }
}

并使用:

throw RuntimeError("Error message.")

13
投票

检查这个很酷的版本。我们的想法是实现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
}

12
投票

斯威夫特4:

按照:

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

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

import Foundation

do {
  throw NSError(domain: "my error description", 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 description, 42
    User info:
        key=ui1, value=12
        key=ui2, value=val2

这允许您提供自定义字符串,以及包含任何类型所需的所有其他数据的数字代码和字典。

N.B。:这是在OS = Linux(Ubuntu 16.04 LTS)上测试的。


4
投票

根据@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*/
}

最初发布在我的快速博客:http://eon.codes/blog/2017/09/01/throwing-simple-errors/


4
投票

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

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

2
投票

我喜欢@ Alexander-Borisenko的答案,但是当作为错误捕获时,没有返回本地化描述。您似乎需要使用LocalizedError:

struct RuntimeError: LocalizedError
{
    let message: String

    init(_ message: String)
    {
        self.message = message
    }

    public var errorDescription: String?
    {
        return message
    }
}

有关详细信息,请参阅this answer


0
投票

只需使用fatalError:fatalError ("Custom message here")

© www.soinside.com 2019 - 2024. All rights reserved.