欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Swift?Error重構(gòu)的基礎(chǔ)示例詳解

 更新時(shí)間:2022年11月30日 09:29:06   作者:移動端小伙伴  
這篇文章主要為大家介紹了Swift?Error基礎(chǔ)錯(cuò)誤處理的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Error

在開發(fā)中,往往最容易被忽略的內(nèi)容就是對錯(cuò)誤的處理。有經(jīng)驗(yàn)的開發(fā)者,能夠?qū)ψ约簩懙拿啃写a負(fù)責(zé),而且非常清楚自己寫的代碼在什么時(shí)候會出現(xiàn)異常,這樣就能提前做好錯(cuò)誤處理。

定義

Swift 里面的Error是一個(gè)協(xié)議

public protocol Error : Sendable { }

Sendable: 可以安全地將可發(fā)送類型的值從一個(gè)并發(fā)域傳遞到另一個(gè)——例如,您可以在調(diào)用參與者的方法時(shí)將可發(fā)送值作為參數(shù)傳遞

概述

Any type that declares conformance to the Error protocol can be used to represent an error in Swift’s error handling system. Because the Error protocol has no requirements of its own, you can declare conformance on any custom type you create.

在Swift的錯(cuò)誤處理系統(tǒng)中,任何聲明符合Error協(xié)議的類型都可以用來表示錯(cuò)誤。因?yàn)镋rror協(xié)議沒有它自己的要求,所以您可以對您創(chuàng)建的任何自定義類型聲明一致性。

用枚舉來表示簡單的錯(cuò)誤

Swift 的枚舉非常適合表示簡單的錯(cuò)誤。創(chuàng)建一個(gè)符合Error協(xié)議的枚舉,并為每個(gè)可能的錯(cuò)誤提供一個(gè)case。如果需要有關(guān)錯(cuò)誤的其他詳細(xì)信息,可以使用關(guān)聯(lián)值來包含該信息。

/// 聲明一個(gè)Int解析的Error
enum IntParsingError: Error {
  /// 超過長度
  case overflow
  /// 無法解析的字符
  case invalidInput(String)
  /// 其他錯(cuò)誤類型
  case other
}
extension Int {
  init(validating input: String) throws {
      for item in input {
          guard let _ = item.toInt() else {
              throw IntParsingError.invalidInput(String(item))
          }
      }
      if let int = input.toInt() {
          self = int
      } else {
          throw IntParsingError.other
      }
  }
}
extension Character {
  func toInt() -> Int? {
      let str = String(self)
      if let int = Int(str) {
          return int
      }
      return nil
  }
}
extension String {
  public func toInt() -> Int? {
      if let num = NumberFormatter().number(from: self) {
          return num.intValue
      } else {
          return nil
      }
  }
}
let money: String = "100塊錢"
let a = try? Int(validating: money)

此時(shí)的 a 是一個(gè)Int?類型, 初始化失敗就返回nil.

do {
  let price = try Int(validating: money)
  print(price)
} catch IntParsingError.invalidInput(let invalid) {
  print("Invalid character: '(invalid)'")
} catch IntParsingError.overflow {
  print("Overflow error")
} catch {
  print("Other error")
}

此時(shí)的price是一個(gè)Int類型, 如果轉(zhuǎn)換失敗,就會拋出異常。

用結(jié)構(gòu)體或其他類型表示復(fù)雜的錯(cuò)誤

以下示例在解析時(shí),使用結(jié)構(gòu)來表示錯(cuò)誤,包括發(fā)生錯(cuò)誤的文件,方法和行號:

struct ParseError: Error {
  enum errorKind {
      case pathError
      case InvalidFormat
      case other
  }
  let file: String
  let method: String
  let line: Int
  let type: errorKind
}
func parse(_ source: String) throws -> Int {
  throw ParseError.init(
      file: "Users/Mccc/Log/Vip.swift",
      method: "LogMethod",
      line: 12,
      type: .InvalidFormat)
}

使用模式匹配來有條件地捕獲錯(cuò)誤。以下是如何捕獲函數(shù)拋出的任何錯(cuò)誤:

do {
  let info = try parse("123")
  print(info)
} catch let e as ParseError {
  print("Parsing error: (e.type) [(e.file) : (e.method) : (e.line)]")
} catch {
  print("Other error: (error)")
}

處理Error的三種方式

  • 通過 try?忽略Error
  • 通過 do - catch 捕捉 Error
  • 不捕捉 Error,在當(dāng)前函數(shù)增加 throws 聲明,Error 將自動拋給上層函數(shù)。如果最頂層函數(shù)(main 函數(shù))依然沒有捕捉 Error,那么程序?qū)⒔K止

相關(guān)的一些關(guān)鍵詞

rethrows & throws

throws關(guān)鍵字首先用在函數(shù)申明中,放在返回類型的前面,比如標(biāo)準(zhǔn)庫中map的函數(shù)簽名。

@frozen public struct Array<Element> {
  @inlinable public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
}

然后在函數(shù)內(nèi)部,如果出現(xiàn)可能的異常,就可以拋出異常。

enum NegativeError: Error {
  /// 負(fù)數(shù)
  case negative
}
let nums = [1, 2, 3, 4, -5]
do {
  let strNums = try nums.map { (num) throws -> String in
      if num >= 0 {
          return String(num)
      } else {
          throw NegativeError.negative
      }
  }
  print(strNums) // Will no print
} catch let err {
  print(err)
}
  • throws::在函數(shù)或者方法中拋出異常,讓調(diào)用者必須明確地處理可能的異常.
  • rethrows::本身并不拋出異?;蛘咛幚懋惓?,其只起到傳遞異常的作用.
func methodThrows(num: Int) throws {
  if num < 0 {
      print("Throwing!")
      throw error
  }
  print("Executed!")
}
func methodRethrows(num: Int, f: (Int) throws -> ()) rethrows {
  try f(num)
}
do {
  try methodRethrows(num: 1, f: methodThrows)
} catch _ {
}

簡單理解的話你可以將 rethrows 看做是 throws 的“子類”,rethrows 的方法可以用來重載那些被標(biāo)為 throws 的方法或者參數(shù),或者用來滿足被標(biāo)為 throws 的接口,但是反過來不行。

try / try!/ try? / defer

  • try: 和可選類型相似,編譯器強(qiáng)制我們在使用可能跑出錯(cuò)誤的房時(shí)使用try關(guān)鍵字。需要和 do {} cathc {} 結(jié)合使用。
  • try?。?類似于可選型中的強(qiáng)制解包,同樣不會對錯(cuò)誤進(jìn)行處理,但是一旦方法拋出錯(cuò)誤,就會造成程序的崩潰
  • try?:有點(diǎn)類似于可選型中的可選鏈,如果方法正確,則完整執(zhí)行;如果跑出錯(cuò)誤,則方法提前結(jié)束,但不會拋出錯(cuò)誤進(jìn)行處理。
  • defer:將必須執(zhí)行的邏輯放在defer{}中,可以保證無論方法從哪個(gè)出口結(jié)束,defer{}中的代碼都會執(zhí)行,通常會將 defer{ } 放在方法體的最上方,defer代碼段總是在方法生命周期的最后才執(zhí)行

fatalError

無條件地打印給定的消息并停止執(zhí)行。

fatalError("something wrong")

fatalError的存在意義是:

在調(diào)試時(shí)我們可以使用斷言來排除類似這樣的問題,但是斷言只會在 Debug 環(huán)境中有效,而在 Release 編譯中所有的斷言都將被禁用。在遇到確實(shí)因?yàn)檩斎氲腻e(cuò)誤無法使程序繼續(xù)運(yùn)行的時(shí)候,我們一般考慮以產(chǎn)生致命錯(cuò)誤 fatalError 的方式來終止程序。

  • 父類中的某些方法,不想讓別人調(diào)用,可以在方法中加上fatalError,這樣子類如果想到用必須重寫
  • 對于其他一切我們不希望別人隨意調(diào)用,但是又不得不去實(shí)現(xiàn)的方法,我們都應(yīng)該使用 fatalError 來避免任何可能的誤會。

Error相關(guān)的協(xié)議

聲明一個(gè)汽車的結(jié)構(gòu)體:

struct Car { }

定義一個(gè)汽車不能行駛的錯(cuò)誤。

extension Car {
  enum TroubleError: Error {
      /// 癱瘓:車輛無法行駛
      case paralysis
      /// 油量不足
      case lackOilWarning
      /// 超員:減員之后可以繼續(xù)行駛。
      case overcrowding(Int)
  }
}

LocalizedError

描述一個(gè)錯(cuò)誤,該錯(cuò)誤提供描述錯(cuò)誤發(fā)生原因的本地化消息,并提供有關(guān)該錯(cuò)誤的更多信息。

public protocol LocalizedError : Error {
  /// 提供描述錯(cuò)誤的本地化消息
  var errorDescription: String? { get }
  /// 發(fā)生錯(cuò)誤的原因
  var failureReason: String? { get }
  /// 如何恢復(fù)的提示
  var recoverySuggestion: String? { get }
  /// 其他幫助文本
  var helpAnchor: String? { get }
}
extension Car.TroubleError: LocalizedError {
  /// 提供描述錯(cuò)誤的本地化消息
  var errorDescription: String? {
      switch self {
      case .paralysis:
          return NSLocalizedString("汽車已經(jīng)癱瘓,無法行駛", comment: "呼叫拖車維修")
      case .lackOilWarning:
          return NSLocalizedString("油量不足", comment: "清前往加油")
      case .overcrowding(let count):
          return NSLocalizedString("乘客超載,超載人數(shù):(count)", comment: "超員部分乘客下車")
      }
  }
  /// 發(fā)生錯(cuò)誤的原因
  var failureReason: String? {
      switch self {
      case .paralysis:
          return "汽車已經(jīng)癱瘓,無法行駛"
      case .lackOilWarning:
          return "油量不足"
      case .overcrowding(let count):
          return "乘客超載,超載人數(shù):(count)"
      }
  }
  /// 如何恢復(fù)的提示
  var recoverySuggestion: String? {
      switch self {
      case .paralysis:
          return "尋找緊急修車方法"
      case .lackOilWarning:
          return "去加油站加油"
      case .overcrowding(let count):
          return "把超載的人數(shù)(count)人趕下車"
      }
  }
  /// 其他幫助文本
  var helpAnchor: String? {
      switch self {
      case .paralysis:
          return "緊急修車電話:0632-2347232"
      case .lackOilWarning:
          return "地圖搜索加油站"
      case .overcrowding(_):
          return "禁止超載"
      }
  }
}

CustomNSError

Error ? NSError

// 初始化一個(gè)NSError
let errorOC = NSError.init(domain: "intsig.qxb", code: 1000, userInfo: nil)
// 轉(zhuǎn)換為Error
let swiftError = errorOC as Error
print(swiftError)
print(swiftError.localizedDescription)
// 轉(zhuǎn)換為NSError
let error = swiftError as NSError

一直認(rèn)為 NSError ? Error ? NSError 可以無障礙轉(zhuǎn)換的。自從收到這個(gè)crash:

0 libswiftCore.dylib __swift_stdlib_bridgeErrorToNSError + 40
1 projectName loadDataDidFailed (文件名.swift:69)
...
...

在各個(gè)渠道也沒找到具體原因。 只是建議使用CustomNSError來處理。 如有知道具體原因的同學(xué),可以評論回復(fù)一下。

描述特定提供域、代碼和用戶信息字典的錯(cuò)誤類型。

public protocol CustomNSError : Error {
  /// The domain of the error.
  static var errorDomain: String { get }
  /// The error code within the given domain.
  var errorCode: Int { get }
  /// The user-info dictionary.
  var errorUserInfo: [String : Any] { get }
}
extension Car.TroubleError: CustomNSError {
  static var errorDomain: String {
      return "Domain"
  }
  var errorCode: Int {
      switch self {
      case .paralysis:
          return 1000
      case .lackOilWarning:
          return 1001
      case .overcrowding(_):
          return 1002
      }
  }
  var errorUserInfo: [String : Any] {
      return [:]
  }
}

轉(zhuǎn)成NSError

extension Car.TroubleError {
  func toNSError() -> NSError {
      NSError.init(domain: Car.TroubleError.errorDomain, code: errorCode, userInfo: errorUserInfo)
  }
}

RecoverableError

可以通過向用戶提供幾個(gè)潛在恢復(fù)選項(xiàng)來恢復(fù)的錯(cuò)誤。這主要在使用 AppKit 的 macOS應(yīng)用 中使用.

extension Car.TroubleError: RecoverableError {
  /// 在用戶請求時(shí)執(zhí)行恢復(fù)來恢復(fù)的錯(cuò)誤。這主要在使用 AppKit 的 macOS應(yīng)用 中使用.
  func attemptRecovery(optionIndex recoveryOptionIndex: Int) -> Bool {
      if recoveryOptionIndex == 0 { // 呼叫緊急車輛救援
          return false
      } else if recoveryOptionIndex == 1 { // 前往加油站加油
          return true
      } else if recoveryOptionIndex == 2 { // 處理超載情況
          return true
      }
      fatalError("something wrong")
  }
  /// 提供提供給用戶的一組可能的恢復(fù)選項(xiàng)
  var recoveryOptions: [String] {
      return ["呼叫緊急車輛救援", "前往加油站加油", "處理超載情況"]
  }
}

KingfisherError

Kingfisher的錯(cuò)誤封裝很經(jīng)典,是使用swift中enum的一個(gè)典型案例。讀完這篇文章,一定能讓大家對swift的枚舉和Error的使用有一個(gè)更深的理解,同時(shí)增加一些枚舉的高級使用技巧。

英文原義:

Represents all the errors which can happen in Kingfisher framework. Kingfisher related methods always throw a KingfisherError or invoke the callback with KingfisherError as its error type. To handle errors from Kingfisher, you switch over the error to get a reason catalog, then switch over the reason to know error detail.

中文翻譯:

KingfisherError 表示在 Kingfisher框架中可能發(fā)生的所有錯(cuò)誤。與 Kingfisher 相關(guān)的方法總是拋出一個(gè) KingfisherError 或者以 KingfisherError 作為錯(cuò)誤類型調(diào)用回調(diào)。要處理來自 Kingfisher 的錯(cuò)誤,需要 switch 錯(cuò)誤以獲取原因目錄,然后 switch 原因了解錯(cuò)誤細(xì)節(jié)。

public enum KingfisherError: Error {
  // 表示網(wǎng)絡(luò)請求階段的錯(cuò)誤原因
  case requestError(reason: RequestErrorReason)
  // 表示網(wǎng)絡(luò)響應(yīng)階段的錯(cuò)誤原因
  case responseError(reason: ResponseErrorReason)
  // 表示 Kingfisher 緩存系統(tǒng)中的錯(cuò)誤
  case cacheError(reason: CacheErrorReason)
  // 表示圖像處理階段的錯(cuò)誤原因
  case processorError(reason: ProcessorErrorReason)
  // 表示在視圖相關(guān)類中設(shè)置圖像時(shí)出現(xiàn)錯(cuò)誤的原因
  case imageSettingError(reason: ImageSettingErrorReason)
}

關(guān)聯(lián)值設(shè)計(jì)的五個(gè)枚舉 RequestErrorReason,ResponseErrorReason,CacheErrorReason,ProcessorErrorReason,ImageSettingErrorReason

他們是定義在 KingfisherError 中獨(dú)立的枚舉,他們之間是包含和被包含的關(guān)系,理解這一點(diǎn)很重要,因?yàn)橛辛诉@種包含的管理,在使用中就需要通過KingfisherError.RequestErrorReason這種方式進(jìn)行操作。

那么最重要的問題就是,如何把上邊5個(gè)獨(dú)立的枚舉進(jìn)行串聯(lián)呢?Kingfisher巧妙的地方就在這里,有5個(gè)獨(dú)立的枚舉,分別代表5大錯(cuò)誤類型。也就是說這個(gè)框架肯定有這5大錯(cuò)誤模塊,我們只需要給KingfisherError設(shè)計(jì)5個(gè)子選項(xiàng),每個(gè)子選項(xiàng)關(guān)聯(lián)上這5個(gè)獨(dú)立枚舉的值就ok了。

這個(gè)設(shè)計(jì)真的很巧妙,試想,如果把所有的錯(cuò)誤都放到KingfisherError中,就顯得非常冗余。大家好好體會體會在swift下這么設(shè)計(jì)的妙用。

RequestErrorReason

英文原義:

Represents the error reason during networking request phase.

emptyRequest: The request is empty. Code 1001.

invalidURL: The URL of request is invalid. Code 1002.

taskCancelled: The downloading task is cancelled by user. Code 1003.

中文翻譯:

表示網(wǎng)絡(luò)請求階段的錯(cuò)誤原因.

emptyRequest: 請求為空。代碼1001

invalidURL: 請求的URL無效。代碼1002

taskCancelled: 下載任務(wù)被用戶取消。代碼1003

public enum KingfisherError: Error {
  public enum RequestErrorReason {
      case emptyRequest
      case invalidURL(request: URLRequest)
      case taskCancelled(task: SessionDataTask, token: SessionDataTask.CancelToken)
  }
}

通過 RequestErrorReason 我們能夠很清楚的看出來這是一個(gè)請求錯(cuò)誤的原因。大家注意reason這個(gè)詞,在命名中,有或者沒有這個(gè)詞,表達(dá)的意境完全不同,因此,Kingfisher 的厲害就體現(xiàn)在這些細(xì)節(jié)之中。

RequestErrorReason 本身是一個(gè)枚舉,同時(shí)它又被包含在 KingfisherError 中,這說明枚舉之中可以有另一個(gè)枚舉 。那么像這種情況我們怎么使用呢?看下邊的代碼:

let reason = KingfisherError.RequestErrorReason.emptyRequest

枚舉的訪問是一級一級進(jìn)行的。我們再看這行代碼:case invalidURL(request: URLRequest)

并不是函數(shù),它是枚舉的一個(gè)普通的子選項(xiàng)。(request: URLRequest)是它的一個(gè)關(guān)聯(lián)值,相對于任何一個(gè)子選項(xiàng),我們都可以關(guān)聯(lián)任何值,它的意義就在于,把這些值與子選項(xiàng)進(jìn)行綁定,方便在需要的時(shí)候調(diào)用。

ResponseErrorReason

英文原義:

Represents the error reason during networking response phase.

invalidURLResponse: The response is not a valid URL response. Code 2001.

invalidHTTPStatusCode: The response contains an invalid HTTP status code. Code 2002.

URLSessionError: An error happens in the system URL session. Code 2003.

dataModifyingFailed: Data modifying fails on returning a valid data. Code 2004.

noURLResponse: The task is done but no URL response found. Code 2005.

中文翻譯:

表示網(wǎng)絡(luò)響應(yīng)階段的錯(cuò)誤原因。

invalidURLResponse: 該響應(yīng)不是有效的URL響應(yīng)。代碼2001。

invalidHTTPStatusCode: 響應(yīng)包含無效的HTTP狀態(tài)碼。代碼2002。

URLSessionError: 統(tǒng)URL會話中發(fā)生錯(cuò)誤。代碼2003。

dataModifyingFailed: 返回有效數(shù)據(jù)時(shí)數(shù)據(jù)修改失敗。代碼2004。

noURLResponse: 任務(wù)完成但沒有找到URL響應(yīng)。代碼2005。

public enum KingfisherError: Error {
  public enum ResponseErrorReason {
      case invalidURLResponse(response: URLResponse)
      case invalidHTTPStatusCode(response: HTTPURLResponse)
      case URLSessionError(error: Error)
      case dataModifyingFailed(task: SessionDataTask)
      case noURLResponse(task: SessionDataTask)
  }
}

CacheErrorReason

英文原義:

Represents the error reason during Kingfisher caching system.

fileEnumeratorCreationFailed: Cannot create a file enumerator for a certain disk URL. Code 3001.

invalidFileEnumeratorContent: Cannot get correct file contents from a file enumerator. Code 3002.

invalidURLResource: The file at target URL exists, but its URL resource is unavailable. Code 3003.

cannotLoadDataFromDisk: The file at target URL exists, but the data cannot be loaded from it. Code 3004.

cannotCreateDirectory: Cannot create a folder at a given path. Code 3005.

imageNotExisting: The requested image does not exist in cache. Code 3006.

cannotConvertToData: Cannot convert an object to data for storing. Code 3007.

cannotSerializeImage: Cannot serialize an image to data for storing. Code 3008.

cannotCreateCacheFile: Cannot create the cache file at a certain fileURL under a key. Code 3009.

cannotSetCacheFileAttribute: Cannot set file attributes to a cached file. Code 3010.

中文翻譯:

在 Kingfisher 緩存系統(tǒng)中出現(xiàn)的錯(cuò)誤。

fileEnumeratorCreationFailed: 無法為某個(gè)磁盤URL創(chuàng)建文件枚舉器。代碼3001

invalidFileEnumeratorContent: 無法從文件枚舉器獲取正確的文件內(nèi)容。代碼3002

invalidURLResource: 目標(biāo)URL上的文件存在,但是它的URL資源不可用。代碼3003

cannotLoadDataFromDisk: 目標(biāo)URL上的文件存在,但無法從中加載數(shù)據(jù)。代碼3004

cannotCreateDirectory: 無法在給定路徑上創(chuàng)建文件夾。代碼3005

imageNotExisting: 緩存中不存在所請求的圖片。代碼3006

cannotConvertToData: 無法將對象轉(zhuǎn)換為用于存儲的數(shù)據(jù)。代碼3007

cannotSerializeImage: 無法將圖片序列化為要存儲的數(shù)據(jù)。代碼3008

cannotCreateCacheFile: 無法在某個(gè)鍵下的某個(gè)文件上創(chuàng)建緩存文件。代碼3009

cannotSetCacheFileAttribute: Cannot set file attributes to a cached file. Code 3010

public enum KingfisherError: Error {
  public enum CacheErrorReason {
      case fileEnumeratorCreationFailed(url: URL)
      case invalidFileEnumeratorContent(url: URL)
      case invalidURLResource(error: Error, key: String, url: URL)
      case cannotLoadDataFromDisk(url: URL, error: Error)
      case cannotCreateDirectory(path: String, error: Error)
      case imageNotExisting(key: String)
      case cannotConvertToData(object: Any, error: Error)
      case cannotSerializeImage(image: KFCrossPlatformImage?, original: Data?, serializer: CacheSerializer)
      case cannotCreateCacheFile(fileURL: URL, key: String, data: Data, error: Error)
      case cannotSetCacheFileAttribute(filePath: String, attributes: [FileAttributeKey : Any], error: Error)
  }
}

ProcessorErrorReason

英文原義:

Represents the error reason during image processing phase.

processingFailed: Image processing fails. There is no valid output image from the processor. Code 4001.

中文翻譯:

代表在圖片處理階段的錯(cuò)誤原因。

processingFailed: 圖像處理失敗。處理器沒有有效的輸出圖像。代碼4001

public enum KingfisherError: Error {
  public enum ProcessorErrorReason {
      case processingFailed(processor: ImageProcessor, item: ImageProcessItem)
  }
}

ImageSettingErrorReason

英文原義:

Represents the error reason during image setting in a view related class.

emptySource: The input resource is empty or nil. Code 5001.

notCurrentSourceTask: The source task is finished, but it is not the one expected now. Code 5002.

dataProviderError: An error happens during getting data from an ImageDataProvider. Code 5003.

alternativeSourcesExhausted: No more alternative Source can be used in current loading process. Code 5004

中文翻譯:

表示在視圖相關(guān)類中設(shè)置圖像時(shí)出現(xiàn)錯(cuò)誤的原因。

emptySource: 輸入資源為空或“nil”。代碼5001

notCurrentSourceTask: 源任務(wù)已經(jīng)完成,但不是現(xiàn)在所期望的任務(wù)。代碼5002

dataProviderError: 從 ImageDataProvider 獲取數(shù)據(jù)時(shí)發(fā)生錯(cuò)誤。代碼5003

alternativeSourcesExhausted: 在當(dāng)前加載過程中不能使用更多的替代“源”。它的意思是。使用了 alternativeSources,Kingfisher 嘗試從最初的錯(cuò)誤恢復(fù),但使用所有給定的替代源仍然失敗。關(guān)聯(lián)的值包含加載過程中遇到的所有錯(cuò)誤,包括原始源加載錯(cuò)誤和所有替代源錯(cuò)誤。

public enum KingfisherError: Error {
  public enum ImageSettingErrorReason {
      case emptySource
      case notCurrentSourceTask(result: RetrieveImageResult?, error: Error?, source: Source)
      case dataProviderError(provider: ImageDataProvider, error: Error)
      case alternativeSourcesExhausted([PropagationError])
  }
}

便捷的檢驗(yàn)方法&屬性

是否任務(wù)被取消

public var isTaskCancelled: Bool {
  if case .requestError(reason: .taskCancelled) = self {
      return true
  }
  return false
}

是否無效的返回狀態(tài)碼

ResponseErrorReason.invalidHTTPStatusCode 這個(gè)case,并且關(guān)聯(lián)的code與給定的一致。

public func isInvalidResponseStatusCode(_ code: Int) -> Bool {
  if case .responseError(reason: .invalidHTTPStatusCode(let response)) = self {
      return response.statusCode == code
  }
  return false
}

是否無效響應(yīng)狀態(tài)碼

public var isInvalidResponseStatusCode: Bool {
  if case .responseError(reason: .invalidHTTPStatusCode) = self {
      return true
  }
  return false
}

是否當(dāng)前任務(wù)

檢查是否為 ImageSettingErrorReason.notCurrentSourceTask 類型錯(cuò)誤。當(dāng)舊的圖像設(shè)置任務(wù)仍在運(yùn)行而新的圖像設(shè)置任務(wù)啟動時(shí),將設(shè)置新的任務(wù)標(biāo)識符并覆蓋舊的任務(wù)。當(dāng)舊的任務(wù)結(jié)束時(shí),一個(gè) .notCurrentSourceTask 錯(cuò)誤將會被拋出,讓您知道設(shè)置過程以一定的結(jié)果結(jié)束,但是 image view or button 沒有被設(shè)置。

public var isNotCurrentTask: Bool {
  if case .imageSettingError(reason: .notCurrentSourceTask(_, _, _)) = self {
      return true
  }
  return false
}

localized message describing

在開發(fā)中,如果程序遇到錯(cuò)誤,我們往往會給用戶展示更加直觀的信息,這就要求我們把錯(cuò)誤信息轉(zhuǎn)換成易于理解的內(nèi)容。因此我們只要實(shí)現(xiàn)LocalizedError協(xié)議就好了。

extension KingfisherError: LocalizedError {    
  public var errorDescription: String? {
      switch self {
      case .requestError(let reason): return reason.errorDescription
      case .responseError(let reason): return reason.errorDescription
      case .cacheError(let reason): return reason.errorDescription
      case .processorError(let reason): return reason.errorDescription
      case .imageSettingError(let reason): return reason.errorDescription
      }
  }
}
extension KingfisherError: CustomNSError {
  public var errorCode: Int {
      switch self {
      case .requestError(let reason): return reason.errorCode
      case .responseError(let reason): return reason.errorCode
      case .cacheError(let reason): return reason.errorCode
      case .processorError(let reason): return reason.errorCode
      case .imageSettingError(let reason): return reason.errorCode
      }
  }
}

通過擴(kuò)展給五大錯(cuò)誤枚舉,添加描述。

extension KingfisherError.RequestErrorReason {
  var errorDescription: String? {
      switch self {
      case .emptyRequest:
          return "The request is empty or `nil`."
      case .invalidURL(let request):
          return "The request contains an invalid or empty URL. Request: (request)."
      case .taskCancelled(let task, let token):
          return "The session task was cancelled. Task: (task), cancel token: (token)."
      }
  }
  var errorCode: Int {
      switch self {
      case .emptyRequest: return 1001
      case .invalidURL: return 1002
      case .taskCancelled: return 1003
      }
  }
}
extension KingfisherError.ResponseErrorReason {
  var errorDescription: String? {
      switch self {
      case .invalidURLResponse(let response):
          return "The URL response is invalid: (response)"
      case .invalidHTTPStatusCode(let response):
          return "The HTTP status code in response is invalid. Code: (response.statusCode), response: (response)."
      case .URLSessionError(let error):
          return "A URL session error happened. The underlying error: (error)"
      case .dataModifyingFailed(let task):
          return "The data modifying delegate returned `nil` for the downloaded data. Task: (task)."
      case .noURLResponse(let task):
          return "No URL response received. Task: (task),"
      }
  }
  var errorCode: Int {
      switch self {
      case .invalidURLResponse: return 2001
      case .invalidHTTPStatusCode: return 2002
      case .URLSessionError: return 2003
      case .dataModifyingFailed: return 2004
      case .noURLResponse: return 2005
      }
  }
}
extension KingfisherError.CacheErrorReason {
  var errorDescription: String? {
      switch self {
      case .fileEnumeratorCreationFailed(let url):
          return "Cannot create file enumerator for URL: (url)."
      case .invalidFileEnumeratorContent(let url):
          return "Cannot get contents from the file enumerator at URL: (url)."
      case .invalidURLResource(let error, let key, let url):
          return "Cannot get URL resource values or data for the given URL: (url). " +
                  "Cache key: (key). Underlying error: (error)"
      case .cannotLoadDataFromDisk(let url, let error):
          return "Cannot load data from disk at URL: (url). Underlying error: (error)"
      case .cannotCreateDirectory(let path, let error):
          return "Cannot create directory at given path: Path: (path). Underlying error: (error)"
      case .imageNotExisting(let key):
          return "The image is not in cache, but you requires it should only be " +
                  "from cache by enabling the `.onlyFromCache` option. Key: (key)."
      case .cannotConvertToData(let object, let error):
          return "Cannot convert the input object to a `Data` object when storing it to disk cache. " +
                  "Object: (object). Underlying error: (error)"
      case .cannotSerializeImage(let image, let originalData, let serializer):
          return "Cannot serialize an image due to the cache serializer returning `nil`. " +
                  "Image: (String(describing:image)), original data: (String(describing: originalData)), " +
                  "serializer: (serializer)."
      case .cannotCreateCacheFile(let fileURL, let key, let data, let error):
          return "Cannot create cache file at url: (fileURL), key: (key), data length: (data.count). " +
                  "Underlying foundation error: (error)."
      case .cannotSetCacheFileAttribute(let filePath, let attributes, let error):
          return "Cannot set file attribute for the cache file at path: (filePath), attributes: (attributes)." +
                  "Underlying foundation error: (error)."
      }
  }
  var errorCode: Int {
      switch self {
      case .fileEnumeratorCreationFailed: return 3001
      case .invalidFileEnumeratorContent: return 3002
      case .invalidURLResource: return 3003
      case .cannotLoadDataFromDisk: return 3004
      case .cannotCreateDirectory: return 3005
      case .imageNotExisting: return 3006
      case .cannotConvertToData: return 3007
      case .cannotSerializeImage: return 3008
      case .cannotCreateCacheFile: return 3009
      case .cannotSetCacheFileAttribute: return 3010
      }
  }
}
extension KingfisherError.ProcessorErrorReason {
  var errorDescription: String? {
      switch self {
      case .processingFailed(let processor, let item):
          return "Processing image failed. Processor: (processor). Processing item: (item)."
      }
  }
  var errorCode: Int {
      switch self {
      case .processingFailed: return 4001
      }
  }
}
extension KingfisherError.ImageSettingErrorReason {
  var errorDescription: String? {
      switch self {
      case .emptySource:
          return "The input resource is empty."
      case .notCurrentSourceTask(let result, let error, let resource):
          if let result = result {
              return "Retrieving resource succeeded, but this source is " +
                      "not the one currently expected. Result: (result). Resource: (resource)."
          } else if let error = error {
              return "Retrieving resource failed, and this resource is " +
                      "not the one currently expected. Error: (error). Resource: (resource)."
          } else {
              return nil
          }
      case .dataProviderError(let provider, let error):
          return "Image data provider fails to provide data. Provider: (provider), error: (error)"
      case .alternativeSourcesExhausted(let errors):
          return "Image setting from alternaive sources failed: (errors)"
      }
  }
  var errorCode: Int {
      switch self {
      case .emptySource: return 5001
      case .notCurrentSourceTask: return 5002
      case .dataProviderError: return 5003
      case .alternativeSourcesExhausted: return 5004
      }
  }
}

以上就是Swift Error重構(gòu)的基礎(chǔ)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Swift Error重構(gòu)基礎(chǔ)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 用Swift構(gòu)建一個(gè)簡單的iOS郵件應(yīng)用的方法

    用Swift構(gòu)建一個(gè)簡單的iOS郵件應(yīng)用的方法

    這篇文章主要介紹了用Swift構(gòu)建一個(gè)簡單的iOS郵件應(yīng)用的方法,包括查看和標(biāo)記已讀等基本的郵件應(yīng)用功能,需要的朋友可以參考下
    2015-07-07
  • Swift中Optional值的鏈?zhǔn)秸{(diào)用學(xué)習(xí)筆記

    Swift中Optional值的鏈?zhǔn)秸{(diào)用學(xué)習(xí)筆記

    這篇文章主要介紹了Swift中Optional值的鏈?zhǔn)秸{(diào)用學(xué)習(xí)筆記,Optional鏈?zhǔn)荢wift入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2016-07-07
  • Swift如何優(yōu)雅的進(jìn)行解包

    Swift如何優(yōu)雅的進(jìn)行解包

    這篇文章主要介紹了Swift優(yōu)雅的進(jìn)行解包,對swift感興趣的同學(xué),可以參考下
    2021-04-04
  • swift依賴注入和依賴注入容器詳解

    swift依賴注入和依賴注入容器詳解

    這篇文章主要為大家介紹了swift依賴注入和依賴注入容器詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Swift 字符串類型及常用方法詳解總結(jié)

    Swift 字符串類型及常用方法詳解總結(jié)

    Swift 字符串是一系列字符的集合。例如 "Hello, World!" 這樣的有序的字符類型的值的集合,它的數(shù)據(jù)類型為 String,接下來文章將詳細(xì)探討
    2021-11-11
  • Swift實(shí)現(xiàn)3D輪播圖效果

    Swift實(shí)現(xiàn)3D輪播圖效果

    這篇文章主要為大家詳細(xì)介紹了Swift實(shí)現(xiàn)3D輪播圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • SwiftUI 中創(chuàng)建反彈動畫的實(shí)現(xiàn)

    SwiftUI 中創(chuàng)建反彈動畫的實(shí)現(xiàn)

    這篇文章主要介紹了SwiftUI 中創(chuàng)建反彈動畫的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • SwiftUI?引導(dǎo)頁界面實(shí)現(xiàn)示例

    SwiftUI?引導(dǎo)頁界面實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了SwiftUI?引導(dǎo)頁界面實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Swift教程之字符串和字符詳解

    Swift教程之字符串和字符詳解

    這篇文章主要介紹了Swift教程之字符串和字符詳解,本文講解了字符串常量、初始化一個(gè)空串、變長字符串、字符串不是指針,而是實(shí)際的值、字符等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • 快速排序算法在Swift編程中的幾種代碼實(shí)現(xiàn)示例

    快速排序算法在Swift編程中的幾種代碼實(shí)現(xiàn)示例

    快速排序是一種不穩(wěn)定的排序,存在著優(yōu)化空間,這里我們來看快速排序算法在Swift編程中的幾種代碼實(shí)現(xiàn)示例:
    2016-07-07

最新評論