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

Digging In To The Apollo iOS SDK - GraphQL Summ...

Digging In To The Apollo iOS SDK - GraphQL Summit, San Francisco, October 2019

Learn about the what and why of recent updates to ApolloGraphQL’s Swift iOS SDK, including updates to code generation, get a few concepts on the iOS side more clearly explained, and learn about where we're going with the iOS SDK!

(Will link to video as soon as it's up!)

Ellen Shapiro

October 31, 2019
Tweet

More Decks by Ellen Shapiro

Other Decks in Technology

Transcript

  1. ⚒ Digging in to the Apollo iOS SDK GraphQL Summit

    | San Francisco, CA | October 2019 by Ellen Shapiro | @DesignatedNerd | apollographql.com
  2. !

  3. !

  4. !

  5. !

  6. !

  7. !

  8. !

  9. ! "

  10. !

  11. !

  12. !

  13. !

  14. Adding an iOS library, normally 1. Install dependency using one

    of: → pod install → carthage checkout → swift build
  15. Adding an iOS library, normally 1. Install dependency using one

    of: → pod install → carthage checkout → swift build 2. Use library.
  16. Codegen needs to know → Where is the schema file?

    → Where are the query files? → Where should generated code be output?
  17. Codegen needs to know → Where is the schema file?

    → Where are the query files? → Where should generated code be output? → Any other options which are available from the codegen library
  18. Adding apollo-ios before 1. Install dependency 2. Add build script

    3. npm install apollo 4. brew install npm
  19. Adding apollo-ios before 1. Install dependency 2. Add build script

    3. npm install apollo 4. brew install npm 5. Google how to install Homebrew
  20. Adding apollo-ios before 1. Install dependency 2. Add build script

    3. npm install apollo 4. brew install npm 5. Google how to install Homebrew 6.
  21. Adding apollo-ios before 1. Install dependency 2. Add build script

    3. npm install apollo 4. Wait, what version of the CLI is this?
  22. Adding apollo-ios before 1. Install dependency 2. Add build script

    3. npm install apollo 4. Wait, what version of the CLI is this? 5. How do I tell what's installed globally vs locally?
  23. Adding apollo-ios before 1. Install dependency 2. Add build script

    3. npm install apollo 4. Wait, what version of the CLI is this? 5. How do I tell what's installed globally vs locally? 6.
  24. !

  25. !

  26. Adding apollo-ios now 1. Install dependency 2. Add build script

    that calls run-bundled-codegen.sh 3. Apollo downloads and unzips the correct version of the CLI, all dependencies, and a node runtime.
  27. Adding apollo-ios now 1. Install dependency 2. Add build script

    that calls run-bundled-codegen.sh 3. Apollo downloads and unzips the correct version of the CLI, all dependencies, and a node runtime. 4. Use library.
  28. !

  29. ReviewInput(stars: 5) // { "stars": 5 } ReviewInput(stars: 2, commentary:

    "Needs more ewoks") // { "stars": 2, "commentary": "Needs more ewoks" } ReviewInput(stars: 3, commentary: nil) // { "stars": 3 } ReviewInput(stars: 4, commentary: .some(nil)) // { "stars": 4, "commentary": null }
  30. ReviewInput(stars: 5) // { "stars": 5 } ReviewInput(stars: 2, commentary:

    "Needs more ewoks") // { "stars": 2, "commentary": "Needs more ewoks" } ReviewInput(stars: 3, commentary: nil) // { "stars": 3 } ReviewInput(stars: 4, commentary: .some(nil)) // { "stars": 4, "commentary": null }
  31. ReviewInput(stars: 5) // { "stars": 5 } ReviewInput(stars: 2, commentary:

    "Needs more ewoks") // { "stars": 2, "commentary": "Needs more ewoks" } ReviewInput(stars: 3, commentary: nil) // { "stars": 3 } ReviewInput(stars: 4, commentary: .some(nil)) // { "stars": 4, "commentary": null }
  32. ReviewInput(stars: 5) // { "stars": 5 } ReviewInput(stars: 2, commentary:

    "Needs more ewoks") // { "stars": 2, "commentary": "Needs more ewoks" } ReviewInput(stars: 3, commentary: nil) // { "stars": 3 } ReviewInput(stars: 4, commentary: .some(nil)) // { "stars": 4, "commentary": null }
  33. ReviewInput(stars: 5) // { "stars": 5 } ReviewInput(stars: 2, commentary:

    "Needs more ewoks") // { "stars": 2, "commentary": "Needs more ewoks" } ReviewInput(stars: 3, commentary: nil) // { "stars": 3 } ReviewInput(stars: 4, commentary: .some(nil)) // { "stars": 4, "commentary": null }
  34. ReviewInput(stars: 5) // { "stars": 5 } ReviewInput(stars: 2, commentary:

    "Needs more ewoks") // { "stars": 2, "commentary": "Needs more ewoks" } ReviewInput(stars: 3, commentary: nil) // { "stars": 3 } ReviewInput(stars: 4, commentary: .some(nil)) // { "stars": 4, "commentary": null }
  35. apollo.cacheKeyForObject = { guard let id = $0["id"], let typename

    = $0["__typename"] else { // Not enough info to uniquely identify the object return nil } return [id, typename] }
  36. apollo.cacheKeyForObject = { guard let id = $0["id"], let typename

    = $0["__typename"] else { // Not enough info to uniquely identify the object return nil } return [id, typename] }
  37. apollo.cacheKeyForObject = { guard let id = $0["id"] as? String,

    let typename = $0["__typename"] as? String else { // Not enough info to uniquely identify the object return nil } return id + typename }
  38. apollo.cacheKeyForObject = { guard let isbn = $0["isbn"], let uuid

    = $0["uuid"] else { // Not enough info to uniquely identify the object return nil } return [isbn, uuid] }
  39. Episode Stars Commentary Empire ̣̣̣̣̣ This movie rocks! New Hope

    ̣̣̣̣̤ This is the first movie, why is it episode 4?
  40. Episode Stars Commentary Empire ̣̣̣̣̣ This movie rocks! New Hope

    ̣̣̣̣̤ This is the first movie, why is it episode 4? Jedi ̣̣̤̤̤ Needs more ewoks.
  41. client.subscribe(subscription: ReviewAddedSubscription()) { result in switch result { case .success(let

    graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } }
  42. client.subscribe(subscription: ReviewAddedSubscription()) { result in switch result { case .success(let

    graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } }
  43. client.subscribe(subscription: ReviewAddedSubscription()) { result in switch result { case .success(let

    graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } }
  44. client.subscribe(subscription: ReviewAddedSubscription()) { result in switch result { case .success(let

    graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } }
  45. var subscription: Cancellable? self.subscription = client .subscribe(subscription: ReviewAddedSubscription()) { [weak

    self] result in guard let self = self else { return } switch result { case .success(let graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } } dealloc { self.subscription?.cancel() }
  46. var subscription: Cancellable? self.subscription = client .subscribe(subscription: ReviewAddedSubscription()) { [weak

    self] result in guard let self = self else { return } switch result { case .success(let graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } } dealloc { self.subscription?.cancel() }
  47. var subscription: Cancellable? self.subscription = client .subscribe(subscription: ReviewAddedSubscription()) { [weak

    self] result in guard let self = self else { return } switch result { case .success(let graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } } dealloc { self.subscription?.cancel() }
  48. var subscription: Cancellable? self.subscription = client .subscribe(subscription: ReviewAddedSubscription()) { [weak

    self] result in guard let self = self else { return } switch result { case .success(let graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } } dealloc { self.subscription?.cancel() }
  49. var subscription: Cancellable? self.subscription = client .subscribe(subscription: ReviewAddedSubscription()) { [weak

    self] result in guard let self = self else { return } switch result { case .success(let graphQLResult): if let review = graphQLResult.data?.reviewAdded { // Handle review being added. } if let errors = graphQLResult.errors { // Handle error from the server } case .failure(let error): // Handle networking error } } dealloc { self.subscription?.cancel() }
  50. → "Poor tutorial support" → "Better documentation." → "More documentation

    on uploading techniques, caching, and background communication."
  51. → "Poor tutorial support" → "Better documentation." → "More documentation

    on uploading techniques, caching, and background communication." → "Expand documentation on SQLiteNormalizedCache"
  52. As part of Swift Codegen: → Codable conformance → Equatable/Hashable

    conformance → xcfilelists of inputs and outputs
  53. As part of Swift Codegen: → Codable conformance → Equatable/Hashable

    conformance → xcfilelists of inputs and outputs → Fragments as protocols
  54. As part of Swift Codegen: → Codable conformance → Equatable/Hashable

    conformance → xcfilelists of inputs and outputs → Fragments as protocols → Get rid of double-optionals for clearer type*
  55. As part of Swift Codegen: → Codable conformance → Equatable/Hashable

    conformance → xcfilelists of inputs and outputs → Fragments as protocols → Get rid of double-optionals for clearer type* → Identifiable auto-conformance*
  56. As part of Swift Codegen: → Codable conformance → Equatable/Hashable

    conformance → xcfilelists of inputs and outputs → Fragments as protocols → Get rid of double-optionals for clearer type* → Identifiable auto-conformance* * - I hope
  57. !

  58. Obligatory Summary Slide → Check out updated build setup, it's

    way easier → Docs have been significantly improved
  59. Obligatory Summary Slide → Check out updated build setup, it's

    way easier → Docs have been significantly improved → New sample app and tutorial coming soon!
  60. Obligatory Summary Slide → Check out updated build setup, it's

    way easier → Docs have been significantly improved → New sample app and tutorial coming soon! → Swift Codegen is coming
  61. Obligatory Summary Slide → Check out updated build setup, it's

    way easier → Docs have been significantly improved → New sample app and tutorial coming soon! → Swift Codegen is coming → Check out the ROADMAP.md
  62. Obligatory Summary Slide → Check out updated build setup, it's

    way easier → Docs have been significantly improved → New sample app and tutorial coming soon! → Swift Codegen is coming → Check out the ROADMAP.md → Contribute!