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

GraphQL + iOS

GraphQL + iOS

Talk at 12° CocoaHeads Fortaleza

Bruno Macabeus

November 23, 2017
Tweet

More Decks by Bruno Macabeus

Other Decks in Technology

Transcript

  1. My name is Bruno Macabeus I’m student at IFCE &

    Apple Developer Academy github.com/macabeus
  2. You are making an app to many devices… … and

    each device have a very different UI!
  3. You are making an app to many devices… … and

    each device have a very different UI!
  4. Title Short description Title Short description Title Title Title Title

    /posts title description userId /users/:id name age imageUrl Overfetch and Underfetch Title Title Title
  5. /posts?include=title,userId title description userId /users/:id?include=imageUrl name age imageUrl Overfetch and

    Underfetch Title Short description Title Short description Title Title Title Title Title Title Title
  6. /posts?include=title,user.imageUrl title description userId user.imageUrl Overfetch and Underfetch Title Short

    description Title Short description Title Title Title Title Title Title Title
  7. /posts?include=title,description,user.avatar,data &filter=notRead&sort=newest&description=long title description (now is deprecated!) shortDescription userId user.avatar

    data Notifications of deprecated Title Short description Title Short description Title Title Title Title Title Title Title
  8. Yes! Because with GraphQL you can be more expressive in

    your query! query GetPosts() { posts { title description user { imageUrl } } }
  9. query GetPosts() { posts { title description user { imageUrl

    } } } It’s a sample of GraphQL language
  10. { "data": { "posts": [ { "user": { "name": "Bruno

    Macabeus” }, "title": “My amazing post!”, "body": “Loren ipsun" }, { "user": { "name": "Ryan Swapp” }, "title": “My blog post", "body": “Foo bar baz” } ] } } Server can respond with JSON or other format
  11. Query Mutation Subscription query FetchPosts() { posts { id title

    body user { name } } } Query is an operation to get data from the server. For example: a list of posts. Operations
  12. Query Mutation Subscription mutation CreatePost($title: String!, $body: String!) { createPost(title:

    $title, body: $body) { id } } Mutation is an operation to perform side-effects on the underlying data system. For example: create a new post, or update one. Operations
  13. Query Mutation Subscription subscription NewComment($postId: Int!) { newComment(roomId: $postId) {

    sender text } } Subscription is an operation to start a new event stream. For example: check for new comments in a post in realtime. Operations
  14. query FetchPokemonBattle() { pokemonBattle { id pokemonLeft { id name

    level hp }, pokemonRight { id name level hp } } } Fragments
  15. query FetchPokemonBattle() { pokemonBattle() { id pokemonLeft { ...PokemonDetail },

    pokemonRight { ...PokemonDetail } } } fragment PokemonDetail on Pokemon { id name level hp } Fragments allow the reuse of common repeated selections of fields. Fragments query FetchPokemonBattle() { pokemonBattle { id pokemonLeft { id name level hp }, pokemonRight { id name level hp } } }
  16. I wrote a server using the Elixir language, a functional

    language that run in the BEAM virtual machine, the same virtual machine of Erlang. I chose this language because it’s great for applications that need a lot parallelism, such as a server. And, to create the server-side code for GraphQL, I used the Absinthe package.
  17. I wrote a server using the Elixir language, a functional

    language that run in virtual machine BEAM, the same virtual machine of Erlang. I chose this language because is great for applications that need a lot parallelism, such a server. And, to create the server-side code about GraphQL, I used using the package Absinthe. github.com/macabeus/graphql-example
  18. We could use the Apollo GraphQL tool for iOS Apollo

    is a community building flexible open source tools for GraphQL.
  19. We could use the Apollo GraphQL tool for iOS Apollo

    is a community building flexible open source tools for GraphQL. Great features for iOS package: Strongly-typed & caching
  20. Initialize the ApolloClient somewhere, for example, AppDelegate.swift Configuration 5/5 import

    Apollo let graphlQLEndpointURL = "http://localhost:4000/api" let apollo = ApolloClient(url: URL(string: graphlQLEndpointURL)!)
  21. Coding class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool)

    { fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? in return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } }
  22. class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool) {

    fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? i return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } query GetPosts($userId: Int) { posts(userId: $userId) { id title body countLikes liked user { name } } }
  23. class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool) {

    fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? i return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } query GetPosts($userId: Int) { posts(userId: $userId) { id title body countLikes liked user { name } } }
  24. class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool) {

    fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? i return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } query GetPosts($userId: Int) { posts(userId: $userId) { id title body countLikes liked user { name } } }
  25. class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool) {

    fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? i return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } query GetPosts($userId: Int) { posts(userId: $userId) { id title body countLikes liked user { name } } }
  26. class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool) {

    fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? i return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } query GetPosts($userId: Int) { posts(userId: $userId) { id title body countLikes liked user { name } } } “fetch" if is query “perform" if is mutation
  27. class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool) {

    fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? i return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } query GetPosts($userId: Int) { posts(userId: $userId) { id title body countLikes liked user { name } } }
  28. class TableViewControllerPosts: UITableViewController { override func viewDidAppear(_ animated: Bool) {

    fetchPosts() } func fetchPosts() { let query = GetPostsQuery(userId: 1) apollo.fetch(query: query) { result, error in // Check for errors if let error = error { print(error) return } guard let posts = result?.data?.posts else { print("Without data!") return } // Parse self.tableDataSource = posts.flatMap { post -> Post? i return Post( id: post?.id, name: post?.title, body: post?.body, countLikes: post?.countLikes, liked: post?.liked, author: User( name: post?.user?.name ) ) } } query GetPosts($userId: Int) { posts(userId: $userId) { id title body countLikes liked user { name } } }
  29. GraphQL is designed to build client applications. Depending on the

    project needs, maybe is better use Rest instead of GraphQL. Or, you could use both, Rest and GraphQL, in same project. One situation that GraphQL is good is when you need a highly query-able API.
  30. { page(url:"http://news.ycombinator.com") { items: query(selector:"tr.athing") { rank: text(selector:"td span.rank") title:

    text(selector:"td.title a") sitebit: text(selector:"span.comhead a") url: attr(selector:"td.title a", name:"href") attrs: next { score: text(selector:"span.score") user: text(selector:"a:eq(0)") comments: text(selector:"a:eq(2)") } } } } GDOM GraphQL-like syntax to create webcrawlers
  31. { brCharacters(func: eq(name@en, "Blade Runner")) { name@en initial_release_date starring {

    performance.actor { name@en # actor name } performance.character { name@en # character name } } } } Distributed graph database , that has a query language inspired by GraphQL, called GraphQL+-