2016-08-27 20 views
72

Swift 3 sözdizimi ile özel bir hata türünü tanımlıyorum ve Error nesnesinin localizedDescription özelliğiyle döndürülen hatanın kullanıcı dostu bir açıklamasını sağlamak istiyorum. Nasıl yapabilirim?Swift'de bir Hata türü ile yerelleştirilmiş bir açıklama nasıl sağlanır?

public enum MyError: Error { 
    case customError 

    var localizedDescription: String { 
    switch self { 
    case .customError: 
     return NSLocalizedString("A user-friendly description of the error.", comment: "My error") 
    } 
    } 
} 

let error: Error = MyError.customError 
error.localizedDescription 
// "The operation couldn’t be completed. (MyError error 0.)" 

benim özel hata açıklamasını geri dönmek localizedDescription için bir yol var mı ("hatanın bir kullanıcı dostu bir açıklama.")? Buradaki hata nesnesinin Error türünde ve MyError değil olduğunu unutmayın. Ben, tabii, MyError

(error as? MyError)?.localizedDescription 

nesneyi yayınlayabilirsiniz ama benim hata türüne çevrim olmadan çalışmasını sağlamak için bir yol var?

Xcode 8 beta 6 sürüm notları olarak tarif edildiği gibi

cevap

161

,

hata tipleri yeni LocalizedError protokolü benimseyerek lokalize hata açıklamaları sağlayabilir Swift tanımlı. Senin durumunda

:

public enum MyError: Error { 
    case customError 
} 

extension MyError: LocalizedError { 
    public var errorDescription: String? { 
     switch self { 
     case .customError: 
      return NSLocalizedString("A user-friendly description of the error.", comment: "My error") 
     } 
    } 
} 

let error: Error = MyError.customError 
print(error.localizedDescription) // A user-friendly description of the error. 

hata NSError için dönüştürülür eğer (her zaman mümkün olan) daha bilgi verebilir:

extension MyError : LocalizedError { 
    public var errorDescription: String? { 
     switch self { 
     case .customError: 
      return NSLocalizedString("I failed.", comment: "") 
     } 
    } 
    public var failureReason: String? { 
     switch self { 
     case .customError: 
      return NSLocalizedString("I don't know why.", comment: "") 
     } 
    } 
    public var recoverySuggestion: String? { 
     switch self { 
     case .customError: 
      return NSLocalizedString("Switch it off and on again.", comment: "") 
     } 
    } 
} 

let error = MyError.customError as NSError 
print(error.localizedDescription)  // I failed. 
print(error.localizedFailureReason)  // Optional("I don\'t know why.") 
print(error.localizedRecoverySuggestion) // Optional("Switch it off and on again.") 

CustomNSError protokolünü benimseyerek hata, userInfo sözlüğüne sözlüğü sağlayabilir (ayrıca bir domain ve).). Örnek:

extension MyError: CustomNSError { 

    public static var errorDomain: String { 
     return "myDomain" 
    } 

    public var errorCode: Int { 
     switch self { 
     case .customError: 
      return 999 
     } 
    } 

    public var errorUserInfo: [String : Any] { 
     switch self { 
     case .customError: 
      return [ "line": 13] 
     } 
    } 
} 

let error = MyError.customError as NSError 

if let line = error.userInfo["line"] as? Int { 
    print("Error in line", line) // Error in line 13 
} 

print(error.code) // 999 
print(error.domain) // myDomain 
+4

Eğer 'Bir' Error' birinci ve sonradan LocalizedError' 'ile bunu genişletmek MyError' yapmak bir sebebi var mı? İlk etapta bir "LocalizedError" yaptıysanız bir fark var mı? –

+5

@ Gee.E: Fark etmez. Kodu düzenlemenin bir yolu (her protokol için bir uzantı). Http: // stackoverflow öğesini karşılaştırın.com/questions/36263892/extensions-in-kendi-özel-sınıf, http://stackoverflow.com/questions/40502086/how-to-properly-use-class-extensions-in-swift veya https://www.natashatherobot.com/using-swift-extensions/. –

+2

Ah, kontrol edin. Şimdi söylediklerinizi alıyorum. Https://www.natashatherobot.com/using-swift-extensions/ adresindeki "Protokol Uygunluğu" bölümü gerçekten ne demek istediğinizin iyi bir örneğidir. Teşekkürler! –

9

Hata bu

enum NetworkError: Error { 
    case responseStatusError(status: Int, message: String) 
} 

gibi parametreleri böyle yerelleştirilmiş açıklamasında bu parametreleri çağırabilir varsa ben de eklersiniz:

extension NetworkError: LocalizedError { 
    var localizedDescription: String { 
    switch self { 
    case .responseStatusError(status: let status, message: let message): 
     return "Error with status \(status) and message \(message) was thrown" 
    } 
} 

Hatta can Bunu aşağıdaki gibi kısaltın:

extension NetworkError: LocalizedError { 
    var localizedDescription: String { 
    switch self { 
    case let .responseStatusError(status, message): 
     return "Error with status \(status) and message \(message) was thrown" 
    } 
} 
+0

Aslında, LocalizedError, ilk kod snip'inizde uygulamak için gereksiz olduğundan, Hata uygular. Ayrıca, yerelleştirilmişDescription geçersiz kılınması gereken doğru hesaplanan özellik hata olarak bildiriliyorDescription – OhadM

1

Artık, Objective-C - LocalizedError ve CustomNSError öğelerine ek bilgi sağlamak için hata türünüzün benimseyebileceği iki Hata kabul eden protokol vardır. İşte bunlardan ikisi benimseyen bir örnek hata var:

enum MyBetterError : CustomNSError, LocalizedError { 
    case oops 

    // domain 
    static var errorDomain : String { return "MyDomain" } 
    // code 
    var errorCode : Int { return -666 } 
    // userInfo 
    var errorUserInfo: [String : Any] { return ["Hey":"Ho"] }; 

    // localizedDescription 
    var errorDescription: String? { return "This sucks" } 
    // localizedFailureReason 
    var failureReason: String? { return "Because it sucks" } 
    // localizedRecoverySuggestion 
    var recoverySuggestion: String? { return "Give up" } 

} 
-1

İşte daha zarif bir çözümdür: alternatif olabilecek bir yapı kullanma

enum ApiError: String, LocalizedError { 

    case invalidCredentials = "Invalid credentials" 
    case noConnection = "No connection" 

    var localizedDescription: String { return NSLocalizedString(self.rawValue, comment: "") } 

    } 
+0

Bu çalışma zamanında daha zarif olabilir, ancak statik yerelleştirme adımı bu dizeleri çevirmenler için ayıklayamaz; Dosyada hatalı bir giriş göreceksiniz - argüman, "exportLocalizations" veya "genstrings" komutunu çalıştırdığınızda, dönüştürülebilir metinler listenizi oluşturmak için bir hata dizgesidir. – savinola

+0

@savinola katılıyorum, bu durumda statik yerelleştirme çalışmaz. Belki de 'switch + case' kullanmak sadece seçenek ... –

0

. Statik lokalizasyonu ile Biraz şıklık:

import Foundation 

struct MyError: LocalizedError, Equatable { 

    private var description: String! 

    init(description: String) { 
     self.description = description 
    } 

    var errorDescription: String? { 
     return description 
    } 

    public static func ==(lhs: MyError, rhs: MyError) -> Bool { 
     return lhs.description == rhs.description 
    } 
} 

extension MyError { 

    static let noConnection = MyError(description: NSLocalizedString("No internet connection",comment: "")) 
    static let requestFailed = MyError(description: NSLocalizedString("Request failed",comment: "")) 
} 

func throwNoConnectionError() throws { 
    throw MyError.noConnection 
} 

do { 
    try throwNoConnectionError() 
} 
catch let myError as MyError { 
    switch myError { 
    case .noConnection: 
     print("noConnection: \(myError.localizedDescription)") 
    case .requestFailed: 
     print("requestFailed: \(myError.localizedDescription)") 
    default: 
     print("default: \(myError.localizedDescription)") 
    } 
} 
İlgili konular