-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a common interface to provide persistent data storage, currently implemented one provider to store data in the `UserDefaults` for local persistence
- Loading branch information
1 parent
35a78f1
commit 319bc2e
Showing
10 changed files
with
406 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// | ||
// LocalProvider.swift | ||
// TodoAll | ||
// | ||
// Created by Franklin Cruz on 27-10-20. | ||
// Copyright © 2020 S.Y.Soft. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import Combine | ||
|
||
class LocalProvider: Provider { | ||
private static var storeNames = [ | ||
Task.typeName: "tasks" | ||
] | ||
|
||
class func registerStoreName(forType type: Any.Type) { | ||
storeNames[String(describing: type)] = String(describing: type) | ||
} | ||
|
||
private func getAllData<T>() -> [T] where T : Identifiable & Codable { | ||
let userDefaults = UserDefaults.standard | ||
|
||
guard let storeName = LocalProvider.storeNames[T.typeName] else { return [] } | ||
|
||
guard let data = userDefaults.data(forKey: storeName) else { return [] } | ||
|
||
let decoder = JSONDecoder() | ||
|
||
if let decoded = try? decoder.decode([T].self, from: data) { | ||
return decoded | ||
} | ||
|
||
return [] | ||
} | ||
|
||
private func save<T>(data: [T]) where T : Identifiable & Codable { | ||
let userDefaults = UserDefaults.standard | ||
|
||
guard let storeName = LocalProvider.storeNames[T.typeName] else { return } | ||
|
||
let encoder = JSONEncoder() | ||
if let encoded = try? encoder.encode(data) { | ||
userDefaults.set(encoded, forKey: storeName) | ||
} | ||
} | ||
|
||
func list<T>(filter: [String : Any]?, sort: [String : SortDirection]?) -> Future<[T], ServiceError> where T : Identifiable & Codable { | ||
return Future { promise in | ||
DispatchQueue.global(qos: .background).async { | ||
promise(.success(self.getAllData())) | ||
} | ||
} | ||
} | ||
|
||
func get<T>(byId id: T.ID) -> Future<T?, ServiceError> where T : Identifiable & Codable { | ||
return Future { promise in | ||
DispatchQueue.global(qos: .background).async { | ||
let data: T? = self.getAllData().first(where: { $0.id == id }) | ||
promise(.success(data)) | ||
} | ||
} | ||
} | ||
|
||
func create<T>(_ element: T) -> Future<T?, ServiceError> where T : Identifiable & Codable { | ||
return Future { promise in | ||
DispatchQueue.global(qos: .background).async { | ||
var all: [T] = self.getAllData() | ||
all.append(element) | ||
self.save(data: all) | ||
promise(.success(element)) | ||
} | ||
} | ||
} | ||
|
||
func update<T>(_ element: T) -> Future<T?, ServiceError> where T : Identifiable & Codable { | ||
return Future { promise in | ||
DispatchQueue.global(qos: .background).async { | ||
var all: [T] = self.getAllData() | ||
all.removeAll(where: {$0.id == element.id}) | ||
all.append(element) | ||
self.save(data: all) | ||
promise(.success(element)) | ||
} | ||
} | ||
} | ||
|
||
func delete<T>(byId id: T.ID) -> Future<T?, ServiceError> where T : Identifiable & Codable { | ||
return Future { promise in | ||
DispatchQueue.global(qos: .background).async { | ||
var all: [T] = self.getAllData() | ||
let element = all.first(where: { $0.id == id}) | ||
all.removeAll(where: {$0.id == id}) | ||
self.save(data: all) | ||
promise(.success(element)) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// | ||
// Provider.swift | ||
// TodoAll | ||
// | ||
// Created by Franklin Cruz on 27-10-20. | ||
// Copyright © 2020 S.Y.Soft. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import Combine | ||
|
||
enum SortDirection { | ||
case ascending | ||
case descending | ||
} | ||
|
||
protocol Provider { | ||
func list<T>(filter: [String:Any]?, sort: [String: SortDirection]?) -> Future<[T], ServiceError> where T: Identifiable & Codable | ||
func get<T>(byId id: T.ID) -> Future<T?, ServiceError> where T: Identifiable & Codable | ||
func create<T>(_ element: T) -> Future<T?, ServiceError> where T: Identifiable & Codable | ||
func update<T>(_ element: T) -> Future<T?, ServiceError> where T: Identifiable & Codable | ||
func delete<T>(byId id: T.ID) -> Future<T?, ServiceError> where T: Identifiable & Codable | ||
} | ||
|
||
extension Provider { | ||
func list<T>(filter: [String:Any]? = nil, sort: [String: SortDirection]? = nil) -> Future<[T], ServiceError> where T: Identifiable & Codable { | ||
return list(filter: filter, sort: sort) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// | ||
// Struct+TypeName.swift | ||
// TodoAll | ||
// | ||
// Created by Franklin Cruz on 27-10-20. | ||
// Copyright © 2020 S.Y.Soft. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
extension Identifiable { | ||
static var typeName: String { | ||
return String(describing: Self.self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.