Ios 在Swift 2中使用自定义消息引发错误/异常的最简单方法?
我想在Swift 2中做一些我在其他多种语言中已经习惯的事情:抛出一个带有自定义消息的运行时异常。例如(在Java中):Ios 在Swift 2中使用自定义消息引发错误/异常的最简单方法?,ios,swift,swift2,Ios,Swift,Swift2,我想在Swift 2中做一些我在其他多种语言中已经习惯的事情:抛出一个带有自定义消息的运行时异常。例如(在Java中): 我知道我可以抛出符合ErrorType协议的枚举类型,但我不想为我抛出的每种类型的错误定义枚举。理想情况下,我希望能够尽可能地模仿上面的例子。我研究了如何创建一个实现ErrorType协议的自定义类,但我甚至不能确定该协议需要什么(请参阅)。想法?最简单的方法可能是定义一个自定义枚举,其中只有一个案例,该案例附带一个字符串: enum MyError: ErrorType {
我知道我可以抛出符合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(“此处的自定义消息”)
抛出代码应明确错误消息是否适合向最终用户显示,还是仅用于开发人员调试。为了向用户显示描述,我使用了一个structDisplayableError
,它实现了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”
乘以抛出异常的位置数进行比较——我是一次性费用