Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift Summit 2016 - Interfacing with GraphQL in...

Avatar for Sommer Panage Sommer Panage
November 07, 2016

Swift Summit 2016 - Interfacing with GraphQL in Swift

A look at GraphQL on mobile. Why is GraphQL so mobile-friendly? How does it work with Swift?

Avatar for Sommer Panage

Sommer Panage

November 07, 2016
Tweet

More Decks by Sommer Panage

Other Decks in Technology

Transcript

  1. Interfacing with GraphQL in Swift Sommer Panage • @sommer 1

    — Sommer Panage • @sommer • Swift Summit 2016
  2. The GraphQL Schema type User { name: String! id: Int!

    email: String twitter: String } 4 — Sommer Panage • @sommer • Swift Summit 2016
  3. I write a query like... { user(id: 1) { name

    email twitter } } And send it to my GraphQL endpoint https://mybackend.com/graphql 6 — Sommer Panage • @sommer • Swift Summit 2016
  4. And I get back a JSON response like... { "data":

    { "name": "Sommer Panage", "email": "sommer@panage.org", "twitter": "@sommer" } } 7 — Sommer Panage • @sommer • Swift Summit 2016
  5. Why is GraphQL such a big deal for mobile? 8

    — Sommer Panage • @sommer • Swift Summit 2016
  6. In a REST world, we'd hit this endpoint: http://swapi.co/api/people/1/ And

    we'd get back... 10 — Sommer Panage • @sommer • Swift Summit 2016
  7. { "name": "Luke Skywalker", "height": "1.72 m", "mass": "77 Kg",

    "hair_color": "Blond", "skin_color": "Caucasian", "eye_color": "Blue", "birth_year": "19 BBY", "gender": "Male", "homeworld": "http://swapi.co/api/planets/1/", "films": [ "http://swapi.co/api/films/1/", "http://swapi.co/api/films/2/", "http://swapi.co/api/films/3/" ], "species": [ "http://swapi.co/api/species/1/" ], "vehicles": [ "http://swapi.co/api/vehicles/14/", "http://swapi.co/api/vehicles/30/" ], "starships": [ "http://swapi.co/api/starships/12/", "http://swapi.co/api/starships/22/" ], "created": "2014-12-09T13:50:51.644000Z", "edited": "2014-12-10T13:52:43.172000Z", "url": "http://swapi.co/api/people/1/", "image_url": "http://static.srcdn.com/wp-content/uploads/luke-skywalker-star-wars-a-new-hope.jpg" } 11 — Sommer Panage • @sommer • Swift Summit 2016
  8. { "name": "X-wing", "model": "T-65 X-wing", "manufacturer": "Incom Corporation", "cost_in_credits":

    "149999", "length": "12.5", "max_atmosphering_speed": "1050", "crew": "1", "passengers": "0", "cargo_capacity": "110", "consumables": "1 week", "hyperdrive_rating": "1.0", "MGLT": "100", "starship_class": "Starfighter", "pilots": [ "http://swapi.co/api/people/1/", "http://swapi.co/api/people/9/", "http://swapi.co/api/people/18/", "http://swapi.co/api/people/19/" ], "films": [ "http://swapi.co/api/films/3/", "http://swapi.co/api/films/2/", "http://swapi.co/api/films/1/" ], "created": "2014-12-12T11:19:05.340000Z", "edited": "2014-12-22T17:35:44.491233Z", "url": "http://swapi.co/api/starships/12/" } 13 — Sommer Panage • @sommer • Swift Summit 2016
  9. { "name": "Imperial shuttle", "model": "Lambda-class T-4a shuttle", "manufacturer": "Sienar

    Fleet Systems", "cost_in_credits": "240000", "length": "20", "max_atmosphering_speed": "850", "crew": "6", "passengers": "20", "cargo_capacity": "80000", "consumables": "2 months", "hyperdrive_rating": "1.0", "MGLT": "50", "starship_class": "Armed government transport", "pilots": [ "http://swapi.co/api/people/1/", "http://swapi.co/api/people/13/", "http://swapi.co/api/people/14/" ], "films": [ "http://swapi.co/api/films/3/", "http://swapi.co/api/films/2/" ], "created": "2014-12-15T13:04:47.235000Z", "edited": "2014-12-22T17:35:44.795405Z", "url": "http://swapi.co/api/starships/22/" } 14 — Sommer Panage • @sommer • Swift Summit 2016
  10. That's 3 calls and a whole lot of data for

    1 little VC 15 — Sommer Panage • @sommer • Swift Summit 2016
  11. Now in GraphQL, instead we'd write the following query: {

    person(personID: 1) { name, height, mass, hairColor, eyeColor, imageURL, starshipConnection { edges { node { name } } } } } 16 — Sommer Panage • @sommer • Swift Summit 2016
  12. And, I'd get back exactly what I wanted! { "data":

    { "person": { "name": "Luke Skywalker", "height": 172, "mass": 77, "hairColor": "blond", "eyeColor": "blue", "imageURL": "http://static.srcdn.com/wp-content/uploads/luke-skywalker-star-wars-a-new-hope.jpg", "starshipConnection": { "edges": [ { "node": { "name": "X-wing" } }, { "node": { "name": "Imperial shuttle" } } ] } } } } 17 — Sommer Panage • @sommer • Swift Summit 2016
  13. So, why is GraphQL such a big deal for mobile?

    1. Ask and ye shall receive! 2. Fewer round trips! 3. Less client logic around data! 18 — Sommer Panage • @sommer • Swift Summit 2016
  14. Our Star Wars Character model struct SWCharacter { let name:

    String let heightInCm: Int let massInKg: Int let hairColorDescriptor: String let skinColorDescriptor: String let eyeColorDescriptor: String let birthYear: StarWarsUniverse.Year let gender: StarWarsUniverse.Gender let homeworld: StarWarsUniverse.Planet let films: [SWFilm] let species: [StarWarsUniverse.Species] let vehicles: [StarWarsUniverse.Vehicle] let starships: [StarWarsUniverse.Starship] let imageURL: URL? } 20 — Sommer Panage • @sommer • Swift Summit 2016
  15. Our Star Wars Character model struct SWCharacter { let name:

    String? let heightInCm: Int? let massInKg: Int? let hairColorDescriptor: String? let skinColorDescriptor: String? let eyeColorDescriptor: String let birthYear: StarWarsUniverse.Year? let gender: StarWarsUniverse.Gender? let homeworld: StarWarsUniverse.Planet? let films: [SWFilm]? let species: [StarWarsUniverse.Species]? let vehicles: [StarWarsUniverse.Vehicle]? let starships: [StarWarsUniverse.Starship]? let imageURL: URL? } 21 — Sommer Panage • @sommer • Swift Summit 2016
  16. Swift, No!!!! struct SWCharacter { let name: String? let heightInCm:

    Int? let massInKg: Int? let hairColorDescriptor: String? let skinColorDescriptor: String? let eyeColorDescriptor: String let birthYear: StarWarsUniverse.Year? let gender: StarWarsUniverse.Gender? let homeworld: StarWarsUniverse.Planet? let films: [SWFilm]? let species: [StarWarsUniverse.Species]? let vehicles: [StarWarsUniverse.Vehicle]? let starships: [StarWarsUniverse.Starship]? let imageURL: URL? } 22 — Sommer Panage • @sommer • Swift Summit 2016
  17. Let's model the data how we want it, not how

    it is → 1 View Controller → 1 Query → 1 Data Model 24 — Sommer Panage • @sommer • Swift Summit 2016
  18. query AllCharacters { allPeople { edges { node { id

    name homeworld { name } } } } } 26 — Sommer Panage • @sommer • Swift Summit 2016
  19. struct AllCharactersData { let people: [Person] struct Person { let

    id: String let name: String let homeworld: Homeworld struct Homeworld { let name: String } } } 27 — Sommer Panage • @sommer • Swift Summit 2016
  20. query Character($id: ID) { person (id: $id) { id height,

    mass, hairColor, eyeColor, imageURL, starshipConnection { edges { node { name } } } } } 28 — Sommer Panage • @sommer • Swift Summit 2016
  21. struct CharacterData { struct Person { let id: String let

    height: Int let mass: Int let hairColor: String let eyeColor: String let imageURL: URL? let starshipConnect: [Starship] struct Starship { let name: String } } } 29 — Sommer Panage • @sommer • Swift Summit 2016
  22. By having query / view- data based models, we no

    longer need optionals everywhere! 30 — Sommer Panage • @sommer • Swift Summit 2016
  23. But our parsing code still looks like... let parsedData =

    try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] self.id = parsedData["id"] as! String self.name = parsedData["name"] as! String self.homeworld = Homeworld(dict: parsedData["homeworld"] as! [String : Any]) Ugh! 31 — Sommer Panage • @sommer • Swift Summit 2016
  24. Apollo's iOS GraphQL Client for Swift → Compile-time safety →

    Inline validation errors for GraphQL → No wasted cycles on query-gen 34 — Sommer Panage • @sommer • Swift Summit 2016
  25. Versioning → "Version-Free" → Easy to test for backwards compatability

    36 — Sommer Panage • @sommer • Swift Summit 2016
  26. Aren't you supposed to use GraphQL with React Native? 40

    — Sommer Panage • @sommer • Swift Summit 2016
  27. GraphQL + Swift -> GraphQL shines on mobile -> Swift

    gives us types and compile time safety -> React Native is new and exciting, but that comes with challenges too 41 — Sommer Panage • @sommer • Swift Summit 2016
  28. Pros to GraphQL + Swift → Fewer requests for data

    → Getting the exact data you need → Code gen -> no janky parsing code → Models that are reflective of your views → A strongly typed backend schema 43 — Sommer Panage • @sommer • Swift Summit 2016
  29. Cons to GraphQL + Swift → Not a lot of

    tooling yet → Best practices still emerging → Poorly defined schema becomes a big client problem → Not as good for endpoints requiring heavy logic 44 — Sommer Panage • @sommer • Swift Summit 2016
  30. Check out → Apollo iOS Client: Documentation and info on

    Apollo's awesome Swift iOS GraphQL client → 5 benefits of static GraphQL Queries: Blog post from Apollo → Bringing GraphQL to iOS: Blog post from Apollo → GraphQL First: A better way to build modern apps: Blog post from Apollo 46 — Sommer Panage • @sommer • Swift Summit 2016
  31. Check out...con’t → GraphQL for mobile: Blog post from Artsy

    → Relay: Thinking in GraphQL: Post from FB on Caching 47 — Sommer Panage • @sommer • Swift Summit 2016
  32. Thank you!! Come ask me questions about GraphQL + Swift

    or about Accessibility! 48 — Sommer Panage • @sommer • Swift Summit 2016
  33. Credits Images GediminasTurbo Baltaduonis, Danil Polshin, Apple, Facebook, Apollo, Lucasfilm

    General Chorus Fitness, Apollo, Facebook 49 — Sommer Panage • @sommer • Swift Summit 2016