web-dev-qa-db-ja.com

Swift 2のカスタムメッセージでエラー/例外をスローする最も簡単な方法は?

他の複数の言語で使用していたSwift 2で何かを実行したい:カスタムメッセージでランタイム例外をスローします。例(Javaの場合):

throw new RuntimeException("A custom message here")

ErrorTypeプロトコルに準拠する列挙型をスローできることは理解していますが、スローするエラーのタイプごとに列挙型を定義する必要はありません。理想的には、上記の例を可能な限り模倣できるようにしたいと思います。 ErrorTypeプロトコルを実装するカスタムクラスの作成を検討しましたが、そのプロトコルに必要なものを把握することすらできません( documentation を参照)。アイデア?

111
markdb314

最も簡単なアプローチは、おそらくone custom enumを定義することです。それには、caseが付加されたStringが1つだけあります。

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になります。カスタムメソッドを使用して作成およびスローするファクトリメソッドを作成できます。

163
Arkku

最も簡単な方法は、StringErrorに準拠させることです。

extension String: Error {}

その後、単に文字列をスローすることができます:

throw "Some Error"

文字列自体をエラーのlocalizedStringにするには、代わりにLocalizedErrorを拡張します。

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

@ 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.")
15

このクールなバージョンをチェックしてください。考え方は、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
}
13
Teodor Ciuraru

スイフト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)でテストされました。

12
PJ_Finnegan

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

4
eonist

追加の拡張、列挙、クラスなどのない最も単純なソリューション:

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

詳細については this answer をご覧ください。

2
Benjamin Smith

FatalErrorを使用してください:fatalError ("Custom message here")

0
Roney Sampaio