commit
a3f000a541
16
README.md
16
README.md
|
@ -15,7 +15,7 @@
|
|||
</a>
|
||||
</p>
|
||||
|
||||
SLazeKit is an easy to use Swift restfull collection of extensions and classes. Don't spend hours writing your code to map your rest api request into models and coredata serialization. Stop wasting your time!
|
||||
SLazeKit is an easy to use Swift restful collection of extensions and classes. Don't spend hours writing your code to map your rest api request into models and coredata serialization. Stop wasting your time!
|
||||
|
||||
**SLazeKit allows you:**
|
||||
- map your models by `Codable` protocol
|
||||
|
@ -47,10 +47,19 @@ This project demonstrates a working method for using Swift Package Manager (SPM)
|
|||
|
||||
## 💊 Usage
|
||||
|
||||
For positive experience, you should configure `SLazeKit` at first. This step is optional. You may leave it as it is default.
|
||||
For positive experience, you should configure `SLazeKit` at first. This step is REQUIRED!
|
||||
|
||||
```swift
|
||||
import SLazeKit
|
||||
/// Required override of this method which will provide Context for bacground execution.
|
||||
///
|
||||
/// - Returns: NSManagedObjectContext
|
||||
open class func newBackgroundContext() -> NSManagedObjectContext? { return nil }
|
||||
```
|
||||
This step is optional. You may leave it as it is default.
|
||||
```swift
|
||||
import SLazeKit
|
||||
|
||||
extension SLazeKit {
|
||||
//Provide base path for your API requests.
|
||||
open class var basePath?: String { return "www.yourdomain.com" }
|
||||
|
@ -78,6 +87,9 @@ extension SLazeKit {
|
|||
```
|
||||
|
||||
**Model example**
|
||||
Simple
|
||||
[Object.swift](Tests/SLazeKitTests/Models/Object.swift)
|
||||
Advance
|
||||
[Model.swift](Tests/SLazeKitTests/Models/Model.swift)
|
||||
|
||||
## ⭐ Contributing
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
625B23AD1FF3462B001976C3 /* Object.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625B23AB1FF34625001976C3 /* Object.swift */; };
|
||||
OBJ_32 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; };
|
||||
OBJ_38 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* Model.swift */; };
|
||||
OBJ_39 /* SLazeKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_22 /* SLazeKitTests.swift */; };
|
||||
|
@ -53,6 +54,7 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
625B23AB1FF34625001976C3 /* Object.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Object.swift; sourceTree = "<group>"; };
|
||||
OBJ_10 /* Decodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Decodable.swift; sourceTree = "<group>"; };
|
||||
OBJ_11 /* NSManagedObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSManagedObject.swift; sourceTree = "<group>"; };
|
||||
OBJ_12 /* NSManagedObjectContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSManagedObjectContext.swift; sourceTree = "<group>"; };
|
||||
|
@ -119,6 +121,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
OBJ_21 /* Model.swift */,
|
||||
625B23AB1FF34625001976C3 /* Object.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
|
@ -132,7 +135,7 @@
|
|||
name = Products;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
OBJ_5 /* */ = {
|
||||
OBJ_5 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
OBJ_6 /* Package.swift */,
|
||||
|
@ -140,7 +143,6 @@
|
|||
OBJ_18 /* Tests */,
|
||||
OBJ_24 /* Products */,
|
||||
);
|
||||
name = "";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
OBJ_7 /* Sources */ = {
|
||||
|
@ -238,7 +240,7 @@
|
|||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = OBJ_5 /* */;
|
||||
mainGroup = OBJ_5;
|
||||
productRefGroup = OBJ_24 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
|
@ -266,6 +268,7 @@
|
|||
files = (
|
||||
OBJ_38 /* Model.swift in Sources */,
|
||||
OBJ_39 /* SLazeKitTests.swift in Sources */,
|
||||
625B23AD1FF3462B001976C3 /* Object.swift in Sources */,
|
||||
OBJ_40 /* StringInitializableTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
|
@ -1,63 +1,99 @@
|
|||
import Foundation
|
||||
|
||||
extension Decodable {
|
||||
public static func request<T: Encodable>(path: String, method: HTTPMethod, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func request(path: String, method: HTTPMethod, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func request<T: Encodable>(path: String, method: HTTPMethod, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func request<T: Encodable>(path: String, method: HTTPMethod, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func request(path: String, method: HTTPMethod, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func request<T: Encodable>(path: String, method: HTTPMethod, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func request(path: String, method: HTTPMethod, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public static func get<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func get(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func get<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func get<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func get(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func get<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func get(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public static func post<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func post(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func post<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func post<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func post(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func post<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func post(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public static func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: T, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func put(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: [T], handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: T, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func put(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: [T], handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func put(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public static func delete<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func patch(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func patch<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func patch<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func patch(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public static func delete(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func delete<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func delete<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func delete(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public static func delete<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public static func delete(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: Self?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,16 @@ import Foundation
|
|||
import CoreData
|
||||
|
||||
extension NSManagedObject {
|
||||
/// String entity name
|
||||
public class var entityName: String? {
|
||||
return NSStringFromClass(self).components(separatedBy: ".").last
|
||||
}
|
||||
|
||||
/// Finds `NSManagedObject` by EntityAttribute parameters.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - context: Context on which fetch should be executed
|
||||
/// - attributes: Entity attribute mapped by key - value
|
||||
/// - Returns: Returns first object that meet the criteria specified by a given fetch request.
|
||||
public class func find(_ context: NSManagedObjectContext?, by attributes: EntityAttribute...) throws -> NSManagedObject? {
|
||||
guard let name = entityName else { return nil }
|
||||
let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest<NSManagedObject>(entityName: name)
|
||||
|
@ -16,6 +22,12 @@ extension NSManagedObject {
|
|||
return try context?.fetch(fetchRequest).first
|
||||
}
|
||||
|
||||
/// Finds `NSManagedObject` by EntityAttribute parameters.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - context: Context on which fetch should be executed
|
||||
/// - attributes: Entity attribute mapped by key - value
|
||||
/// - Returns: Returns first object that meet the criteria specified by a given fetch request.
|
||||
public class func find(_ context: NSManagedObjectContext?, by attributes: [EntityAttribute]) throws -> NSManagedObject? {
|
||||
guard let name = entityName else { return nil }
|
||||
let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest<NSManagedObject>(entityName: name)
|
||||
|
|
|
@ -2,6 +2,7 @@ import Foundation
|
|||
import CoreData
|
||||
|
||||
extension NSManagedObjectContext {
|
||||
/// Ifthe context has uncommitted changes, attempts to commit unsaved changes to registered objects to the context’s parent store.
|
||||
func commit() {
|
||||
if hasChanges {
|
||||
do {
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
import Foundation
|
||||
|
||||
extension String {
|
||||
/// Replace string patter keys with values. For example:
|
||||
///
|
||||
/// in pattern `"/api/path/:id"`
|
||||
///
|
||||
/// `[":id":"\(123-XYZ-321)"]` `:id` key would be replaced with `"\(123-XYZ-321)"` value.
|
||||
///
|
||||
/// - Parameter arguments: Dictionary with key & value to replace.
|
||||
/// - Returns: Path with values instead of keys.
|
||||
public func patternToPath(with arguments: [String : String] = [:]) -> String {
|
||||
var path = self
|
||||
for (key, value) in arguments {
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import Foundation
|
||||
import CoreData
|
||||
|
||||
/// Entity attribute alias for key, value tuple.
|
||||
public typealias EntityAttribute = (key: String, value: Any)
|
||||
|
||||
/// Mapping protocol. Required for request object serialization.
|
||||
public protocol EntityMapping {
|
||||
static var entityType: NSManagedObject.Type { get }
|
||||
var idAttributes: [EntityAttribute]? { get }
|
||||
func fillObject(with model: NSManagedObject)
|
||||
}
|
||||
|
||||
@available(iOS 10.0, *)
|
||||
extension EntityMapping {
|
||||
func map() throws -> NSManagedObject? {
|
||||
guard let context = Self.persistentContainer?.newBackgroundContext() else { return nil }
|
||||
guard let context = SLazeKit.newBackgroundContext() else { return nil }
|
||||
let model: NSManagedObject
|
||||
if let attribiutes = idAttributes {
|
||||
model = try Self.entityType.find(context, by: attribiutes) ?? Self.entityType.init(context: context)
|
||||
|
@ -23,20 +24,27 @@ extension EntityMapping {
|
|||
context.performAndWait { context.commit() }
|
||||
return model
|
||||
}
|
||||
|
||||
private func findObject(_ context: NSManagedObjectContext?) throws -> NSManagedObject? {
|
||||
return try Self.entityType.find(context, by: idAttributes ?? [])
|
||||
}
|
||||
}
|
||||
|
||||
extension EntityMapping {
|
||||
/// Serialized managed object from datastore by given attribiutes. To be more specific. If request is returning JSON with `EntityMapping` and given Encodable object conform to this protocol. It will be automaticaly updated in DataStore. This method featch this object.
|
||||
///
|
||||
/// - Parameter context: Context on which fetch should be executed
|
||||
/// - Returns: Serialized object from EntityMapping model
|
||||
public func serialized<T: NSManagedObject>(_ context: NSManagedObjectContext?) throws -> T? {
|
||||
return (try Self.entityType.find(context, by: idAttributes ?? [])) as? T
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element: EntityMapping {
|
||||
/// Serialized managed objects from datastore by given attribiutes. To be more specific. If request is returning JSON with `EntityMapping` and given Encodable object conform to this protocol. It will be automaticaly updated in DataStore. This method featch this objects.
|
||||
///
|
||||
/// - Parameter context: Context on which fetch should be executed
|
||||
/// - Returns: Array of serialized object from EntityMapping response type.
|
||||
public func serialized<T: NSManagedObject>(_ context: NSManagedObjectContext?) throws -> [T] {
|
||||
return try flatMap({ try $0.serialized(context) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,12 @@ public protocol StringInitializable {
|
|||
}
|
||||
|
||||
extension KeyedDecodingContainerProtocol {
|
||||
/// If you API have unstable JSON responses for number types. You can use this helper method to decode string as a number. However, first you need extend your desired number type with `StringInitializable` protocol.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - type: Type to decode
|
||||
/// - key: JSON key under given type should be stored
|
||||
/// - Returns: Desired type value
|
||||
public func decodeUnstable<T: Decodable & StringInitializable>(_ type: T.Type = T.self, forKey key: Key) throws -> T? {
|
||||
guard contains(key) else { return nil }
|
||||
guard !(try decodeNil(forKey: key)) else { return nil }
|
||||
|
@ -19,6 +25,12 @@ extension KeyedDecodingContainerProtocol {
|
|||
}
|
||||
return try decode(T.self, forKey: key)
|
||||
}
|
||||
/// If you API have unstable JSON responses for number types. You can use this helper method to decode string as a number. However, first you need extend your desired number type with `StringInitializable` protocol.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - type: Type to decode
|
||||
/// - key: JSON key under given type should be stored
|
||||
/// - Returns: Desired type value
|
||||
public func decodeUnstable<T: Decodable & StringInitializable>(_ type: T.Type = T.self, forKey key: Key) throws -> T {
|
||||
if let string = try? decode(String.self, forKey: key) {
|
||||
guard let value = T.init(rawValue: string) else {
|
||||
|
|
|
@ -4,60 +4,79 @@ import CoreData
|
|||
public typealias EntityMappingCodable = EntityMapping & Codable
|
||||
public typealias EntityMappingDecodable = EntityMapping & Decodable
|
||||
|
||||
/// NetworkResponse tuple holding response `Data` and `HTTPURLResponse`
|
||||
public typealias NetworkResponse = (data: Data?, urlResponse: HTTPURLResponse?)
|
||||
|
||||
/// HTTPMethod types
|
||||
public enum HTTPMethod {
|
||||
case GET, POST, PUT, PATCH, DELETE, COPY, HEAD, OPTIONS, LINK, UNLINK, PURGE, LOCK, UNLOCK, PROPFIND, VIEW
|
||||
}
|
||||
|
||||
@available(iOS 10.0, *)
|
||||
extension EntityMapping {
|
||||
public static var persistentContainer: NSPersistentContainer? { return nil }
|
||||
}
|
||||
|
||||
/// SLazeKit is an easy to use restful collection of extensions and classes. Maps your rest api request into models and provides coredata serialization.
|
||||
public class SLazeKit {
|
||||
/// Provide base path for your API requests.
|
||||
open class var basePath: String? { return nil }
|
||||
/// Additional you can set port for your requests.
|
||||
open class var basePort: Int? { return nil }
|
||||
/// Optional provider for JSONDecoder instance.
|
||||
open class var decoder: JSONDecoder { return JSONDecoder() }
|
||||
/// Optional provider for JSONDecoder instance.
|
||||
open class var urlSession: URLSession { return URLSession.shared }
|
||||
|
||||
/// Global outgoing `URLRequest` customization. Called everytime request is created before executed.
|
||||
///
|
||||
/// - Parameter request: `URLRequest` object to setup
|
||||
/// - Returns: already setup and customize URLRequest object
|
||||
open class func setup(_ request: URLRequest) -> URLRequest { return request }
|
||||
open class func handle(_ response: HTTPURLResponse?) {}
|
||||
}
|
||||
|
||||
//MARK: network tasks implementation
|
||||
extension SLazeKit {
|
||||
class func networkTask(request: URLRequest, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
/// Required override of this method which will provide Context for bacground execution.
|
||||
///
|
||||
/// - Returns: NSManagedObjectContext
|
||||
open class func newBackgroundContext() -> NSManagedObjectContext? { return nil }
|
||||
|
||||
class func networkTask(request: URLRequest, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
let task = urlSession.dataTask(with: setup(request)) { (data, response, error) in
|
||||
handle(response as? HTTPURLResponse)
|
||||
handler(response as? HTTPURLResponse, error)
|
||||
handler((data, response as? HTTPURLResponse), error)
|
||||
}
|
||||
task.resume()
|
||||
return task
|
||||
}
|
||||
|
||||
class func networkTask<T: Decodable>(request: URLRequest, handler: @escaping (_ response: HTTPURLResponse?, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
class func networkTask<T: Decodable>(request: URLRequest, handler: @escaping (_ response: NetworkResponse, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
let task = urlSession.dataTask(with: setup(request)) { (data, response, error) in
|
||||
handle(response as? HTTPURLResponse)
|
||||
if let data = data, error == nil {
|
||||
do {
|
||||
let object = try decoder.decode(T.self, from: data)
|
||||
if #available(iOS 10.0, *) {
|
||||
try synchronize(object)
|
||||
}
|
||||
handler(response as? HTTPURLResponse, object, nil)
|
||||
handler((data, response as? HTTPURLResponse), object, nil)
|
||||
} catch {
|
||||
handler(response as? HTTPURLResponse, nil, error)
|
||||
handler((data, response as? HTTPURLResponse), nil, error)
|
||||
}
|
||||
} else {
|
||||
handler(response as? HTTPURLResponse, nil, error)
|
||||
handler((data, response as? HTTPURLResponse), nil, error)
|
||||
}
|
||||
}
|
||||
task.resume()
|
||||
return task
|
||||
}
|
||||
|
||||
class func networkTask<B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: B, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
class func networkTask(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: String, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler(nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
handler((nil,nil), NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
var request = urlRequest(url, method: method)
|
||||
request.httpBody = body.data(using: .utf8)
|
||||
return networkTask(request: request, handler: handler)
|
||||
}
|
||||
|
||||
class func networkTask<B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: B, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler((nil,nil), NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -65,16 +84,28 @@ extension SLazeKit {
|
|||
do {
|
||||
request.httpBody = try JSONEncoder().encode(body)
|
||||
} catch {
|
||||
handler(nil, error)
|
||||
handler((nil,nil), error)
|
||||
return nil
|
||||
}
|
||||
|
||||
return networkTask(request: request, handler: handler)
|
||||
}
|
||||
|
||||
class func networkTask<T: Decodable, B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: B, handler: @escaping (_ response: HTTPURLResponse?, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
class func networkTask<T: Decodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: String, handler: @escaping (_ response: NetworkResponse, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler(nil, nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
handler((nil,nil), nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
var request = urlRequest(url, method: method)
|
||||
request.httpBody = body.data(using: .utf8)
|
||||
|
||||
return networkTask(request: request, handler: handler)
|
||||
}
|
||||
|
||||
class func networkTask<T: Decodable, B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: B, handler: @escaping (_ response: NetworkResponse, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler((nil,nil), nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -82,16 +113,16 @@ extension SLazeKit {
|
|||
do {
|
||||
request.httpBody = try JSONEncoder().encode(body)
|
||||
} catch {
|
||||
handler(nil, nil, error)
|
||||
handler((nil,nil), nil, error)
|
||||
return nil
|
||||
}
|
||||
|
||||
return networkTask(request: request, handler: handler)
|
||||
}
|
||||
|
||||
class func networkTask<B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: [B], handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
class func networkTask<B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: [B], handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler(nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
handler((nil,nil), NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -99,16 +130,16 @@ extension SLazeKit {
|
|||
do {
|
||||
request.httpBody = try JSONEncoder().encode(body)
|
||||
} catch {
|
||||
handler(nil, error)
|
||||
handler((nil,nil), error)
|
||||
return nil
|
||||
}
|
||||
|
||||
return networkTask(request: request, handler: handler)
|
||||
}
|
||||
|
||||
class func networkTask<T: Decodable, B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: [B], handler: @escaping (_ response: HTTPURLResponse?, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
class func networkTask<T: Decodable, B: Encodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, body: [B], handler: @escaping (_ response: NetworkResponse, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler(nil, nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
handler((nil,nil), nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -116,24 +147,24 @@ extension SLazeKit {
|
|||
do {
|
||||
request.httpBody = try JSONEncoder().encode(body)
|
||||
} catch {
|
||||
handler(nil, nil, error)
|
||||
handler((nil,nil), nil, error)
|
||||
return nil
|
||||
}
|
||||
|
||||
return networkTask(request: request, handler: handler)
|
||||
}
|
||||
|
||||
class func networkTask(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
class func networkTask(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler(nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
handler((nil,nil), NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
return networkTask(request: urlRequest(url, method: method), handler: handler)
|
||||
}
|
||||
|
||||
class func networkTask<T: Decodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
class func networkTask<T: Decodable>(path: String, method: HTTPMethod? = nil, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ result: T?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
guard let url = components(for: path, queryItems: queryItems)?.url else {
|
||||
handler(nil, nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
handler((nil,nil), nil, NSError(domain: "Unable to get url from components", code: NSURLErrorBadURL, userInfo: nil))
|
||||
return nil
|
||||
}
|
||||
return networkTask(request: urlRequest(url, method: method), handler: handler)
|
||||
|
@ -153,12 +184,8 @@ extension SLazeKit {
|
|||
urlComponents?.queryItems = queryItems
|
||||
return urlComponents
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: CoreData mapping support
|
||||
extension SLazeKit {
|
||||
@available(iOS 10.0, *)
|
||||
fileprivate class func synchronize(_ obj: Any) throws {
|
||||
private class func synchronize(_ obj: Any) throws {
|
||||
if let array = obj as? [EntityMapping] {
|
||||
array.forEach({_ = try? $0.map()})
|
||||
} else {
|
||||
|
@ -169,63 +196,99 @@ extension SLazeKit {
|
|||
}
|
||||
|
||||
extension SLazeKit {
|
||||
public class func request<T: Encodable>(path: String, method: HTTPMethod, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func request(path: String, method: HTTPMethod, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func request<T: Encodable>(path: String, method: HTTPMethod, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func request<T: Encodable>(path: String, method: HTTPMethod, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func request(path: String, method: HTTPMethod, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func request<T: Encodable>(path: String, method: HTTPMethod, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func request(path: String, method: HTTPMethod, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: method, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public class func get<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func get(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func get<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func get<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func get(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func get<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func get(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public class func post<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func post(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func post<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func post<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func post(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func post<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func post(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .POST, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public class func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: T, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func put(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: [T], handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: T, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func put(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func put<T: Encodable>(path: String, queryItems: [URLQueryItem]? = nil, body: [T], handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func put(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PUT, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public class func delete<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func patch(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func patch<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func patch<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func patch(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .PATCH, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
|
||||
public class func delete(path: String, body: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func delete<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func delete<T: Encodable>(path: String, body: T, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func delete(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: HTTPURLResponse?, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
public class func delete<T: Encodable>(path: String, body: [T], queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, body: body, handler: handler)
|
||||
}
|
||||
|
||||
public class func delete(path: String, queryItems: [URLQueryItem]? = nil, handler: @escaping (_ response: NetworkResponse, _ error: Error?) -> ()) -> URLSessionDataTask? {
|
||||
return SLazeKit.networkTask(path: path, method: .DELETE, queryItems: queryItems, handler: handler)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,7 @@ import Foundation
|
|||
import SLazeKit
|
||||
import CoreData
|
||||
|
||||
//First we gonna create NSManagedObject object on which we will work.
|
||||
|
||||
/// We assume you have Model as an NSManagedObject
|
||||
class Model: NSManagedObject {}
|
||||
|
||||
// MARK: - Simulate extension for CoreData
|
||||
extension Model {
|
||||
class Model: NSManagedObject {
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<Model> {
|
||||
return NSFetchRequest<Model>(entityName: "Model")
|
||||
}
|
||||
|
@ -16,11 +10,7 @@ extension Model {
|
|||
@NSManaged public var id: String
|
||||
@NSManaged public var value: Double
|
||||
@NSManaged public var name: String?
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SLazeKit extension
|
||||
extension Model {
|
||||
/// Path pattern for our model API requests
|
||||
public struct PathPattern {
|
||||
static var model: String { return "/api/Models/:modelId" }
|
||||
|
@ -53,7 +43,6 @@ extension Model {
|
|||
object.name = name
|
||||
}
|
||||
}
|
||||
|
||||
/// We could skip that and add `Encodable` to our ModelResponse. But to highlight it. We will create separate one for request purpose
|
||||
public struct ModelRequest: Encodable {
|
||||
var id: String
|
||||
|
@ -66,9 +55,6 @@ extension Model {
|
|||
self.name = model.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Model {
|
||||
/// Create request. Called from SLazeKit. Response is not maped or serialized.
|
||||
///
|
||||
/// - Parameters:
|
||||
|
@ -77,7 +63,7 @@ extension Model {
|
|||
/// SLazeKit request are done i background. To handle response on main thread we need to dispatch it.
|
||||
let _ = SLazeKit.post(path: PathPattern.create.patternToPath(with: ["modelId":model.id]), body: ModelRequest(with: model)) { (response, error) in
|
||||
guard error == nil else {
|
||||
DispatchQueue.main.async { failure?(response?.statusCode ?? -1,error) }
|
||||
DispatchQueue.main.async { failure?(response.urlResponse?.statusCode ?? -1,error) }
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.async { success() }
|
||||
|
@ -87,19 +73,24 @@ extension Model {
|
|||
///
|
||||
/// - Parameters:
|
||||
/// - modelId: model id used to replace key string in path pattern.
|
||||
class func remove(for modelId: String, success: @escaping (() ->()), failure: ((_ statusCode: Int, _ error: Error?) ->())? = nil) {
|
||||
///
|
||||
/// SLazeKit request are done i background. To handle response on main thread we need to dispatch it.
|
||||
class func remove(for modelId: String, success: @escaping (() ->()), failure: ((_ statusCode: Int, _ error: Error?) ->())? = nil) {
|
||||
let _ = SLazeKit.delete(path: PathPattern.delete.patternToPath(with: ["modelId":modelId])) { (response, error) in
|
||||
guard error == nil else {
|
||||
DispatchQueue.main.async { failure?(response?.statusCode ?? -1,error) }
|
||||
DispatchQueue.main.async { failure?(response.urlResponse?.statusCode ?? -1,error) }
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.async { success() }
|
||||
}
|
||||
}
|
||||
/// `[ModelResponse]` Stands as a result type. Decodable provides generic requests. if Response model beside `Decodable` comforms to `EntityMapping` as well it will be serialized.
|
||||
class func getFromServer(success: @escaping (([Model]?) ->()), failure: (() ->())? = nil) {
|
||||
///
|
||||
/// [ModelResponse] Decodable type used to generate result type.
|
||||
///
|
||||
///Result is type of `[ModelResponse]` to return array of our CoreData models we need to serialize it.
|
||||
///`result?.serialized` will return `[Model]`
|
||||
class func getFromServer(success: @escaping (([Model]?) ->()), failure: (() ->())? = nil) {
|
||||
let _ = [ModelResponse].get(path: PathPattern.models.patternToPath()) { (response, result, error) in
|
||||
guard error == nil else {
|
||||
failure?()
|
||||
|
@ -107,18 +98,19 @@ extension Model {
|
|||
}
|
||||
var models: [Model]? = nil
|
||||
do {
|
||||
//Result is type of `[ModelResponse]` to return array of our CoreData models we need to serialize it.
|
||||
//result?.serialized will return `[Model]`
|
||||
models = try result?.serialized(ModelResponse.persistentContainer?.newBackgroundContext())
|
||||
models = try result?.serialized(SLazeKit.newBackgroundContext())
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
success(models)
|
||||
}
|
||||
}
|
||||
|
||||
/// In this example API request will decode single object of type ModelResponse instead of an array.
|
||||
///
|
||||
///Result of type `ModelResponse` to return CoreData model we need to serialize it.
|
||||
///
|
||||
///`result?.serialized` will return `Model`
|
||||
class func getFromServer(for modelId: String, success: @escaping ((Model?) ->()), failure: (() ->())? = nil) {
|
||||
/// in this example API request will decode single object of type ModelResponse instead of an array.
|
||||
let _ = ModelResponse.get(path: PathPattern.model.patternToPath(with: ["modelId":modelId])) { (response, result, error) in
|
||||
guard error == nil else {
|
||||
failure?()
|
||||
|
@ -126,9 +118,7 @@ extension Model {
|
|||
}
|
||||
var models: Model? = nil
|
||||
do {
|
||||
//Result of type `ModelResponse` to return CoreData model we need to serialize it.
|
||||
//result?.serialized will return `Model`
|
||||
models = try result?.serialized(ModelResponse.persistentContainer?.newBackgroundContext())
|
||||
models = try result?.serialized(SLazeKit.newBackgroundContext())
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import Foundation
|
||||
import SLazeKit
|
||||
import CoreData
|
||||
|
||||
class Object: NSManagedObject {
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<Object> {
|
||||
return NSFetchRequest<Object>(entityName: "Object")
|
||||
}
|
||||
|
||||
@NSManaged public var id: String
|
||||
@NSManaged public var value: Double
|
||||
@NSManaged public var name: String?
|
||||
|
||||
/// Path pattern for our model API requests
|
||||
public struct PathPattern {
|
||||
static var model: String { return "/api/Objects/:modelId" }
|
||||
static var models: String { return "/api/Objects" }
|
||||
static var create: String { return "/api/Objects/:modelId/create" }
|
||||
static var delete: String { return "/api/Objects/:modelId/delete" }
|
||||
}
|
||||
/// We are creating struct which represents Codable object of our API request
|
||||
/// `EntityMappingCodable` is required
|
||||
public struct ObjectRestful: EntityMappingCodable {
|
||||
var id: String
|
||||
var value: Double
|
||||
var name: String?
|
||||
/// We need provide NSManagedObject type for our serialization.
|
||||
public static var entityType: NSManagedObject.Type {
|
||||
return Object.self
|
||||
}
|
||||
/// By providing id attributes our model are updated/created/serialized
|
||||
public var idAttributes: [EntityAttribute]? {
|
||||
return [
|
||||
("id",id)
|
||||
]
|
||||
}
|
||||
/// init ObjectRestful with our Object clss
|
||||
///
|
||||
/// - Parameter model: model of our Object class
|
||||
init(with model: Object) {
|
||||
self.id = model.id
|
||||
self.value = model.value
|
||||
self.name = model.name
|
||||
}
|
||||
|
||||
/// Fill CoreData object with our model response
|
||||
public func fillObject(with model: NSManagedObject) {
|
||||
guard let object = model as? Object else { return }
|
||||
object.id = id
|
||||
object.value = value
|
||||
object.name = name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue