172 lines
7.3 KiB
Swift
172 lines
7.3 KiB
Swift
import Foundation
|
|
import SLazeCoreData
|
|
import SLazeKit
|
|
import CoreData
|
|
|
|
class Model: NSManagedObject {
|
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<Model> {
|
|
return NSFetchRequest<Model>(entityName: "Model")
|
|
}
|
|
|
|
@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/Models/:modelId" }
|
|
static var models: String { return "/api/Models" }
|
|
static var create: String { return "/api/Models/:modelId/create" }
|
|
static var delete: String { return "/api/Models/:modelId/delete" }
|
|
}
|
|
/// We are creating struct which represents Decodable response of API request
|
|
/// `EntityMappingDecodable` is required
|
|
public struct ModelResponse: EntityMappingDecodable {
|
|
var id: String
|
|
var value: Double
|
|
var name: String?
|
|
/// We need provide NSManagedObject type for our serialization.
|
|
public static var entityType: NSManagedObject.Type {
|
|
return Model.self
|
|
}
|
|
/// By providing id attributes our model are updated/created/serialized
|
|
public var idAttributes: [EntityAttribute]? {
|
|
return [
|
|
("id",id)
|
|
]
|
|
}
|
|
|
|
/// Fill CoreData object with our model response
|
|
public func fillObject(with model: NSManagedObject) {
|
|
guard let object = model as? Model else { return }
|
|
object.id = id
|
|
object.value = value
|
|
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
|
|
var value: Double
|
|
var name: String?
|
|
//Convenience initializer.
|
|
init(with model: Model) {
|
|
self.id = model.id
|
|
self.value = model.value
|
|
self.name = model.name
|
|
}
|
|
}
|
|
/// Create request. Called from SLazeKit. Response is not maped or serialized.
|
|
///
|
|
/// - Parameters:
|
|
/// - model: CoreData model used to post request with body of ModelRequest
|
|
class func create(model: Model, 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.
|
|
let _ = SLazeKit<Default>.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.http?.statusCode ?? -1,error) }
|
|
return
|
|
}
|
|
DispatchQueue.main.async { success() }
|
|
}
|
|
}
|
|
/// Another request example with out mapping or serialization.
|
|
///
|
|
/// - Parameters:
|
|
/// - modelId: model id used to replace key string in path pattern.
|
|
///
|
|
/// 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<Default>.delete(path: PathPattern.delete.patternToPath(with: ["modelId":modelId])) { (response, error) in
|
|
guard error == nil else {
|
|
DispatchQueue.main.async { failure?(response.http?.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.
|
|
///
|
|
/// [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?()
|
|
return
|
|
}
|
|
var models: [Model]? = nil
|
|
do {
|
|
models = try result?.serialized(Default.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) {
|
|
let _ = ModelResponse.get(path: PathPattern.model.patternToPath(with: ["modelId":modelId])) { (response, result, error) in
|
|
guard error == nil else {
|
|
failure?()
|
|
return
|
|
}
|
|
var models: Model? = nil
|
|
do {
|
|
models = try result?.serialized(Default.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 getFromOtherServer(for modelId: String, success: @escaping ((Model?) ->()), failure: (() ->())? = nil) {
|
|
class NoneDefault: LazeConfiguration {
|
|
static var basePath: String? { return "www.yourdomain.com" }
|
|
static var basePort: Int? { return 8765 }
|
|
static var decoder: JSONDecoder { return JSONDecoder() }
|
|
static var urlSession: URLSession { return URLSession.shared }
|
|
|
|
static func setup(_ request: URLRequest) -> URLRequest {
|
|
var request: URLRequest = request
|
|
request.setValue("Your token", forHTTPHeaderField: "X-Access-Token")
|
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
return request
|
|
}
|
|
|
|
static func handle(_ response: HTTPURLResponse?) {
|
|
if response?.statusCode == 401 {
|
|
print("unauthorised")
|
|
}
|
|
}
|
|
|
|
public static func newBackgroundContext() -> NSManagedObjectContext? { return NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) }
|
|
}
|
|
let _ = Laze<NoneDefault,ModelResponse>.get(path: PathPattern.model.patternToPath(with: ["modelId":modelId])) { (response, result, error) in
|
|
guard error == nil else {
|
|
failure?()
|
|
return
|
|
}
|
|
var models: Model? = nil
|
|
do {
|
|
models = try result?.serialized(Default.newBackgroundContext())
|
|
} catch {
|
|
print(error)
|
|
}
|
|
success(models)
|
|
}
|
|
}
|
|
}
|