diff --git a/Counters.xcodeproj/project.pbxproj b/Counters.xcodeproj/project.pbxproj index 4ac3e28..c8d5971 100644 --- a/Counters.xcodeproj/project.pbxproj +++ b/Counters.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 00039F6C268210520061B2A2 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00039F6B268210520061B2A2 /* String+Extensions.swift */; }; + 000BB85126B1CA79001B2C7E /* URLResponse+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000BB85026B1CA79001B2C7E /* URLResponse+Extensions.swift */; }; 001978632695D13B0092FFF1 /* UserDefaultsProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 001978622695D13B0092FFF1 /* UserDefaultsProtocol.swift */; }; 001978692695D1D80092FFF1 /* UserDefaultsMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 001978682695D1D80092FFF1 /* UserDefaultsMock.swift */; }; 002ABA3126666F5500F5B3C9 /* CreateCounterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002ABA2626666F5500F5B3C9 /* CreateCounterViewModel.swift */; }; @@ -98,6 +99,7 @@ /* Begin PBXFileReference section */ 00039F6B268210520061B2A2 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; + 000BB85026B1CA79001B2C7E /* URLResponse+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLResponse+Extensions.swift"; sourceTree = ""; }; 001978622695D13B0092FFF1 /* UserDefaultsProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsProtocol.swift; sourceTree = ""; }; 001978682695D1D80092FFF1 /* UserDefaultsMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsMock.swift; sourceTree = ""; }; 002ABA2626666F5500F5B3C9 /* CreateCounterViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateCounterViewModel.swift; sourceTree = ""; }; @@ -496,6 +498,7 @@ children = ( 00A1035C26651BF200E661CD /* URL+Extensions.swift */, 00A1035826651BF200E661CD /* URLRequest+Extensions.swift */, + 000BB85026B1CA79001B2C7E /* URLResponse+Extensions.swift */, ); path = Extensions; sourceTree = ""; @@ -830,6 +833,7 @@ 00A1036226651BF200E661CD /* APIClient.swift in Sources */, 007C166C2681046800EB74C5 /* ExampleCollectionViewCell.swift in Sources */, 00A103922665204200E661CD /* CustomTextField.swift in Sources */, + 000BB85126B1CA79001B2C7E /* URLResponse+Extensions.swift in Sources */, 00CF700C269CB7D100F5AB5E /* ExamplesCollectionViewDataSource.swift in Sources */, 00A103AA266522C800E661CD /* UIImage+Badge.swift in Sources */, 002ABA3326666F5500F5B3C9 /* CreateCounterStrings.swift in Sources */, diff --git a/Counters/Counters/ViewModel/CountersViewModel.swift b/Counters/Counters/ViewModel/CountersViewModel.swift index fb24298..1a0611c 100644 --- a/Counters/Counters/ViewModel/CountersViewModel.swift +++ b/Counters/Counters/ViewModel/CountersViewModel.swift @@ -7,7 +7,7 @@ import Foundation -final class CountersViewModel: ObservableObject { +final class CountersViewModel { private let service: CountersService private let userDefaults: UserDefaultsProtocol @@ -15,6 +15,9 @@ final class CountersViewModel: ObservableObject { private(set) var filteredCounters: [Counter] = [] private let firstTimeOpenKey = "FirstOpen" + private var cache = Cache.shared + private var countersCacheKey = "counters" + private(set) var viewState: ViewState = .noContent { didSet { switch viewState { @@ -26,9 +29,21 @@ final class CountersViewModel: ObservableObject { } } - private var cache = Cache.shared - private var countersCacheKey = "counters" + // View bindings + var didChangeState: ((ViewState, ViewStateError?) -> Void)? = { (_, _) in + fatalError("Not implemented") + } + // Init + init(service: CountersService = CountersService(), + userDefaults: UserDefaultsProtocol = UserDefaults.standard) { + self.service = service + self.userDefaults = userDefaults + } +} + +// MARK: - Computed properties +extension CountersViewModel { var totalCountersText: String { guard counters.count > 0 else { return "" @@ -50,16 +65,6 @@ final class CountersViewModel: ObservableObject { var isFilteredCountersEmpty: Bool { return filteredCounters.count == 0 } - - // View bindings - var didChangeState: ((ViewState, ViewStateError?) -> Void)? - - // Init - init(service: CountersService = CountersService(), - userDefaults: UserDefaultsProtocol = UserDefaults.standard) { - self.service = service - self.userDefaults = userDefaults - } } // MARK: - Public methods diff --git a/Counters/Network/APIClient.swift b/Counters/Network/APIClient.swift index 1ad12ab..6f937a1 100755 --- a/Counters/Network/APIClient.swift +++ b/Counters/Network/APIClient.swift @@ -42,7 +42,7 @@ class APIClient { } if let response = response as? HTTPURLResponse, - !(200..<300 ~= response.statusCode) { + response.validationStatus != .success { completion(.failure(APIError(response)), response) return } diff --git a/Counters/Network/Extensions/URLResponse+Extensions.swift b/Counters/Network/Extensions/URLResponse+Extensions.swift new file mode 100644 index 0000000..a671d0d --- /dev/null +++ b/Counters/Network/Extensions/URLResponse+Extensions.swift @@ -0,0 +1,41 @@ +// +// URLResponse+Extensions.swift +// Counters +// +// Created by Fabio Cezar Salata on 28/07/21. +// + +import Foundation + +enum ValidationStatus { + case informational // 100 + case success // 200 + case redirection // 300 + case clientError // 400 + case serverError // 500 + case unknown +} + +extension URLResponse { + var validationStatus: ValidationStatus { + if let httpResponse = self as? HTTPURLResponse { + let statusCode = httpResponse.statusCode + switch statusCode { + case 0...199: + return .informational + case 200...299: + return .success + case 300...399: + return .redirection + case 400...499: + return .clientError + case 500...599: + return .serverError + default: + return .unknown + } + } else { + return .unknown + } + } +}