Swift 2에서 사용자 정의 메시지로 오류 / 예외를 발생시키는 가장 간단한 방법은 무엇입니까?


136

Swift 2에서 다른 여러 언어로 익숙한 작업을하고 싶습니다. 사용자 정의 메시지로 런타임 예외를 throw하십시오. 예를 들어 (Java) :

throw new RuntimeException("A custom message here")

ErrorType 프로토콜을 준수하는 열거 형 유형을 던질 수 있다는 것을 알고 있지만 던지는 모든 유형의 오류에 대해 열거 형을 정의하고 싶지는 않습니다. 이상적으로는 위의 예를 가능한 한 유사하게 모방하고 싶습니다. ErrorType 프로토콜을 구현하는 사용자 정의 클래스를 만들려고 시도했지만 해당 프로토콜에 필요한 것이 무엇인지 파악할 수도 없습니다 ( documentation 참조 ). 아이디어?


2
스위프트 2 스로우 / 캐치는 예외가 아닙니다.
zaph

답변:


194

가장 간단한 방법은 정의 아마 하나의 정의를 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은이며 사용자 정의 메시지로 유형을 작성하고 던지는 팩토리 메소드를 작성할 수 있습니다.


안녕하세요, 귀하가이 답변을 게시 한 지 1 년이되었다는 것을 알고 있지만 String귀하 의 내부 를 알아볼 수 있는지 알고 싶습니다. errorMessage그렇다면 어떻게해야합니까?
Renan Camaforte 1

1
@RenanCamaforte 죄송합니다. 질문을 이해하지 못합니까? 는 String여기 연관된다 MyError.RuntimeError(시간에 세트 throw), 당신은에서 그것에 접근 획득 catch(과를 let errorMessage).
Arkku

1
가장 간단한 솔루션을 요청했습니다. 사용자 정의 열거 형, 함수 등을 만들 때의 해결책은 간단하지 않습니다. 나는 적어도 한 가지 방법을 알고 있지만 objective-C를위한 것이므로 게시하지 않을 것입니다
Vyachaslav Gerchicov

3
@VyachaslavGerchicov 질문에 지정된 Swift에 대한 간단한 방법을 모른다면 이것이 가장 간단한 방법 일 것입니다. . (또한이 답변은 기본적으로 열거 형에 대한 일회성 일회성 정의이며, 함수 및 해당 호출은 솔루션의 일부가 아닌 사용법의 예입니다.
Arkku

1
@Otar 그렇습니다.하지만…에 대해 이야기하고 있지만 try!여기서는 사용되지 않습니다. 당신은 실제로 어떤 종류의 없이는 잠재적으로 던지는 전화를 걸 수 없습니다 try. (또한 코드의 일부는 실제 솔루션이 아니라 사용 예입니다.)
Arkku

136

가장 간단한 방법은 다음을 String준수하는 것입니다 Error.

extension String: Error {}

그런 다음 문자열을 던질 수 있습니다.

throw "Some Error"

문자열 자체를 localizedString오류 로 만들기 위해 대신 확장 할 수 있습니다 LocalizedError.

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

이것은 영리하지만 localizedDescription문자열 자체 로 만드는 방법이 있습니까?
빌라 포수 01. 25. 17.

1
매우 우아한 방법!
Vitaliy Gozhenko

1
정말 우아합니다! 그러나 다음과 같은 메시지가 테스트 대상에 나를 위해 분해 Redundant conformance of 'String' to protocol 'Error':(
알렉산더 Borisenko에게

2
어떤 이유로 든 이것이 효과가 없습니다. error.localizedDescription문자열을 던진 후 구문 분석 할 때 작업을 완료 할 수 없다고 말합니다 .
Noah Allen

1
경고 :이 확장으로 인해 외부 라이브러리에 문제가 발생했습니다. 여기 내 예가 있습니다. 오류를 관리하는 모든 타사 라이브러리에서 가능합니다. String이 Error를 준수하도록하는 확장을 피할 수 있습니다.
Bryan W. Wagner

20

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

19

이 멋진 버전을 확인하십시오. 아이디어는 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
}

여전히 필요에 따라,이 방법에 약간의 도움이 될 것 같습니다 as User.UserValidationError과 그 위에을 .rawValue. 대신 구현하는 경우에는 CustomStringConvertible같은 var description: String { return rawValue },을 통해 갈 필요없이 열거 구문을 사용하여 사용자 정의 설명을 얻을 수 유용 할 수 있습니다 rawValue당신이 그것을 인쇄 할 경우 모든 장소에서.
Arkku

1
더 나은 .rawValue 반환 localizedDescription 메소드를 구현
DanSkeel

16

스위프트 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

이를 통해 사용자 정의 문자열과 숫자 코드 및 필요한 모든 추가 데이터가 포함 된 사전을 모든 유형으로 제공 할 수 있습니다.

NB : OS = Linux (Ubuntu 16.04 LTS)에서 테스트되었습니다.


12

추가 확장, 열거 형, 클래스 등이없는 가장 간단한 솔루션 :

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

2
레. 내 대답에 대한 귀하의 의견, 이것은 정의 및 열거 또는 확장을 한 번 정의하는 것이 다소 복잡 하다고 임의로 결정했다는 의미에서 간단합니다 . 따라서 네 대답에는 "setup"줄이 없지만 모든 예외를 희생시키면서 기억하기 어려운 복잡하고 스위프트가 아닌 ( 주문 raise()대신 throw) 철자를 사용하십시오. 귀하의 솔루션과 예외가 발생한 장소의 수를 곱 throw Foo.Bar("baz")하거나 throw "foo"곱한 값을 비교하십시오 – IMO 일회성 연장 또는 열거 형의 일회성 요금은와 같은 것보다 훨씬 선호됩니다 NSExceptionName.
Arkku

@Arkku 예를 들어 postNotification2-3 개의 매개 변수가 필요하며 선택기는이 매개 변수와 유사합니다. 더 적은 입력 매개 변수를 허용하도록 각 프로젝트를 재정의 Notification및 / 또는 무시 NotificationCenter합니까?
Vyachaslav Gerchicov

1
아니요, 본인의 답변으로는 솔루션을 사용하지 않을 것입니다. 나는 내가 스스로 할 일이 아니기 때문에 질문에 대답하기 위해 그것을 게시했습니다. 어쨌든, 그것은 요점 외에 있습니다 : 나는 당신의 대답이 광산이나 Nick Keets의 것보다 사용하기 가 훨씬 더 복잡하다는 의견에 견딜 수 있습니다 . 물론 String준수하기 위해 확장 하는 Error것이 너무 놀랍거나 MyError열거 형이 너무 모호한 경우와 같이 고려해야 할 다른 유효한 점이 있습니다 (개인적으로 두 가지 모두에 예라고 대답하고 대신 각 오류에 대해 별도의 열거 형 사례를 수행합니다. throw ThisTypeOfError.thisParticularCase).
Arkku

6

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


1
TBH : 나는 이제 막throw NSError(message: "err", code: 0)
eonist

그래서 당신은 당신 자신의 예를 사용하지 않습니까? : D 아, 그리고 첫 번째 주장은 domain그렇지 message않습니까?
NRitH

1
당신의 권리, 도메인. 그리고 아니요, 코드에 설탕을 너무 많이 넣습니다. 나는 보통 작은 프레임 워크와 모듈을 많이 만들고 편리한 확장 설탕을 낮게 유지하려고합니다. 요즘 나는 결과와 NSError 사이의 혼합을 사용하려고
eonist

6

오류를 잡을 필요가없고 응용 프로그램을 즉시 중지하려는 경우 fatalError를 사용할 수 있습니다. fatalError ("Custom message here")


3
이것은 잡힐 수있는 오류를 발생시키지 않습니다. 앱이 중단됩니다.
Adil Hussain

4

@ Alexander-Borisenko의 답변이 마음에 들지만 오류로 잡힐 때 현지화 된 설명이 반환되지 않았습니다. 대신 LocalizedError를 사용해야하는 것 같습니다.

struct RuntimeError: LocalizedError
{
    let message: String

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

    public var errorDescription: String?
    {
        return message
    }
}

자세한 내용은 이 답변 을 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.