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

Swift Summit 2016 - Interfacing with GraphQL in Swift

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?

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": "[email protected]", "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