Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Swift 2中使用自定义消息引发错误/异常的最简单方法?_Ios_Swift_Swift2 - Fatal编程技术网

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

Ios 在Swift 2中使用自定义消息引发错误/异常的最简单方法?,ios,swift,swift2,Ios,Swift,Swift2,我想在Swift 2中做一些我在其他多种语言中已经习惯的事情:抛出一个带有自定义消息的运行时异常。例如(在Java中): 我知道我可以抛出符合ErrorType协议的枚举类型,但我不想为我抛出的每种类型的错误定义枚举。理想情况下,我希望能够尽可能地模仿上面的例子。我研究了如何创建一个实现ErrorType协议的自定义类,但我甚至不能确定该协议需要什么(请参阅)。想法?最简单的方法可能是定义一个自定义枚举,其中只有一个案例,该案例附带一个字符串: enum MyError: ErrorType {

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


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

最简单的方法可能是定义一个自定义
枚举
,其中只有一个
案例
,该案例附带一个
字符串

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)
}

如果您希望使用现有的
错误类型,最常用的类型是
NSError
,您可以创建一个工厂方法来创建并抛出一个带有自定义消息的错误。

请查看此酷版本。其思想是实现String和ErrorType协议,并使用错误的原始值

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
}

最简单的方法是使
字符串
符合
错误

extension String: Error {}
extension String: LocalizedError {
    public var errorDescription: String? { return self }
}
然后你可以扔一根绳子:

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

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

@nick keets的解决方案是最优雅的,但它确实在test target中出现了以下编译时错误:

协议“错误”与“字符串”的冗余一致性

以下是另一种方法:

struct RuntimeError: Error {
    let message: String

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

    public var localizedDescription: String {
        return message
    }
}
以及使用:

throw RuntimeError("Error message.")

根据@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博客上:

swift 4:

根据:

如果不想定义自定义异常,可以使用标准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)")
  }
}
印刷品:

捕获N错误:操作无法完成,我的错误域,42
用户信息:
key=ui1,value=12
key=ui2,value=val2
这允许您提供一个自定义字符串(错误域)、一个数字代码和一个字典,以及您需要的任何类型的所有附加数据


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

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

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

我喜欢@Alexander Borisenko的答案,但当被发现为错误时,本地化描述没有返回。似乎您需要改用LocalizedError:

struct RuntimeError: LocalizedError
{
    let message: String

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

    public var errorDescription: String?
    {
        return message
    }
}

有关更多详细信息,请参阅。

如果您不需要捕获错误,并且希望立即停止应用程序,则可以使用fatalError:
fatalError(“此处的自定义消息”)

抛出代码应明确错误消息是否适合向最终用户显示,还是仅用于开发人员调试。为了向用户显示描述,我使用了一个struct
DisplayableError
,它实现了
LocalizedError
协议

struct DisplayableError:错误,LocalizedError{
let errorDescription:字符串?
初始化(描述:字符串){
errorDescription=描述
}
}
投掷的用法:

throw DisplayableError("Out of pixie dust.")
显示用途:

let messageToDisplay = error.localizedDescription

Swift 2抛接球也不例外。非常优雅的方式!真的很优雅!但在测试目标中,它会出现以下消息,即“字符串”与协议“错误”的冗余一致性
:(由于某些原因,这对我不起作用。表示在解析
错误时无法完成操作。引发字符串后localizedDescription
。警告:此扩展给我的外部库带来了问题。这对于任何管理错误的第三方库都是可能的;我将避免使用使字符串符合E的扩展。)错误。协议应该声明类型“是”,而不是“可能是”。字符串并不总是一个错误,这个扩展很容易让人意外地认为它是错误的,从而破坏了类型安全。嗨,我知道你发布这个答案已经有一年了,但我想知道是否有可能在你的
错误消息
中获取
字符串
,如果是,我该怎么做?@rencamaforte对不起,我不知道理解这个问题吗?
字符串
在这里与
MyError.RuntimeError
(在
抛出时设置)关联,您可以在
捕获
时访问它(使用
let errorMessage
)。您被要求提供最简单的解决方案。创建自定义枚举、函数等时的解决方案并不简单。我至少知道一种方法,但我不会将其发布到那里,因为这是为了实现目标-C@VyachaslavGerchicov如果您不知道Swift的更简单的方法,这也是问题中指定的,那么这将是最简单的方法,即使是y在一个更一般的上下文中,不包括Objy-C(简单地说,这个答案基本上是EnUM的一行一次定义,函数和它的调用是使用的一个例子,而不是解决方案的一部分)。@Otar是的,但是……您所说的是
try!
,这里没有使用它。如果没有某种
try
,您甚至不能进行潜在的抛出调用(代码的这一部分是示例用法,而不是实际的解决方案)关于你对我的答案的评论,这很简单,只是因为你有点武断地认为定义和枚举或扩展一次是复杂的。因此,是的,你的答案没有“设置”行,但代价是每个抛出的异常都是复杂和非快速的(
raise()
而不是
throw
)难以记忆的拼写。将您的解决方案与
抛出Foo.Bar(“baz”)
抛出“Foo”
乘以抛出异常的位置数进行比较——我是一次性费用