신속한 언어의 오류 처리


190

나는 Swift를 너무 많이 읽지 않았지만 주목할 점은 예외가 없다는 것입니다. 그렇다면 Swift에서 오류 처리는 어떻게합니까? 누구든지 오류 처리와 관련된 것을 발견 했습니까?


1
Obj-C : o
Arbitur

13
@ Arbitur 좋은 오래된 segfault 방법?
peko

Swift에서 NSTimer를
만들었고

3
이 기사의 지침에 따라 Swift에 대한 try-catch 지원을 추가 할 수 있습니다. medium.com/@_willfalcon/adding-try-catch-to-swift-71ab27bcb5b8
William Falcon

@ peko Swift에서 segfault를 어떻게 처리합니까? 현재로서는 불가능하다고 생각합니다. 슬프게도 일부 오류를 복구 할 수 없습니다.
Orlin Georgiev

답변:


148

스위프트 2 & 3

새로운 오류 처리 메커니즘이 있기 때문에 예외와 다소 유사하지만 세부 사항이 다르기 때문에 Swift 2에서는 상황이 약간 변경되었습니다.

1. 오류 가능성 표시

함수 / 메소드에 오류가 발생할 수 있음을 나타내려면 다음 throws과 같은 키워드 를 포함해야합니다.

func summonDefaultDragon() throws -> Dragon

참고 : 함수가 실제로 던질 수있는 오류 유형에 대한 사양은 없습니다. 이 선언은 단순히 함수가 ErrorType을 구현하는 모든 유형의 인스턴스를 던질 수 있거나 전혀 던지지 않음을 나타냅니다.

2. 오류를 발생시킬 수있는 함수 호출

함수를 호출하려면 다음과 같이 try 키워드를 사용해야합니다.

try summonDefaultDragon()

이 줄은 일반적으로 이와 같은 do-catch 블록이 있어야합니다

do {
    let dragon = try summonDefaultDragon() 
} catch DragonError.dragonIsMissing {
    // Some specific-case error-handling
} catch DragonError.notEnoughMana(let manaRequired) {
    // Other specific-case error-handlng
} catch {
    // Catch all error-handling
}

참고 : catch 절은 Swift 패턴 일치의 모든 강력한 기능을 사용하므로 여기에서 매우 유연합니다.

throws키워드 자체로 표시된 함수에서 throwing 함수를 호출하는 경우 오류를 전파하기로 결정할 수 있습니다 .

func fulfill(quest: Quest) throws {
    let dragon = try summonDefaultDragon()
    quest.ride(dragon)
} 

또는 다음을 사용하여 투사 기능을 호출 할 수 있습니다 try?.

let dragonOrNil = try? summonDefaultDragon()

이렇게하면 오류가 발생하면 반환 값을 얻거나 nil을 얻습니다. 이 방법을 사용하면 오류 개체가 나타나지 않습니다.

즉, 다음 try?과 같은 유용한 문장과 결합 할 수도 있습니다 .

if let dragon = try? summonDefaultDragon()

또는

guard let dragon = try? summonDefaultDragon() else { ... }

마지막으로, 실제로 오류가 발생하지 않는다는 것을 알 수 있으며 (예 : 이미 확인한 전제 조건이므로) try!키워드를 사용하십시오 .

let dragon = try! summonDefaultDragon()

함수에서 실제로 오류가 발생하면 응용 프로그램에 런타임 오류가 발생하고 응용 프로그램이 종료됩니다.

3. 오류 발생

오류를 발생시키기 위해 다음과 같이 throw 키워드를 사용하십시오

throw DragonError.dragonIsMissing

ErrorType프로토콜에 맞는 것을 던질 수 있습니다 . 초보자 NSError는이 프로토콜을 준수하지만 열거 형 ErrorType을 사용하여 여러 관련 오류를 잠재적으로 다음과 같은 추가 데이터 조각으로 그룹화 할 수 있습니다.

enum DragonError: ErrorType {
    case dragonIsMissing
    case notEnoughMana(requiredMana: Int)
    ...
}

새로운 Swift 2 & 3 오류 메커니즘과 Java / C # / C ++ 스타일 예외의 주요 차이점은 다음과 같습니다.

  • 구문은 약간 다릅니다 : do-catch+ try+ defer와 기존 try-catch-finally구문.
  • 예외 처리는 일반적으로 성공 경로보다 예외 경로에서 훨씬 더 높은 실행 시간을 발생시킵니다. 성공 경로와 오류 경로의 비용이 거의 같은 Swift 2.0 오류의 경우에는 그렇지 않습니다.
  • 모든 오류 발생 코드를 선언해야하지만 예외는 어디에서나 발생했을 수 있습니다. Java 명명법에서는 모든 오류가 "체크 된 예외"입니다. 그러나 Java와 달리 잠재적으로 발생 된 오류를 지정하지 않습니다.
  • 스위프트 예외는 ObjC 예외와 호환되지 않습니다. 당신의 do-catch당신이 ObjC를 사용해야합니다 그것을 위해 블록은, 반대로 어떤 NSException, 그리고 그 반대를 잡을 수 없습니다.
  • Swift 예외는 ( 함수 를 리턴 하기 위해 ) 또는 ( 함수 를 리턴 하기 위해) 리턴 하고 오류 세부 사항을 전달하는 Cocoa NSError메소드 규칙 과 호환됩니다 .falseBoolnilAnyObjectNSErrorPointer

오류 처리를 용이하게하는 여분의 합성 설탕으로서 두 가지 개념이 더 있습니다

  • deferJava / C # / etc의 finally 블록과 동일한 효과를 얻을 수있는 지연된 동작 ( 키워드 사용 )
  • 가드 문 ( guard키워드 사용 )을 사용 하면 일반적인 오류 확인 / 신호 코드보다 if / else 코드를 적게 작성할 수 있습니다.

스위프트 1

런타임 오류 :

Leandros는 네트워크 연결 문제, 데이터 구문 분석, 파일 열기 등과 같은 런타임 오류 처리에 NSError대해 Foundation, AppKit, UIKit 등이 이러한 방식으로 오류를보고하므로 ObjC에서와 같이 사용해야합니다 . 언어보다 프레임 워크가 더 중요합니다.

AFNetworking과 같은 분리기 성공 / 실패 블록이 사용되는 또 다른 빈번한 패턴은 다음과 같습니다.

var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets"))
sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingSquad,
    success: { (NSURLSessionDataTask) -> Void in
        println("Success")
    },
    failure:{ (NSURLSessionDataTask, NSError) -> Void in
        println("Failure")
    })

여전히 오류 블록 NSError은 오류를 설명하는 인스턴스를 자주 받았습니다 .

프로그래머 오류 :

프로그래머 오류 (배열 요소의 범위를 벗어난 액세스, 함수 호출에 전달 된 잘못된 인수 등)의 경우 ObjC에서 예외를 사용했습니다. Swift 언어는 예외 (예 throw: catch, 등의 키워드)에 대한 언어 지원이없는 것 같습니다 . 그러나 문서에 따르면 ObjC와 동일한 런타임에서 실행 중이므로 여전히 NSExceptions다음과 같이 던질 수 있습니다 .

NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()

ObjC 코드에서 예외를 포착하도록 선택할 수도 있지만 순수한 Swift에서는이를 포착 할 수 없습니다.

문제는 프로그래머 오류에 대한 예외를 던지거나 언어 가이드에서 Apple이 제안한 어설 션을 사용해야하는지 여부입니다.


20
Cocoa API (NSFileHandle)를 사용하는 "네트워크 연결 문제"및 "파일 열기"는 예외가 발생할 수 있습니다. Swift에서 예외없이 Objective-C에서 프로그램의이 부분을 구현하거나 BSD C API를 사용하여 모든 작업을 수행해야합니다 (둘 다 해결 방법이 좋지 않습니다). 더 ...에 대한 NSFileHandle.writeData에 대한 설명서를 참조하십시오 developer.apple.com/library/ios/documentation/Cocoa/Reference/... :
매트 갤러거

5
다시 말하지만 예외 처리는 모든 고유 한 문제가있는 2 단계 객체 구성을 의미합니다. stroustrup.com/except.pdf를 참조하십시오 .
Phil

2
fatalError(...)아니라 동일합니다.
holex

8
내가 스위프트를 좋아하는만큼, 이것은 이것이 치명적인 선택이라고 생각하고, 그 결과의 일부를 맛 보았을 때, 그들은이 생략으로 불을 가지고 놀고있다.
Rob

2
예, 확인 된 예외는 이제 조금만 사용됩니다. 프로그래머가 예외를 잡아야한다는 것은 단일 책임 원칙을 깨는 방식으로 오염 코드에서 복구 할 가능성이 거의 없다는 것이 밝혀 졌기 때문입니다. 도메인 수준 클래스는 인프라 계층 예외를 처리하지 않아도됩니다. 따라서, 점검되지 않은 예외는 선호되는 경향이 있으며, 해당되는 경우 이해 당사자가 예외를 포착 할 수 있습니다. . 확인 됨 = 확실히 복구 가능. 확인되지 않음 = 비 / 잠재적으로 복구 가능
재스퍼 블루스

69

2015 년 6 월 9 일 업데이트-매우 중요

스위프트 2.0 함께 제공 try, throwcatch키워드와 가장 흥미로운입니다 :

Swift는 오류를 생성하는 Objective-C 메소드를 Swift의 기본 오류 처리 기능에 따라 오류를 발생시키는 메소드로 자동 변환합니다.

참고 : NSError 객체 인수와 함께 완료 처리기를 사용하는 대리자 메서드 또는 메서드와 같이 오류를 소비하는 메서드는 Swift에서 가져올 때 throw되는 메서드가 아닙니다.

발췌 : Apple Inc.“Cocoa 및 Objective-C와 함께 Swift 사용 (Swift 2 시험판).” iBooks.

예 : (책에서)

NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *URL = [NSURL fileURLWithPath:@"/path/to/file"];
NSError *error = nil;
BOOL success = [fileManager removeItemAtURL:URL error:&error];
if (!success && error){
    NSLog(@"Error: %@", error.domain);
}

신속한 대응은 다음과 같습니다.

let fileManager = NSFileManager.defaultManager()
let URL = NSURL.fileURLWithPath("path/to/file")
do {
    try fileManager.removeItemAtURL(URL)
} catch let error as NSError {
    print ("Error: \(error.domain)")
}

오류 발생 :

*errorPtr = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCannotOpenFile userInfo: nil]

발신자에게 자동으로 전파됩니다.

throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)

Apple의 책에서 Swift Programming Language는 enum을 사용하여 오류를 처리해야합니다.

다음은이 책의 예입니다.

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}

let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")

switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure...  \(error)"
}

출처 : Apple Inc. "Swift Programming Language" iBooks. https://itun.es/br/jEUH0.l

최신 정보

Apple 뉴스 서적, "Cocoa 및 Objective-C와 함께 Swift 사용". 신속한 언어를 사용하면 런타임 예외가 발생하지 않으므로 try-catch가 없습니다. 대신 옵션 체인 을 사용 합니다.

이 책의 내용은 다음과 같습니다.

예를 들어 아래 코드 목록에서 length 속성과 characterAtIndex : 메서드가 NSDate 개체에 없기 때문에 첫 번째와 두 번째 줄은 실행되지 않습니다. myLength 상수는 선택적 Int 인 것으로 추론되며 nil로 설정됩니다. if-let 문을 사용하여 3 행에 표시된 것처럼 오브젝트가 응답하지 않을 수있는 메소드의 결과를 조건부 랩 해제 할 수도 있습니다.

let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)
if let fifthCharacter = myObject.characterAtIndex(5) {
    println("Found \(fifthCharacter) at index 5")
}

발췌 : Apple Inc.“Cocoa 및 Objective-C와 함께 Swift 사용” iBooks. https://itun.es/br/1u3-0.l


또한이 책은 Objective-C (NSError Object)의 코코아 오류 패턴을 사용하도록 권장합니다.

Swift의 오류보고는 Objective-C에서와 동일한 패턴을 따르며 선택적 반환 값을 제공 할 수 있다는 이점이 있습니다. 가장 간단한 경우 함수에서 Bool 값을 반환하여 성공했는지 여부를 나타냅니다. 오류 이유를보고해야하는 경우 NSErrorPointer 유형의 NSError 출력 매개 변수를 함수에 추가 할 수 있습니다. 이 유형은 추가 메모리 안전 및 선택적 입력을 통해 Objective-C의 NSError **와 거의 동일합니다. 아래 코드 목록에 표시된 것처럼 접두사 및 연산자를 사용하여 선택적 NSError 유형에 대한 참조를 NSErrorPointer 객체로 전달할 수 있습니다.

var writeError : NSError?
let written = myString.writeToFile(path, atomically: false,
    encoding: NSUTF8StringEncoding,
    error: &writeError)
if !written {
    if let error = writeError {
        println("write failure: \(error.localizedDescription)")
    }
}

발췌 : Apple Inc.“Cocoa 및 Objective-C와 함께 Swift 사용” iBooks. https://itun.es/br/1u3-0.l


마지막 문장의 경우 : do {try myString.writeToFile (path, atomically : true, encoding : NSUTF8StringEncoding)} try NSError as error {print (error)}
Jacky

1
@Jacky 네, 그것은 swift 2.0에 해당합니다.이 답변은 swift 2.0이 출시되기 전에 작성되었지만 swift 2.0의 새로운 방법 처리 오류를 보여주기 위해 답변을 업데이트했습니다. 내가 참조를 위해이 방법을시키는에 생각하고 있었다, 그러나 나는 단지 신속 2.0 사용하는 전체 답을 업데이트 고려할 것
Guilherme 토레스 카스트로

12

Objective-C의 접근 방식과 비슷한 Swift에는 예외가 없습니다.

개발 과정에서 assert나타날 수있는 오류를 파악하고 프로덕션 환경으로 가기 전에 수정해야 할 때 사용할 수 있습니다.

고전적인 NSError접근 방식은 변경되지 않고을 보내면 NSErrorPointer채워집니다.

간단한 예 :

var error: NSError?
var contents = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/Users/leandros", error: &error)
if let error = error {
    println("An error occurred \(error)")
} else {
    println("Contents: \(contents)")
}

6
이것은 Swift에서 호출하는 ObjC 코드가 실제로 예외를 던질 때 발생하는 것과 NSError가 ObjC에서와 같이 보편적 인 오류 객체인지 여부는 두 가지 질문입니다.
MDJ

1
초기화 프로그램이 실패하거나 실패 할 수 없다는 것이 Swift의 삶의 사실입니까?
Phil

11
예외 처리는 다소 더러워 보입니다
Tash Pemhiwa

27
네, 충돌 할 때 누가 예외가 필요한가요? 또는 선언 한 모든 함수에서 NSError **를 인수로 사용 하시겠습니까? 그래서 모든 f();g();것이 f(&err);if(err) return;g(&err);if(err) return;첫 달이되게되었고, 이제 막f(nil);g(nil);hopeToGetHereAlive();
hariseldon78

2
이 답변은 구식 (Swift는 이제 예외를 지원함)과 잘못 (Objective-C는 예외를 지원합니다)
Rog

11

권장되는 'Swift Way'는 다음과 같습니다.

func write(path: String)(#error: NSErrorPointer) -> Bool { // Useful to curry error parameter for retrying (see below)!
    return "Hello!".writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: error)
}

var writeError: NSError?
let written = write("~/Error1")(error: &writeError)
if !written {
    println("write failure 1: \(writeError!.localizedDescription)")
    // assert(false) // Terminate program
}

그러나 오류 처리를 끝에 별도의 블록으로 이동하기 때문에 추적하기가 더 쉬우므로 try / catch를 선호합니다.이 배열을 "황금 경로"라고도합니다. 운이 좋으면 클로저 로이 작업을 수행 할 수 있습니다.

TryBool {
    write("~/Error2")(error: $0) // The code to try
}.catch {
    println("write failure 2: \($0!.localizedDescription)") // Report failure
    // assert(false) // Terminate program
}

또한 재시도 기능을 쉽게 추가 할 수 있습니다.

TryBool {
    write("~/Error3")(error: $0) // The code to try
}.retry {
    println("write failure 3 on try \($1 + 1): \($0!.localizedDescription)")
    return write("~/Error3r")  // The code to retry
}.catch {
    println("write failure 3 catch: \($0!.localizedDescription)") // Report failure
    // assert(false) // Terminate program
}

TryBool의 리스팅은 다음과 같습니다 :

class TryBool {
    typealias Tryee = NSErrorPointer -> Bool
    typealias Catchee = NSError? -> ()
    typealias Retryee = (NSError?, UInt) -> Tryee

    private var tryee: Tryee
    private var retries: UInt = 0
    private var retryee: Retryee?

    init(tryee: Tryee) {
        self.tryee = tryee
    }

    func retry(retries: UInt, retryee: Retryee) -> Self {
        self.retries = retries
        self.retryee = retryee
        return self
    }
    func retry(retryee: Retryee) -> Self {
        return self.retry(1, retryee)
    }
    func retry(retries: UInt) -> Self {
        // For some reason you can't write the body as "return retry(1, nil)", the compiler doesn't like the nil
        self.retries = retries
        retryee = nil
        return self
    }
    func retry() -> Self {
        return retry(1)
    }

    func catch(catchee: Catchee) {
        var error: NSError?
        for numRetries in 0...retries { // First try is retry 0
            error = nil
            let result = tryee(&error)
            if result {
                return
            } else if numRetries != retries {
                if let r = retryee {
                    tryee = r(error, numRetries)
                }
            }
        }
        catchee(error)
    }
}

Bool 값 대신 Optional 반환 값을 테스트하기 위해 비슷한 클래스를 작성할 수 있습니다.

class TryOptional<T> {
    typealias Tryee = NSErrorPointer -> T?
    typealias Catchee = NSError? -> T
    typealias Retryee = (NSError?, UInt) -> Tryee

    private var tryee: Tryee
    private var retries: UInt = 0
    private var retryee: Retryee?

    init(tryee: Tryee) {
        self.tryee = tryee
    }

    func retry(retries: UInt, retryee: Retryee) -> Self {
        self.retries = retries
        self.retryee = retryee
        return self
    }
    func retry(retryee: Retryee) -> Self {
        return retry(1, retryee)
    }
    func retry(retries: UInt) -> Self {
        // For some reason you can't write the body as "return retry(1, nil)", the compiler doesn't like the nil
        self.retries = retries
        retryee = nil
        return self
    }
    func retry() -> Self {
        return retry(1)
    }

    func catch(catchee: Catchee) -> T {
        var error: NSError?
        for numRetries in 0...retries {
            error = nil
            let result = tryee(&error)
            if let r = result {
                return r
            } else if numRetries != retries {
                if let r = retryee {
                    tryee = r(error, numRetries)
                }
            }
        }
        return catchee(error)
    }
}

TryOptional 버전은 선택적 프로그래밍이 아닌 리턴 유형을 적용하여 'Swift Way :

struct FailableInitializer {
    init?(_ id: Int, error: NSErrorPointer) {
        // Always fails in example
        if error != nil {
            error.memory = NSError(domain: "", code: id, userInfo: [:])
        }
        return nil
    }
    private init() {
        // Empty in example
    }
    static let fallback = FailableInitializer()
}

func failableInitializer(id: Int)(#error: NSErrorPointer) -> FailableInitializer? { // Curry for retry
    return FailableInitializer(id, error: error)
}

var failError: NSError?
var failure1Temp = failableInitializer(1)(error: &failError)
if failure1Temp == nil {
    println("failableInitializer failure code: \(failError!.code)")
    failure1Temp = FailableInitializer.fallback
}
let failure1 = failure1Temp! // Unwrap

TryOptional 사용하기 :

let failure2 = TryOptional {
    failableInitializer(2)(error: $0)
}.catch {
    println("failableInitializer failure code: \($0!.code)")
    return FailableInitializer.fallback
}

let failure3 = TryOptional {
    failableInitializer(3)(error: $0)
}.retry {
    println("failableInitializer failure, on try \($1 + 1), code: \($0!.code)")
    return failableInitializer(31)
}.catch {
    println("failableInitializer failure code: \($0!.code)")
    return FailableInitializer.fallback
}

자동 언 랩핑을 참고하십시오.


7

편집 : 이 답변은 효과가 있지만 Objective-C가 Swift로 음역되는 것 이상입니다. Swift 2.0의 변경으로 인해 더 이상 사용되지 않습니다. 위의 Guilherme Torres Castro의 답변은 Swift에서 오류를 처리하는 기본 방법에 대한 아주 좋은 소개입니다. VOS

알아내는 데 약간의 시간이 걸렸지 만 나는 그것을 생각한 것 같습니다. 그래도 추한 것 같습니다. Objective-C 버전의 얇은 스킨에 지나지 않습니다.

NSError 매개 변수를 사용하여 함수 호출 ...

var fooError : NSError ? = nil

let someObject = foo(aParam, error:&fooError)

// Check something was returned and look for an error if it wasn't.
if !someObject {
   if let error = fooError {
      // Handle error
      NSLog("This happened: \(error.localizedDescription)")
   }
} else {
   // Handle success
}`

에러 파라미터를받는 함수 작성 중 ...

func foo(param:ParamObject, error: NSErrorPointer) -> SomeObject {

   // Do stuff...

   if somethingBadHasHappened {
      if error {
         error.memory = NSError(domain: domain, code: code, userInfo: [:])
      }
      return nil
   }

   // Do more stuff...
}


5

시험 Catch 기능을 제공하는 objective C 주변의 기본 래퍼입니다. https://github.com/williamFalcon/SwiftTryCatch

다음과 같이 사용하십시오.

SwiftTryCatch.try({ () -> Void in
        //try something
     }, catch: { (error) -> Void in
        //handle error
     }, finally: { () -> Void in
        //close resources
})

좋은 생각. 그러나 이것을 사용하기로 결정한 사람은 예외가 발생했을 때 try 블록에 할당 된 객체가 할당 해제되지 않음을 명심해야합니다. 이것은 좀비 개체의 문제를 일으킬 수 있으며 RAII의 모든 사용이 손상됩니다 (자동 잠금 해제, 자동 SQL 커밋, 자동 SQL 롤백 ...). 아마도 c ++가 "runAtExit"의 어떤 형태로 우리를 도울 수 있을까요?
hariseldon78

업데이트 : 방금 예외 발생시 객체를 해제 할 수있는 플래그가 clang에 있음을 발견했습니다 : -fobjc-arc-exceptions. 랩핑 된 버전으로 여전히 작동하는지 시도해야합니다. (그렇다고 생각합니다)
hariseldon78

이 옵션을 사용하면 컴파일러에서 반-예외 안전 코드를 생성해야하므로 코드 크기가 커집니다. 또한 : 그러한 컴파일러 기능에 의존하는 것이 가장 좋은 아이디어는 아닙니다. 프로그래머 오류에 대한 예외는 개발 중에 약간의 메모리를 절약하기 위해 컴파일러 옵션을 사용하는 것은 가치가 없습니다. 프로덕션 코드에 예외가있는 경우 먼저 예외를 발생시키는 것을 처리해야합니다.
Christian Kienle

1
통제 할 수없는 상황이있을 수 있습니다. 예를 들어, 잘못된 형식으로 json을 구문 분석합니다.
William Falcon

3

이것은 swift 2.0에 대한 업데이트 답변입니다. Java와 같은 기능이 풍부한 오류 처리 모델을 기대하고 있습니다. 마침내 그들은 좋은 소식을 발표했습니다. 여기

오류 처리 모델 : Swift 2.0의 새로운 오류 처리 모델은 익숙한 try, throw 및 catch 키워드를 사용 하여 자연스럽게 느껴집니다 . 무엇보다도 Apple SDK 및 NSError와 완벽하게 작동하도록 설계되었습니다. 실제로 NSError는 Swift의 ErrorType을 따릅니다. Swift의 새로운 기능에 대한 WWDC 세션을 확실히보고 싶을 것입니다.

예 :

func loadData() throws { }
func test() {
do {
    try loadData()
} catch {
    print(error)
}}

3

Guilherme 토레스 카스트로가 말했듯이, 스위프트 2.0, try, catch, do프로그래밍에 사용할 수 있습니다.

예를 들어,에서 CoreData 대신 넣어의 데이터 방법을 가져 &error에 매개 변수로 managedContext.executeFetchRequest(fetchRequest, error: &error)지금 우리는 사용을 사용할 필요가, managedContext.executeFetchRequest(fetchRequest)다음으로 오류를 처리 try, catch( 애플의 문서 링크 )

do {
   let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as? [NSManagedObject]
   if let results = fetchedResults{
      people = results
   }
} catch {
   print("Could not fetch")
}

xcode7 베타를 이미 다운로드 한 경우 설명서 및 API 참조 에서 오류 발생 을 검색 하고 첫 번째로 표시되는 결과를 선택하면이 새로운 구문에 대해 수행 할 수있는 기본 아이디어가 제공됩니다. 그러나 많은 API에 대한 완전한 문서는 아직 게시되지 않았습니다.

더 멋진 오류 처리 기술은

Swift의 새로운 기능 (2015 세션 106 28m30s)



1

예외를 처리하기위한 훌륭하고 간단한 라이브러리 : TryCatchFinally-Swift

다른 몇 가지와 마찬가지로 객관적인 C 예외 기능을 둘러 쌉니다.

다음과 같이 사용하십시오.

try {
    println("  try")
}.catch { e in
    println("  catch")
}.finally {
    println("  finally")
}

나는 샘플을 추가했다 :)
Morten Holmgaard

"경고 : 이것은 재미와 악의 해킹입니다. 그것을 사용하려는 유혹에 저항하십시오."
jbat100

1

다른 사람들이 이미 언급했듯이 Swift 2부터는 오류 처리는 do / try / catch 및 ErrorType 열거 형을 사용하여 가장 잘 수행됩니다. 이 방법은 동기식 방법에는 적합하지만 비동기식 오류 처리에는 약간의 영리함이 필요합니다.

이 기사에는이 문제에 대한 훌륭한 접근 방식이 있습니다.

https://jeremywsherman.com/blog/2015/06/17/using-swift-throws-with-completion-callbacks/

요약:

// create a typealias used in completion blocks, for cleaner code
typealias LoadDataResult = () throws -> NSData

// notice the reference to the typealias in the completionHandler
func loadData(someID: String, completionHandler: LoadDataResult -> Void)
    {
    completionHandler()
    }

위의 메소드에 대한 호출은 다음과 같습니다.

self.loadData("someString",
    completionHandler:     
        { result: LoadDataResult in
        do
            {
            let data = try result()
            // success - go ahead and work with the data
            }
        catch
            {
            // failure - look at the error code and handle accordingly
            }
        })

이것은 별도의 errorHandler 콜백을 비동기 함수에 전달하는 것보다 조금 더 깨끗해 보입니다. 이는 Swift 2 이전에 처리 된 방식이었습니다.


0

내가 본 것은 장치의 특성으로 인해 사용자에게 많은 암호 오류 처리 메시지를 던지고 싶지 않다는 것입니다. 그렇기 때문에 대부분의 함수는 선택적 값을 반환하고 옵션을 무시하도록 코드를 작성합니다. 함수가 nil을 반환하면 실패했다는 메시지 또는 기타 메시지를 표시 할 수 있습니다.


1
nil을 반환하면 오류의 성격에 대한 정보가 반환되지 않습니다. 오류가 발생했을 때 오류 개체가 반환되면 오류에 따라 프로그래머는 오류를 무시하고 처리하고 버블 링하거나 "메시지 또는 기타 메시지를 표시"하도록 선택할 수 있습니다. 아는 것이 힘이다.
빈스 오 설리번
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.