NOTE Swift에서 에러 처리는 Cocoa와 Objective-C에NSError
를 사용하는 에러 처리 패턴과 상호 운용됩니다. 더많은 정보는 Swift에서 Cocoa 에러 처리 (Handling Cocoa Errors in Swift) 를 참고 바랍니다.
Error
프로토콜에 준수하는 타입의 값으로 표현됩니다. 이 빈 프로토콜은 에러를 처리하는 것에 대해 사용될 수 있음을 나타냅니다.throw
구문을 사용하여 에러를 발생 시킵니다. 예를 들어 아래의 코드는 자동 판매기에 5개의 코인이 더 필요하다고 에러를 발생 시킵니다:do
-catch
구문을 사용하거나 옵셔널 값으로 에러를 처리하거나 에러가 발생하지 않을 것이라고 주장할 수 있습니다. 각 접근은 아래에 설명되어 있습니다.try
또는 try?
또는 try!
키워드를 작성합니다. 이 키워드는 아래에 설명되어 있습니다.NOTE Swift에서 에러 처리는try
,catch
그리고throw
키워드를 사용하는 다른 언어에서 에러 처리와 유사합니다. Objective-C를 포함하여 많은 언어에서의 예외 처리와 달리 Swift에서 에러 처리는 계산 비용이 많이 드는 프로세스 인 호출 스택 해제가 포함되지 않습니다. 따라서throw
구문의 성능 특성은return
구문의 성능 특성과 비슷합니다.
throws
키워드를 작성합니다. throws
로 표시된 함수는 던지기 함수 라고 합니다. 함수에 반환 타입이 지정되어 있으면 throws
키워드는 반환 화살표 (->
) 전에 작성합니다.NOTE 던지기 함수는 에러를 전파만 할 수 있습니다. 던지기 선언이 되지 않은 함수 내에서 발생된 모든 에러는 함수 내에서 처리되어야 합니다.
VendingMachine
클래스는 요청된 항목이 불가능 하거나 품절이거나 현재 입금액을 초과하는 비용이 있는 경우 적절한 VendingMachineError
를 발생하는 vend(itemNamed:)
메서드를 가지고 있습니다:vend(itemNamed:)
메서드의 구현은 guard
구문을 사용하여 메서드를 일찍 종료시키고 스낵 구매 요구사항 중 하나라도 충족하지 않으면 적절한 에러를 발생합니다. throw
구문은 프로그램 제어를 즉시 전달하므로 항목은 요구사항이 모두 만족해야만 판매됩니다.vend(itemNamed:)
메서드는 발생하는 에러를 전파하기 때문에 이 메서드를 호출하는 코드는 do
-catch
구문, try?
또는 try!
를 사용하여 에러를 처리하거나 계속 전파해야 합니다. 예를 들어 아래 예제에서 buyFavoriteSnack(person:vendingMachine:)
은 던지기 함수이며 vend(itemNamed:)
메서드에서 발생한 에러는 buyFavoriteSnack(person:vendingMachine:)
함수가 호출된 지점까지 전파될 것입니다.buyFavoriteSnack(person:vendingMachine:)
함수는 주어진 사람의 좋아하는 스낵을 검색하고 vend(itemNamed:)
메서드를 호출하여 그 제품을 구입합니다. vend(itemNamed:)
메서드는 에러를 발생할 수 있으므로 try
키워드를 앞에 두어 호출됩니다.PurchasedSnack
구조체의 초기화 구문은 초기화 프로세스 부분으로 던지기 함수를 호출하고 발생하는 모든 에러를 호출자에게 전파하여 처리합니다.do
-catch
구문을 사용하여 코드의 블럭을 실행하여 에러를 처리합니다. 에러가 do
절에서 발생되면 catch
절과 비교하여 에러를 처리할 수 있는 항목을 결정합니다.do
-catch
구문의 일반적인 형태입니다:catch
뒤에 패턴을 작성합니다. catch
절이 패턴을 가지고 있지 않다면 이 절은 모든 에러와 일치하고 error
라는 이름을 가진 지역 상수로 에러를 바인드 합니다. 자세한 내용은 패턴 (Patterns) 을 참고 바랍니다.VendingMachineError
열거형에 3가지 모든 케이스에 대해 일치합니다.buyFavoriteSnack(person:vendingMachine:)
함수는 에러를 발생할 수 있으므로 try
표현식으로 호출됩니다. 에러가 발생하면 실행이 즉시 catch
절로 전송되어 전파가 계속 될 것인지 여부를 결정합니다. 패턴이 일치하지 않으면 에러는 마지막 catch
절에 의해 포착되고 지역 error
상수에 바인딩 됩니다. 에러가 발생하지 않으면 do
구문에 나머지 구문이 실행됩니다.catch
절은 do
절에서 발생할 수 있는 모든 에러를 처리할 필요는 없습니다. catch
절이 에러를 처리하지 않으면 에러는 주변에 전파합니다. 그러나 전파된 에러는 일부 주변 범위에서 처리되어야 합니다. 던지지 않는 함수에서는 do
-catch
구문은 에러를 처리해야 합니다. 던지는 함수에서는 do
-catch
구문이나 호출자가 에러를 처리해야 합니다. 에러가 처리되지 않고 범위의 최상위로 전파되면 런타임 에러를 발생합니다.VendingMachineError
가 아닌 모든 에러가 호출 함수에서 포착되도록 작성할 수 있습니다:nourish(with:)
함수에서 vend(itemNamed:)
가 VendingMachineError
열거형에 케이스 중 하나의 에러를 발생하면 nourish(with:)
는 메세지를 출력하여 에러를 처리합니다. 그렇지 않으면 nourish(with:)
는 호출 부분으로 에러를 전파합니다. 이 에러는 일반적인 catch
절에 의해 포착됩니다.catch
다음에 목록 형식으로 작성하는 것입니다. 예를 들어:eat(item:)
함수는 포착할 자동 판매기 에러를 나열하며 에러 텍스트는 해당 목록의 항목에 해당합니다. 목록화 된 3가지 에러 중 어떤 에러가 발생하면 이 catch
절은 메세지를 출력하여 처리합니다. 나중에 추가될 수 있는 에러를 포함하여 다른 에러는 주변 범위로 전파됩니다.try?
를 사용합니다. try?
표현식을 평가하는 동안 에러가 발생되면 이 표현식의 값은 nil
입니다. 예를 들어 아래 코드에서 x
와 y
는 같은 값을 가지고 동작합니다:shomeThrowingFunction()
이 에러를 발생하면 x
와 y
의 값은 nil
입니다. 그렇지 않으면 x
와 y
의 값은 반환된 함수 값입니다. x
와 y
는 someThrowingFunction()
이 반환하는 타입의 옵셔널 입니다. 여기서 함수는 정수를 반환하므로 x
와 y
는 옵셔널 옵셔널 정수입니다.try?
를 사용하면 모든 에러를 같은 방식으로 처리하려는 경우 간결한 에러 처리 코드를 작성할 수 있습니다. 예를 들어 아래의 코드는 여러 접근방식을 사용하여 데이터를 가져오거나 모든 접근방식이 실패하면 nil
을 반환합니다.try!
를 작성할 수 있고 에러를 발생하지 않는다고 호출을 래핑할 수 있습니다. 에러가 발생한다면 런타임 에러를 얻습니다.loadImage(atPath:)
함수를 사용합니다. 이러한 경우 이미지는 이미지는 애플리케이션과 함께 제공되고 런타임에 에러가 발생하지 않으므로 에러 전파를 비활성화 하는 것이 적절합니다.defer
구문을 사용하여 일련의 구문을 실행합니다. 이 구문을 사용하여 에러가 발생하여 종료되거나 return
또는 break
와 같은 구문에 의해 종료되는 방식에 상관없이 필요한 정리를 수행할 수 있습니다. 예를 들어 defer
구문을 사용하여 파일 설명자가 닫히고 수동으로 할당된 메모리가 해제되도록 할 수 있습니다.defer
구문은 현재 범위가 종료될 때까지 실행을 연기합니다. 이 구문은 defer
키워드와 나중에 실행될 구문으로 구성되어 있습니다. 지연된 구문은 break
또는 return
구문과 같이 구문의 밖으로 제어를 이동하거나 에러를 발생시키는 코드를 포함할 수 없습니다. 지연된 동작은 소스 코드에 작성된 순서와 반대로 실행됩니다. 즉 첫번째 defer
구문의 코드는 마지막에 실행되고 두번째 defer
구문의 코드는 마지막에서 두번째로 실행되는 식입니다. 소스 코드의 마지막 defer
구문은 마지막에 실행합니다.open(_:)
함수에 close(_:)
에 대한 호출이 있는지 확인하기 위해 defer
구문을 사용합니다.NOTE 에러 처리 코드가 포함되지 않았을 때도defer
구문을 사용할 수 있습니다.