Swift-Language 오류 처리
스위프트에 대해 많이 읽지는 않았지만 한 가지 깨달은 점은 예외는 없다는 것이다.그럼 Swift에서는 에러 처리를 어떻게 하고 있을까요?에러 처리와 관련된 것을 발견한 사람이 있습니까?
Swift 2 & 3
Swift 2에서는 예외와 다소 비슷하지만 세부적으로 다른 새로운 오류 처리 메커니즘이 있기 때문에 상황이 조금 바뀌었습니다.
1. 오류 가능성 표시
function이 있는 , 「/」를 할 필요가 .throws
과 같은
func summonDefaultDragon() throws -> Dragon
참고: 함수가 실제로 발생시킬 수 있는 오류 유형에 대한 사양은 없습니다.이 선언은 단순히 함수가 ErrorType을 구현하는 모든 유형의 인스턴스를 슬로우할 수 있거나 전혀 슬로우하지 않음을 나타냅니다.
(2) 에러를 발생시킬 가능성이 있는 함수를 기동한다.
함수를 호출하려면 다음과 같이 try 키워드를 사용해야 합니다.
try summonDefaultDragon()
이 라인은 보통 다음과 같은 do-contract 블록이 있어야 합니다.
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
★★★★★★★★★★★★★★★★★★:
func fulfill(quest: Quest) throws {
let dragon = try summonDefaultDragon()
quest.ride(dragon)
}
던지기 .try?
:
let dragonOrNil = try? summonDefaultDragon()
이렇게 하면 오류가 발생한 경우 반환값 또는 0을 얻을 수 있습니다.이 방법을 사용하면 오류 개체를 얻을 수 없습니다.
, which은, which which which which 、 which을 、 을 which 、 which which 、 which which 、 which which 、 which which which 。try?
다음과 같은 유용한 문장이 포함되어 있습니다.
if let dragon = try? summonDefaultDragon()
또는
guard let dragon = try? summonDefaultDragon() else { ... }
가 발생하지 않는 하고 있기 에), 「」, 「」, 「」를 사용할 수 .try!
★★★★★★★★★★★★★★★★★★:
let dragon = try! summonDefaultDragon()
함수가 실제로 오류를 발생시키면 응용 프로그램에서 런타임 오류가 발생하고 응용 프로그램이 종료됩니다.
3. 에러 던지기
에러를 던지려면 , 다음과 같이 throw 키워드를 사용합니다.
throw DragonError.dragonIsMissing
수 , 던질 수 있다, 던질 수 있다, 던질 수 , 던질 수 있다, 던질 수 , 던질 수 있다, 던질 수 있다, 던질 수 있다, 던질 수 있다.ErrorType
프로토콜입니다. ★★★★★★NSError
는 이 만, 의 enum-based를 하는 것이 .ErrorType
할 수 오류는 추가 할 수 있습니다.
enum DragonError: ErrorType {
case dragonIsMissing
case notEnoughMana(requiredMana: Int)
...
}
새로운 Swift 2 & 3 오류 메커니즘과 Java/C#/C++ 스타일의 예외의 주요 차이점은 다음과 같습니다.
- 요.
do-catch
+try
+defer
기존 vs 래래try-catch-finally
구문을 사용합니다. - 예외 처리는 보통 성공 경로보다 예외 경로에서 훨씬 더 많은 실행 시간을 발생시킵니다.이는 성공 경로와 오류 경로 비용이 거의 동일한 Swift 2.0 오류의 경우에는 해당되지 않습니다.
- 모든 오류 발생 코드를 선언해야 하며, 예외는 어디에서나 발생할 수 있습니다.Java 명명법에서는 모든 오류가 "체크된 예외"입니다.그러나 Java와 달리 잠재적인 오류 발생은 지정하지 않습니다.
- Swift ObjC입니다.의 ★★★★★★★★★★★★★★★★★.
do-catch
NSException을 차단합니다.ObjC를 사용하다 - 는 코코아와 된다.
NSError
방법false
)Bool
반환함수)nil
)AnyObject
및 통과함수)를 합니다.NSErrorPointer
에러의 상세를 표시합니다.
오류 처리를 완화하기 위한 추가 구문설탕으로 두 가지 개념이 더 있습니다.
- 액션를 사용)
defer
키워드C#/)의 수 . - 스테이트먼트 사용)
guard
키워드)를 사용하면 일반적인 에러 체크/오류 코드보다 if/오류 코드를 적게 쓸 수 있습니다.
스위프트 1
런타임 오류:
접속 , 등하는 바와 같이 Leandros를 사용해야 .NSError
ObjC 서, 、 AppKit 、 UIKit 、 ObjC 서,ationation 。언어보다는 틀에 더 가깝습니다.
자주 사용되는 또 다른 패턴은 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
, error.discription, error.discription.discription
프로그래머 오류:
프로그래머 오류(어레이 요소의 경계 밖의 액세스, 함수 호출에 전달된 잘못된 인수 등)에 대해서는 ObjC에서 예외를 사용했습니다.빠른 언어는 예외에 대한 어떠한 언어도 지원하지 않는 것 같습니다(예:throw
,catch
키워드 등).단,한 런타임으로 되고 있기 에 ObjC는 수 .NSExceptions
음음음같 뭇매하다
NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()
ObjC 코드에서 예외를 포착하는 것을 선택할 수도 있지만 순수 스위프트에서는 잡을 수 없습니다.
문제는 프로그래머 오류에 대한 예외를 둘 것인지, 아니면 애플이 언어 가이드에 제시한 주장을 사용할 것인지 여부입니다.
2015년 6월 9일 업데이트 - 매우 중요
2에는 Swift 2.0이 .try
,throw
, , , , 입니다.catch
로운 것은 '키워드'입니다.
Swift는 Swift의 기본 오류 처리 기능에 따라 오류를 발생시키는 Objective-C 메서드를 자동으로 변환합니다.
주의: 위임 메서드나 NSError object 인수를 사용하여 완료 핸들러를 사용하는 메서드 등 오류를 소비하는 메서드는 Swift에서 가져올 때 던지는 메서드가 되지 않습니다.
출처: Apple Inc.에서 발췌."Swift with Cocoa and Objective-C (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);
}
swift의 등가물은 다음과 같습니다.
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)
애플 서적에서 Swift Programming Language 오류는 열거형을 사용하여 처리해야 할 것 같습니다.
여기 책의 예가 있다.
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.'스위트 프로그래밍 언어' 아이북스https://itun.es/br/jEUH0.l
갱신하다
애플 뉴스북에서 "Using Swift with Cocoa and Objective-C"를 인용했습니다.실행 시 예외는 swift 언어를 사용하여 발생하지 않으므로 try-catch가 없습니다.대신 옵션 체인을 사용합니다.
다음은 책의 한 줄입니다.
예를 들어, 아래 코드 목록에서는 길이 속성과 characterAt 때문에 첫 번째 줄과 두 번째 줄이 실행되지 않습니다.인덱스: NSDate 개체에 메서드가 없습니다.myLength 상수는 옵션 Int로 추정되며 0으로 설정됩니다.또한 if-let 문을 사용하여 세 번째 줄에 나타나듯이 오브젝트가 응답하지 않을 수 있는 메서드의 결과를 조건부로 전개할 수도 있습니다.
let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)
if let fifthCharacter = myObject.characterAtIndex(5) {
println("Found \(fifthCharacter) at index 5")
}
출처: Apple Inc.에서 발췌."Swift with Cocoa and Objective-C" 아이북스https://itun.es/br/1u3-0.l
또한 Objective-C(NSError Object)의 코코아 오류 패턴을 사용할 것을 권장합니다.
Swift의 오류 보고는 Objective-C와 동일한 패턴을 따르며 옵션인 반환값을 제공하는 이점이 있습니다.가장 간단한 경우 함수의 Bool 값을 반환하여 성공 여부를 나타냅니다.오류 이유를 보고해야 하는 경우 NSErrorPointer 유형의 NSError out 매개 변수를 함수에 추가할 수 있습니다.이 타입은 Objective-C의 NSError **와 거의 동등하며 메모리 안전성 향상과 옵션 입력이 가능합니다.프리픽스와 연산자를 사용하면 NSError Pointer 오브젝트로서 옵션의 NSError 타입에 대한 참조를 전달할 수 있습니다(아래 코드 리스트 참조).
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.에서 발췌."Swift with Cocoa and Objective-C" 아이북스https://itun.es/br/1u3-0.l
Objective-C의 접근법과 유사한 Swift에는 예외가 없습니다.
use in in 、 음 、 음 、 음 、 음 、 음 、 음 、 in in in in in in in in 。assert
발생할 수 있는 오류를 파악하여 프로덕션으로 이동하기 전에 수정해야 합니다.
인 래식 theNSError
합니다.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)")
}
권장되는 '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를 하는 것이 편리하기 때문에 이 배열을 "Golden Path"라고 부르기도 합니다.폐쇄를 통해 이 작업을 수행할 수 있는 것은 행운입니다.
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 returned 값을 테스트하기 위해 유사한 클래스를 작성할 수 있습니다.
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
}
자동 포장을 해제합니다.
편집:이 답변은 효과가 있지만 Swift로 번역된 Objective-C에 불과합니다.Swift 2.0의 변경으로 인해 더 이상 사용되지 않게 되었습니다.위의 Gilherme 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...
}
Try catch 기능을 제공하는 오브젝트 C 주위의 기본 래퍼.https://github.com/williamFalcon/SwiftTryCatch
사용방법:
SwiftTryCatch.try({ () -> Void in
//try something
}, catch: { (error) -> Void in
//handle error
}, finally: { () -> Void in
//close resources
})
말한 2.에서는 렘 as as as as as 0try
,catch
,do
프로그래밍에 사용할 수 있습니다.
를 들어,메서드는 "Put " 대신 " CoreData"를 합니다.&error
로서 「」를 합니다.managedContext.executeFetchRequest(fetchRequest, error: &error)
사용법만 .managedContext.executeFetchRequest(fetchRequest)
다음 를 에러로 처리해 .try
,catch
(Apple 문서 링크)
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as? [NSManagedObject]
if let results = fetchedResults{
people = results
}
} catch {
print("Could not fetch")
}
xcode7 베타 버전을 이미 다운로드한 경우.Documentations 및 API Reference에서 전송 오류를 검색하여 첫 번째 표시 결과를 선택하면 이 새로운 구문에 대해 수행할 수 있는 기본적인 아이디어를 얻을 수 있습니다.그러나 많은 API에 대해서는 아직 완전한 문서가 게시되지 않았습니다.
보다 화려한 오류 처리 기호에 기재되어 있습니다.
스위프트의 신기능 (2015년 세션 106 28m30s)
swift 2.0에 대한 업데이트 답변입니다.자바와 같은 풍부한 기능의 에러 처리 모델을 기대하고 있습니다.마침내, 그들은 좋은 소식을 발표했다.여기
오류 처리 모델:Swift 2.0의 새로운 오류 처리 모델은 익숙한 try, throw, catch 키워드를 사용하여 즉시 자연스러운 느낌을 줍니다.무엇보다도 Apple SDK 및 NSError와 완벽하게 작동하도록 설계되었습니다.실제로 NSError는 Swift의 ErrorType을 준수합니다.자세한 내용은 WWDC 세션인 What's New in Swift에서 확인하시기 바랍니다.
예:
func loadData() throws { }
func test() {
do {
try loadData()
} catch {
print(error)
}}
Swift 2부터는 이미 언급한 바와 같이 do/try/catch 및 ErrorType enum을 사용하여 오류 처리를 가장 잘 수행할 수 있습니다.이 방법은 동기 방식에서는 잘 작동하지만 비동기 오류 처리에는 약간의 지능이 필요합니다.
이 문서는 이 문제에 대한 훌륭한 접근방식을 제공합니다.
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보다 전의 처리 방식입니다.
Swift 2.0입니다., 이렇게 요.try
,throw
★★★★★★★★★★★★★★★★★」catch
키워드를 지정합니다.
Apple Swift 공식 블로그에서 Apple Swift 2.0 발표를 참조하십시오.
예외 처리를 위한 심플한 lib:TryCatch Finally-Swift
다른 몇 가지와 마찬가지로 목적 C 예외 기능을 둘러쌉니다.
다음과 같이 사용합니다.
try {
println(" try")
}.catch { e in
println(" catch")
}.finally {
println(" finally")
}
enum CheckValidAge : Error{
case overrage
case underage
}
func checkValidAgeForGovernmentJob(age:Int)throws -> Bool{
if age < 18{
throw CheckValidAge.underage
}else if age > 25{
throw CheckValidAge.overrage
}else{
return true
}
}
do {
try checkValidAgeForGovernmentJob(age: 26)
print("You are valid for government job ")
}catch CheckValidAge.underage{
print("You are underage for government job ")
}catch CheckValidAge.overrage{
print("You are overrage for government job ")
}
Check 실행 시 경과시간 변경ValidAgeForGovernmentJob(나이: 26)
Out Put 정부 업무의 우선 순위
디바이스의 특성상 사용자에게 많은 오류 처리 메시지를 전달하고 싶지 않다는 것을 알게 되었습니다.그렇기 때문에 대부분의 함수는 옵션 값을 반환하고, 사용자는 이 옵션을 무시하도록 코드화하기만 하면 됩니다.함수가 실패했음을 의미하는 영이 반환될 경우 메시지를 팝업할 수 있습니다.
언급URL : https://stackoverflow.com/questions/24010569/error-handling-in-swift-language
'programing' 카테고리의 다른 글
XAML만 사용하고 코드 배후는 사용하지 않고 ListBox를 정렬하려면 어떻게 해야 합니까? (0) | 2023.04.17 |
---|---|
Git 브랜치에서 다른 브랜치로 단일 파일 버전을 복사하려면 어떻게 해야 합니까? (0) | 2023.04.17 |
BIT 필드에 대한 MIN 집약 함수 적용 (0) | 2023.04.17 |
문자열이 C++에서 다른 문자열로 끝나는지 확인합니다. (0) | 2023.04.17 |
C++의 "X does not name a type" 오류 (0) | 2023.04.17 |