Skip to content

Instantly share code, notes, and snippets.

View SwiftyAlex's full-sized avatar

Alex Logan SwiftyAlex

View GitHub Profile
@SwiftyAlex
SwiftyAlex / Route.swift
Last active September 15, 2019 12:53
A Simple, TypeSafe routing protocol built around Combine.
public protocol Route {
/// Request & ResponseType are forced, but `EmptyRequest` allows you to skip encoding/decoding
associatedtype RequestType: Encodable
associatedtype ResponseType: Decodable
static var method: HTTPMethod { get }
static var path: String { get }
/// Optional instance of `RequestType` that gets encoded if present
var requestObject: RequestType? { get set }
@SwiftyAlex
SwiftyAlex / Route.swift
Last active September 23, 2019 07:10
Route Protocol
public protocol Route {
/// Request & ResponseType are forced, but `Empty` allows you to skip encoding/decoding
associatedtype RequestType: Encodable
associatedtype ResponseType: Decodable
static var method: HTTPMethod { get }
static var path: String { get }
static var requiresAuth: Bool { get }
/// Optional instance of `RequestType` that gets encoded if present
var requestObject: RequestType? { get set }
@SwiftyAlex
SwiftyAlex / Route+toRequest.swift
Last active September 22, 2019 16:02
Route+toRequest
extension Route {
/// Default parameters so routes do not need to declare these
var queryParameters: [URLQueryItem] {
return []
}
var pathParameters: [String] {
return []
}
/// The basic implementation of `Route` `toRequest` adds parameters and builds the path.
public func toRequest() -> URLRequest {
@SwiftyAlex
SwiftyAlex / GetTodoRoute.swift
Last active September 22, 2019 16:30
A Route that gets a Todo
/// A route that gets a single `Todo`.
public struct GetTodoRoute: Route {
public typealias RequestType = Empty
public typealias ResponseType = Todo
public static let method = HTTPMethod.get
public static let path = "todos"
public static let requiresAuth = false
public var requestObject: Empty?
@SwiftyAlex
SwiftyAlex / TodoService.swift
Last active September 22, 2019 15:48
Todo Service
import Foundation
import Combine
public class TodoService {
public func getTodo(todo: Todo) -> AnyPublisher<Todo, Error> {
return Router.performRequest(GetTodoRoute(todo: todo))
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}
@SwiftyAlex
SwiftyAlex / Router.swift
Last active September 22, 2019 16:14
A Router
public class Router {
static var baseUrl = APIConfig.baseURL
@available(iOS 13.0, *)
public static func performRequest<R: Route>(_ route: R) -> AnyPublisher<R.ResponseType, Error> {
return URLSession.shared.dataTaskPublisher(for: route.toRequest())
.mapError { NetworkError(from: $0) }
.map(\.data)
.decode(type: R.ResponseType.self, decoder: JSONDecoder())
.mapError { _ in NetworkError.decodingFailed }
@SwiftyAlex
SwiftyAlex / GetTodo.swift
Created September 22, 2019 15:59
Get Todo
TodoService().getTodo(todo: Todo.placeholder(id: 1))
.sink(receiveCompletion: {
(completion) in
print(completion)
}) { (todo) in
print(todo)
}
import CoreData
@propertyWrapper
class Fetched<Object: NSManagedObject>: NSObject, NSFetchedResultsControllerDelegate {
private var _fetchedResultsController: NSFetchedResultsController<Object>?
var wrappedValue: [Object] = []
init(context: NSManagedObjectContext = CoreDataService.context, sortDescriptiors: [NSSortDescriptor] = [], predicate: NSPredicate? = nil) {
super.init()
// Setup a fetch request
import CoreData
@propertyWrapper
class Fetched<Object: NSManagedObject>: NSObject, NSFetchedResultsControllerDelegate {
private var _fetchedResultsController: NSFetchedResultsController<Object>?
var wrappedValue: [Object] = []
init(context: NSManagedObjectContext = CoreDataService.context, sortDescriptiors: [NSSortDescriptor] = [], predicate: NSPredicate? = nil) {
super.init()
// Setup a fetch request
@propertyWrapper
struct Ubiquitous<T> {
private var key: String
private var defaultValue: T
private var store: NSUbiquitousKeyValueStore
init(key: String, defaultValue: T, store: NSUbiquitousKeyValueStore = .default) {
self.key = key
self.defaultValue = defaultValue
self.store = store