listless

A simple list app for Apple platforms
Log | Files | Refs | README | LICENSE

CloudKitErrorClassifier.swift (1948B)


      1 import CloudKit
      2 import Foundation
      3 
      4 enum SyncIssue {
      5     case transient(message: String)
      6     case deferred(message: String)
      7 }
      8 
      9 enum CloudKitErrorClassifier {
     10     static func classify(_ error: Error) -> SyncIssue {
     11         let rootError = unwrap(error)
     12         let nsError = rootError as NSError
     13 
     14         if nsError.domain == CKError.errorDomain,
     15             let ckCode = CKError.Code(rawValue: nsError.code)
     16         {
     17             return classifyCloudKit(code: ckCode)
     18         }
     19 
     20         return .transient(message: "Saved locally. iCloud sync will retry automatically.")
     21     }
     22 
     23     private static func classifyCloudKit(code: CKError.Code) -> SyncIssue {
     24         switch code {
     25         case .networkUnavailable, .networkFailure, .serviceUnavailable, .requestRateLimited,
     26             .zoneBusy, .serverResponseLost, .operationCancelled:
     27             return .transient(message: "Saved locally. iCloud sync will retry automatically.")
     28 
     29         case .notAuthenticated:
     30             return .transient(message: "Sign in to iCloud to sync across devices.")
     31 
     32         case .quotaExceeded:
     33             return .transient(message: "iCloud storage full. Free up space to continue syncing.")
     34 
     35         case .permissionFailure, .badContainer, .missingEntitlement:
     36             return .transient(message: "iCloud sync unavailable. Check iCloud settings.")
     37 
     38         case .accountTemporarilyUnavailable, .zoneNotFound, .userDeletedZone:
     39             return .deferred(message: "Saved locally. iCloud sync will retry automatically.")
     40 
     41         default:
     42             return .deferred(message: "Saved locally. iCloud sync will retry automatically.")
     43         }
     44     }
     45 
     46     private static func unwrap(_ error: Error) -> Error {
     47         if let storeError = error as? ItemStoreError {
     48             switch storeError {
     49             case .fetchFailed(let wrappedError), .saveFailed(let wrappedError):
     50                 return wrappedError
     51             }
     52         }
     53         return error
     54     }
     55 }