SlideShare a Scribd company logo
Values, Protocols and Codables
Florent Vilmart
•
•
•
•
What we’ll cover
Disclaimer
I have no idea what I’m doin’
•
•
•
•
•
Parse SDK
not your average SDK
An API, to build API’s
Parse SDK iOS/OSX Parse Swift
Runtime Dynamism Compile-time Dynamism
Object Oriented PoP
NSObject struct
async (Bolts) sync
iOS/macOS/tvOS/watchOS Just Swift
Objective-C vs Swift
The past, the present…
o
Value protocols and codables
An REST API is a contract
… but …
Object
Data
Data
Object
Serialize ⚠️💣
Send
Responds
💣 ⚠️ Deserialize
💥
💥
Any API Client…
Till today
T:
Encodable
Data
Data
U:
Decodable
JSONEncoder
Send
Responds
JSONDecoderFor Free!
For Free!
URLSession
REST with Swift 4
T: Encodable
URLSession
U: Decodable
Great spot to fake / mock your server!
Or datastore
Or anything really…
REST abstract
Encodable / Decodable
Strings, Numbers, enum, Arrays, Dictionaries (of Codables) …
Objects / Structs with only Codable’s
Custom *(through protocol conformance)
Implement CodingKeys for encoding subset
Composability
Codable’s
•
•
•
•
Encoders / Decoders
•
•
•
•
•
JSONEncoder / ParseEncoder
JSON and friends
Value protocols and codables
Protocols
protocol Saving: Encodable {
associatedtype SavingType
func save(options: Options) throws -> SavingType
func save() throws -> SavingType
}
protocol Fetching: Decodable {
associatedtype FetchingType
func fetch(options: Options) throws -> FetchingType
func fetch() throws -> FetchingType
}
ObjectType Protocol
public protocol ObjectType: Fetching, Saving {
static var className: String { get }
var objectId: String? { get set }
var createdAt: Date? { get set }
var updatedAt: Date? { get set }
var ACL: ACL? { get set }
}
public extension ObjectType {
public func save(options: Options = []) throws -> Self {
return try Command<Self, SaveResponse>(method: .POST,
path: object.endpoint,
params: nil,
body: object)
.execute(options: options)
.map { $0.apply(self) }
}
}
Extensible
extension Saving {
typealias Callback = (Self.SavingType?, Error?) -> Void
func save(options: API.Options = [],
callback: @escaping Callback) {
runAsync(options: options,
function: self.save,
callback: callback)
}
}
runAsync
let queue = DispatchQueue(label: "org.parse-community.ParseSwift.async")
private func runAsync<T>(options: API.Options,
function: @escaping (API.Options) throws -> T?,
callback: @escaping (T?, Error?) -> Void) {
queue.async {
do {
callback(try function(options), nil)
} catch let e {
callback(nil, e)
}
}
}
As a SDK user
struct GameScore: ParseSwift.ObjectType {
//: Those are required for ObjectType
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ACL?
//: Your own properties
var score: Int
//: a custom initializer
init(score: Int) {
self.score = score
}
}
let score = GameScore(score: 10)
guard let savedScore = try? score.save() else { fatalError() }
public struct Command<T, U>: Encodable where T: Encodable, U: Decodable {
let method: Method
let path: Endpoint
let params: [String: String?]?
let body: T?
public func data() throws -> Data? {
return try JSONEncoder().encode(body)
}
public func execute(options: Options) throws -> Response<U> {
return try options.executor.execute(command: self, options: options)
}
internal func decode(responseData: Data) throws -> Response<U> {
do {
return Response(object: try Decoder.json.decode(U.self, from: responseData))
} catch _ {
throw try Decoder.json.decode(ParseError.self, from: responseData)
}
}
}
Command
Commands
extension Command where T: ObjectType {
// MARK: custom encoding
func data() throws -> Data? {
return try API.Encoder.parse.encode(body)
}
}
struct Response<T> where T: Decodable {
let object: T
func map<U>(_ mapper: (T) throws -> U) rethrows -> U {
return try mapper(object)
}
}
Executor
extension API.Command {
internal func getURLRequest(options: API.Options) throws -> URLRequest {
/* build a URLRequest from the command */
}
}
extension URLSession: APIExecutor {
public func execute<T, U>(command: API.Command<T, U>,
options: API.Options) throws -> API.Response<U> {
let urlRequest = try command.getURLRequest(options: options)
let responseData = try self.syncDataTask(with: urlRequest)
return try command.decode(responseData: responseData)
}
}
•
•
•
•
•
About Async
A Quick Word on sync code
no async is the best async
extension URLSession {
internal func syncDataTask(with request: URLRequest) throws -> Data {
let semaphore = DispatchSemaphore(value: 0)
var data: Data?
var error: Error?
var response: URLResponse?
dataTask(with: request) { (responseData, urlResponse, responseError) in
data = responseData; error = responseError; response = urlResponse;
semaphore.signal()
}.resume()
semaphore.wait()
guard let responseData = data else {
guard let error = error else { // no err no res?
throw NSError(domain: "unknown", code: -1, userInfo: ["response": response!])
}
throw error
}
return responseData
}
}
🤦♀️
•
•
•
•
•
What’s next
Because all is not green!
Values, Protocols and Codables
Florent Vilmart

More Related Content

PPTX
Parse, scale to millions
PDF
Happy Go Programming Part 1
PDF
并发模型介绍
PDF
Happy Go Programming
PDF
Docker tips & tricks
KEY
Kansai.pm 10周年記念 Plack/PSGI 入門
ODP
nginx mod PSGI
PDF
PuppetDB, Puppet Explorer and puppetdbquery
Parse, scale to millions
Happy Go Programming Part 1
并发模型介绍
Happy Go Programming
Docker tips & tricks
Kansai.pm 10周年記念 Plack/PSGI 入門
nginx mod PSGI
PuppetDB, Puppet Explorer and puppetdbquery

What's hot (20)

PDF
Unleash your inner console cowboy
PPTX
Migrating to Puppet 4.0
PDF
Vim Script Programming
PDF
Ansible, Simplicity, and the Zen of Python
PPTX
(Practical) linux 104
PDF
BSDM with BASH: Command Interpolation
PDF
BASH Variables Part 1: Basic Interpolation
PDF
PDF
Web Audio API + AngularJS
PPTX
Ansible for Beginners
PDF
Keeping objects healthy with Object::Exercise.
PDF
Hypers and Gathers and Takes! Oh my!
PDF
Ethiopian multiplication in Perl6
PDF
Findbin libs
PDF
Metadata-driven Testing
PDF
Application Logging in the 21st century - 2014.key
PDF
JIP Pipeline System Introduction
PPTX
Linux networking
PPTX
PPTX
DevOps with Fabric
Unleash your inner console cowboy
Migrating to Puppet 4.0
Vim Script Programming
Ansible, Simplicity, and the Zen of Python
(Practical) linux 104
BSDM with BASH: Command Interpolation
BASH Variables Part 1: Basic Interpolation
Web Audio API + AngularJS
Ansible for Beginners
Keeping objects healthy with Object::Exercise.
Hypers and Gathers and Takes! Oh my!
Ethiopian multiplication in Perl6
Findbin libs
Metadata-driven Testing
Application Logging in the 21st century - 2014.key
JIP Pipeline System Introduction
Linux networking
DevOps with Fabric
Ad

Similar to Value protocols and codables (20)

PDF
Introduction to clojure
PPT
devLink - What's New in C# 4?
PDF
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
PDF
Clojure: Simple By Design
PDF
Bay Area Apache Spark ™ Meetup: Upcoming Apache Spark 4.0.0 Release
PPTX
.NET Foundation, Future of .NET and C#
PPTX
Building a friendly .NET SDK to connect to Space
PPTX
A Replay Approach to Software Validation
PPTX
PDC Video on C# 4.0 Futures
PPTX
Codable routing
PPT
An Overview Of Python With Functional Programming
PDF
Clean Code 2
PDF
Who killed object oriented design?
PDF
Scalding big ADta
PPT
A Life of breakpoint
PDF
Asynchronous IO in Rust - Enrico Risa - Codemotion Rome 2017
PPT
Lo Mejor Del Pdc2008 El Futrode C#
PPTX
Track c-High speed transaction-based hw-sw coverification -eve
KEY
iPhone Development Intro
PPTX
Event-driven IO server-side JavaScript environment based on V8 Engine
Introduction to clojure
devLink - What's New in C# 4?
"ClojureScript journey: from little script, to CLI program, to AWS Lambda fun...
Clojure: Simple By Design
Bay Area Apache Spark ™ Meetup: Upcoming Apache Spark 4.0.0 Release
.NET Foundation, Future of .NET and C#
Building a friendly .NET SDK to connect to Space
A Replay Approach to Software Validation
PDC Video on C# 4.0 Futures
Codable routing
An Overview Of Python With Functional Programming
Clean Code 2
Who killed object oriented design?
Scalding big ADta
A Life of breakpoint
Asynchronous IO in Rust - Enrico Risa - Codemotion Rome 2017
Lo Mejor Del Pdc2008 El Futrode C#
Track c-High speed transaction-based hw-sw coverification -eve
iPhone Development Intro
Event-driven IO server-side JavaScript environment based on V8 Engine
Ad

Recently uploaded (20)

PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
Understanding Forklifts - TECH EHS Solution
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Digital Systems & Binary Numbers (comprehensive )
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
history of c programming in notes for students .pptx
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PDF
Nekopoi APK 2025 free lastest update
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Transform Your Business with a Software ERP System
PDF
medical staffing services at VALiNTRY
PPTX
L1 - Introduction to python Backend.pptx
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Digital Strategies for Manufacturing Companies
PDF
Design an Analysis of Algorithms II-SECS-1021-03
wealthsignaloriginal-com-DS-text-... (1).pdf
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Understanding Forklifts - TECH EHS Solution
Odoo POS Development Services by CandidRoot Solutions
Digital Systems & Binary Numbers (comprehensive )
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Navsoft: AI-Powered Business Solutions & Custom Software Development
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
history of c programming in notes for students .pptx
Odoo Companies in India – Driving Business Transformation.pdf
Which alternative to Crystal Reports is best for small or large businesses.pdf
Why Generative AI is the Future of Content, Code & Creativity?
Nekopoi APK 2025 free lastest update
Softaken Excel to vCard Converter Software.pdf
Transform Your Business with a Software ERP System
medical staffing services at VALiNTRY
L1 - Introduction to python Backend.pptx
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Digital Strategies for Manufacturing Companies
Design an Analysis of Algorithms II-SECS-1021-03

Value protocols and codables

  • 1. Values, Protocols and Codables Florent Vilmart
  • 3. Disclaimer I have no idea what I’m doin’
  • 5. An API, to build API’s
  • 6. Parse SDK iOS/OSX Parse Swift Runtime Dynamism Compile-time Dynamism Object Oriented PoP NSObject struct async (Bolts) sync iOS/macOS/tvOS/watchOS Just Swift Objective-C vs Swift The past, the present…
  • 7. o
  • 9. An REST API is a contract … but …
  • 10. Object Data Data Object Serialize ⚠️💣 Send Responds 💣 ⚠️ Deserialize 💥 💥 Any API Client… Till today
  • 12. T: Encodable URLSession U: Decodable Great spot to fake / mock your server! Or datastore Or anything really… REST abstract
  • 13. Encodable / Decodable Strings, Numbers, enum, Arrays, Dictionaries (of Codables) … Objects / Structs with only Codable’s Custom *(through protocol conformance) Implement CodingKeys for encoding subset Composability Codable’s
  • 17. Protocols protocol Saving: Encodable { associatedtype SavingType func save(options: Options) throws -> SavingType func save() throws -> SavingType } protocol Fetching: Decodable { associatedtype FetchingType func fetch(options: Options) throws -> FetchingType func fetch() throws -> FetchingType }
  • 18. ObjectType Protocol public protocol ObjectType: Fetching, Saving { static var className: String { get } var objectId: String? { get set } var createdAt: Date? { get set } var updatedAt: Date? { get set } var ACL: ACL? { get set } } public extension ObjectType { public func save(options: Options = []) throws -> Self { return try Command<Self, SaveResponse>(method: .POST, path: object.endpoint, params: nil, body: object) .execute(options: options) .map { $0.apply(self) } } }
  • 19. Extensible extension Saving { typealias Callback = (Self.SavingType?, Error?) -> Void func save(options: API.Options = [], callback: @escaping Callback) { runAsync(options: options, function: self.save, callback: callback) } }
  • 20. runAsync let queue = DispatchQueue(label: "org.parse-community.ParseSwift.async") private func runAsync<T>(options: API.Options, function: @escaping (API.Options) throws -> T?, callback: @escaping (T?, Error?) -> Void) { queue.async { do { callback(try function(options), nil) } catch let e { callback(nil, e) } } }
  • 21. As a SDK user struct GameScore: ParseSwift.ObjectType { //: Those are required for ObjectType var objectId: String? var createdAt: Date? var updatedAt: Date? var ACL: ACL? //: Your own properties var score: Int //: a custom initializer init(score: Int) { self.score = score } } let score = GameScore(score: 10) guard let savedScore = try? score.save() else { fatalError() }
  • 22. public struct Command<T, U>: Encodable where T: Encodable, U: Decodable { let method: Method let path: Endpoint let params: [String: String?]? let body: T? public func data() throws -> Data? { return try JSONEncoder().encode(body) } public func execute(options: Options) throws -> Response<U> { return try options.executor.execute(command: self, options: options) } internal func decode(responseData: Data) throws -> Response<U> { do { return Response(object: try Decoder.json.decode(U.self, from: responseData)) } catch _ { throw try Decoder.json.decode(ParseError.self, from: responseData) } } } Command
  • 23. Commands extension Command where T: ObjectType { // MARK: custom encoding func data() throws -> Data? { return try API.Encoder.parse.encode(body) } } struct Response<T> where T: Decodable { let object: T func map<U>(_ mapper: (T) throws -> U) rethrows -> U { return try mapper(object) } }
  • 24. Executor extension API.Command { internal func getURLRequest(options: API.Options) throws -> URLRequest { /* build a URLRequest from the command */ } } extension URLSession: APIExecutor { public func execute<T, U>(command: API.Command<T, U>, options: API.Options) throws -> API.Response<U> { let urlRequest = try command.getURLRequest(options: options) let responseData = try self.syncDataTask(with: urlRequest) return try command.decode(responseData: responseData) } }
  • 26. A Quick Word on sync code no async is the best async extension URLSession { internal func syncDataTask(with request: URLRequest) throws -> Data { let semaphore = DispatchSemaphore(value: 0) var data: Data? var error: Error? var response: URLResponse? dataTask(with: request) { (responseData, urlResponse, responseError) in data = responseData; error = responseError; response = urlResponse; semaphore.signal() }.resume() semaphore.wait() guard let responseData = data else { guard let error = error else { // no err no res? throw NSError(domain: "unknown", code: -1, userInfo: ["response": response!]) } throw error } return responseData } } 🤦♀️
  • 28. Values, Protocols and Codables Florent Vilmart

Editor's Notes

  • #6: - Many of you may have already used, it - Schema less
  • #7: Unlike other SDK’s like FB/Github, schemas are not defined by us We provide the facility to create custom schemas Which makes the whole shebang quite more difficult. But, we know response types, error codes, bare minimal object (objectId, createdAt… , errors, responses)
  • #19: start with those 2 fundamental protocols Becaust that’s the base (for files and object and Pointers etc…) Provides the abstraction necessary. Could add Destroying but … Easily extensible
  • #24: - Encodable, because batch API 🤓 - params is [String: String?]? 😪 (QueryStringEncoder?) - tied to HTTP semantics 🤷🏻‍♀️ - executor in options func data() throws -> Data? Response (simple wrapper) I cannot subclass, butt……
  • #27: not a big fan of deps of deps of deps taking a side, is usually hindering adoption Who’S better? Rx, Reactive, Bolts, PromiseKit… Don’t care much