$30 off During Our Annual Pro Sale. View Details »

結婚式を支えた技術 Firebaseを活用したサーバレスiOSアプリケーション開発

Motoki Narita
September 17, 2017

結婚式を支えた技術 Firebaseを活用したサーバレスiOSアプリケーション開発

Motoki Narita

September 17, 2017
Tweet

More Decks by Motoki Narita

Other Decks in Technology

Transcript

  1. ݁ࠗࣜΛࢧٕ͑ͨज़
    'JSFCBTFΛ׆༻ͨ͠αʔόϨεJ04ΞϓϦέʔγϣϯ։ൃ
    J04%$+BQBO %BZ 5SBDL"ʙ
    !NPUPLJFF

    View Slide

  2. "CPVUNF
    w HJUIVC UXJUUFS RJJUBNPUPLJFF
    w J04%$+BQBOελοϑ
    w גࣜձࣾι΢κ΢ͰϝϧΧϦΧ΢ϧͷ։ൃΛ͍ͯ͠ΔJ04ΤϯδχΞ
    w ι΢κ΢͸ϝϧΧϦʹଓ͘৽ͨͳαʔϏεΛ࡞ΔձࣾͰ͢
    w γΣΞαΠΫϧαʔϏεNFSDIBSJ४උத
    w ϋʔυ΢ΣΞ΋Ͱ͖ΔPSڵຯ௡ʑͳJ04ΤϯδχΞɺେืूத

    View Slide

  3. View Slide

  4. ͖ΐ͏࿩͢͜ͱ

    View Slide

  5. ڈ೥݁ࠗࣜΛڍ͛ͨͱ͖ʹɺ

    ઐ༻ͷJ04ΞϓϦΛ։ൃ͓ͨ͠࿩

    View Slide

  6. ݁ࠗࣜ)BDL

    View Slide

  7. ͳͥ։ൃͨ͠ͷ͔ʁ

    View Slide

  8. ղܾ͢΂͖՝୊͕͔͋ͬͨΒ

    View Slide

  9. ղܾ͍ͨ͠՝୊
    w ݁ࠗࣜͷΧϝϥϚϯ͸େม͕͓͔͔ۚΔ
    w ΧϝϥϚϯʹݶΒͣશൠతʹߴ͍
    w ݁ࠗࣜͰΈΜͳεϚϗͰࣸਅࡱͬͯΔ
    w Ͱ΋ͳ͔ͥૹΒΕͳ͍ʢ࣮͸ࣗ෼͚ͩૹ͍ͬͯͳ͍͚͔ͩ΋ʣ

    View Slide

  10. ղܾ͢΂͖՝୊
    w ݁ࠗࣜͷΧϝϥϚϯ͸େม͕͓͔͔ۚΔ
    w ΧϝϥϚϯʹݶΒͣશൠతʹߴ͍
    w ݁ࠗࣜͰΈΜͳεϚϗͰࣸਅࡱͬͯΔ
    w Ͱ΋ͳ͔ͥૹΒΕͳ͍ʢ࣮͸ࣗ෼͚ͩૹ͍ͬͯͳ͍͚͔ͩ΋ʣ

    View Slide

  11. ࣸਅΞοϓϩʔυ·ͰͷಓͷΓ

    View Slide

  12. ࡱΔ
    ͳΜΒ͔ͷ࡞ۀ
    Ξοϓϩʔυ

    View Slide

  13. ͳΜΒ͔ͷ࡞ۀ͕๛෋
    w ࡱΔˠͳΜΒ͔ͷ࡞ۀˠΞοϓϩʔυ
    w ͳΜΒ͔ͷ࡞ۀ͕໘౗Ͱ͋ΔʢΞϓϦ։͍ͯɺࣸਅબΜͰɺૹΔʣ
    w ͳΜΒ͔ͷ࡞ۀͷखஈ͕ͨ͘͞Μ͋ΔʢΞϓϦ͍ͬͺ͍ʣ
    w -*/& 'BDFCPPL.FTTFOHFS ϓϦϯτΞ΢τ &NBJMʜ
    w ํ๏͕͋Γ͗͢Δ͜ͱʹՃ͑ͯૹΔखஈΛܾΊΔίϛϡχέʔγϣϯ͕໘౗
    w ๨ΕΔɺͦͯ࣌͠͸ྲྀΕΔ

    View Slide

  14. खஈʹ͍ͭͯ͸
    Կ΋ߟ͑ͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠

    View Slide

  15. *OTUBHSBNΈ͍ͨͳΞϓϦΛ
    ։ൃ͠Α͏

    View Slide

  16. ͜ͷΞϓϦͰ໨ࢦ͢͜ͱ
    w ࡱΔˠͳΜΒ͔ͷ࡞ۀˠΞοϓϩʔυ
    w ͳΜΒ͔ͷ࡞ۀ͕໘౗Ͱ͋ΔˠΞϓϦ಺ͰࡱӨޙͷϑϩʔʹ૊ΈࠐΉ
    ͜ͱʹΑͬͯ࠷খԽ
    w ͳΜΒ͔ͷ࡞ۀͷखஈ͕ͨ͘͞Μ͋Δˠखஈ͕ΞϓϦʹू໿
    w ํ๏͕͋Γ͗͢Δ͜ͱʹՃ͑ͯૹΔํ๏ͷίϛϡχέʔγϣϯ͕໘౗
    w ๨ΕΔɺͦͯ࣌͠͸ྲྀΕΔˠʮࡱΔʯʮΞοϓϩʔυʯΛಉ࣌ʹߦ͏

    View Slide

  17. ։ൃ͢Δͧɾɾɾʂ

    View Slide

  18. ͢Ͱʹϲ݄੾ͬͯͨ
    ʢ݁ࠗࣜ͸೥݄೔ʣ

    View Slide

  19. *OJUJBMDPNNJU
    J04%$+BQBO
    స৬
    ݁ࠗࣜ

    View Slide

  20. *OJUJBMDPNNJU
    J04%$+BQBO
    స৬
    ݁ࠗࣜ
    ͖͋Β͔ʹਓੜͷେࣄͳΠϕϯτΛ٧ΊࠐΈ͍͗ͯ͢Δ

    View Slide

  21. ͋ΕɺϜϦʁ

    View Slide

  22. Ͱ΋࡞Γ͍ͨɾɾɾʂ
    ΍͍ͬͯͧ͘ʂ

    View Slide

  23. ओͳ΍Γ͍ͨ͜ͱ
    w ࣸਅʢλΠϜϥΠϯʣ
    w 1VTI௨஌
    w ੮࣍දӾཡ
    w ͓஌Βͤը໘

    View Slide

  24. ࡉ͔͘
    w ࣸਅʢλΠϜϥΠϯʣ
    w Χϝϥ͔ΒͷΞοϓϩʔυ
    w ΞϧόϜ͔ΒͷΞοϓϩʔ
    υ
    w Ξοϓͨࣸ͠ਅʹ-JLFతͳ
    ͜ͱ͕Ͱ͖Δ
    w Ξοϓͨࣸ͠ਅʹίϝϯτ
    Ͱ͖Δ
    w ࣸਅΛՃ޻Ͱ͖Δ
    w 1VTI௨஌
    w ݁ࠗࣜલ೔ʹʮ໌೔͸ΑΖ͘͠
    ͓Ͷ͕͍͠·͢ʯͱ͔ૹΓ͔ͨͬ
    ͨ
    w ੮࣍දӾཡ
    w ͜Ε෼͔ͬͯΔͱخ͍͠͸ͣ
    w ͓஌Βͤը໘
    w Կ͔͋ͬͨΒ͜͜ʹදࣔͯ͠ʮಡ
    ΜͰͶʯ͕͔ͨͬͨ͠

    View Slide

  25. ࡟ͬͨͭ΋ΓͰ΋ͨ͘͞Μ

    View Slide

  26. ՝୊੔ཧ
    w εέδϡʔϧ
    w ϦϦʔε೔݁ࠗࣜ౰೔ʜͩͱؒʹ߹Θͳ͍ͷͰ೔͘Β͍લ
    w αʔόαΠυʢͳʹΛ࢖͏ʹͯ͠΋ઈରؒʹ߹Θͳ͍ʣ
    w ࣌ظʢ৽͍͠04 4XJGUͳͲ͕ग़Δ͔ग़ͳ͍͔ͷλΠϛϯάʣ
    w ഑෍
    w Πϯετʔϧ͢ΔਓΛͬͪ͜Ͱίϯτϩʔϧ͍ͨ͠
    w Ϣʔβʔ
    w ࣗ෼ͨͪͷ༑ୡಉੈ୅
    w ෕਌ɺ฼਌ɺ਌଒ εϚϗ࢖͍׳Εͯͳ͍ਓ͕ଟ͍

    w 04͸ʜʁJ04ͷਓ͍ͨΒͲ͏͠Α͏

    View Slide

  27. ΍Βͳ͍͜ͱΛܾΊͨ

    View Slide

  28. ՝୊΁ͷΞϓϩʔν
    w εέδϡʔϧ͸Ԇͼͳ͍ͷͰͰ͖Δ͜ͱΛؒʹ߹͏ൣғͰ΍Δ
    w αʔόαΠυ͸΍Βͳ͍ɺ'JSFCBTFΛ࢖͏
    w J04 4XJGUͰ։ൃΛߦ͏
    w ετΞʹ͸ग़͞ͳ͍ɺ%FQMPZHBUFͰ഑Δ
    w Πϯετʔϧํ๏͕෼͔Βͳ͍ਓ͸έΞ͢Δ

    View Slide

  29. ࣮૷

    View Slide

  30. ΍Γ͍ͨ͜ͱ
    w ࣸਅ
    w Χϝϥ͔ΒͷΞοϓϩʔυ
    w ΞϧόϜ͔ΒͷΞοϓϩʔ
    υ
    w Ξοϓͨࣸ͠ਅʹ-JLFతͳ
    ͜ͱ͕Ͱ͖Δ
    w Ξοϓͨࣸ͠ਅʹίϝϯτ
    Ͱ͖Δ
    w ࣸਅΛՃ޻Ͱ͖Δ
    w 1VTI௨஌
    w ݁ࠗࣜલ೔ʹʮ໌೔͸ΑΖ͘͠
    ͓Ͷ͕͍͠·͢ʯͱ͔ૹΓ͔ͨͬ
    ͨ
    w ੮࣍දӾཡ
    w ͜Ε෼͔ͬͯΔͱخ͍͠͸ͣ
    w ͓஌Βͤը໘
    w Կ͔͋ͬͨΒ͜͜ʹදࣔͯ͠ʮಡ
    ΜͰͶʯ͕͔ͨͬͨ͠

    View Slide

  31. ΄΅શͯ'JSFCBTFͰ࣮ݱՄೳ

    View Slide

  32. ΍Γ͍ͨ͜ͱ
    w ࣸਅʢλΠϜϥΠϯʣ
    w Χϝϥ͔ΒͷΞοϓϩʔυ
    w ΞϧόϜ͔ΒͷΞοϓϩʔ
    υ
    w Ξοϓͨࣸ͠ਅʹ-JLFతͳ
    ͜ͱ͕Ͱ͖Δ
    w Ξοϓͨࣸ͠ਅʹίϝϯτ
    Ͱ͖Δ
    w ࣸਅΛՃ޻Ͱ͖Δ
    w 1VTI௨஌
    w ݁ࠗࣜલ೔ʹʮ໌೔͸ΑΖ͘͠
    ͓Ͷ͕͍͠·͢ʯͱ͔ૹΓ͔ͨͬ
    ͨ
    w ੮࣍දӾཡ
    w ͜Ε෼͔ͬͯΔͱخ͍͠͸ͣ
    w ͓஌Βͤը໘
    w Կ͔͋ͬͨΒ͜͜ʹදࣔͯ͠ʮಡ
    ΜͰͶʯ͕͔ͨͬͨ͠
    ແ೦ɺ͜Ε͚ͩͰ͖ͣ

    View Slide

  33. View Slide

  34. λΠϜϥΠϯͷ࣮૷

    View Slide

  35. λΠϜϥΠϯͷػೳ
    w Χϝϥ͔ΒͷΞοϓϩʔυ
    w ΞϧόϜ͔ΒͷΞοϓϩʔυ
    w Ξοϓͨࣸ͠ਅʹ-JLFతͳ͜ͱ͕Ͱ͖Δ
    w Ξοϓͨࣸ͠ਅʹίϝϯτͰ͖Δ
    w ࣸਅΛՃ޻Ͱ͖Δ

    View Slide

  36. ඞཁͳ΋ͷ

    View Slide

  37. ࣸਅΛΞοϓϩʔυ
    ը૾63-औಘ
    औಘͨ͠ը૾63-ͱͱ΋ʹ%BUBCBTFʹอଘ
    ίʔϧόοΫ

    View Slide

  38. final class FirebaseDatabaseManager {
    private var reference: FIRDatabaseReference = FIRDatabase.database().reference().child("articles")
    func save(_ article: Article, completion: CompletionHandler?) {
    reference.child(article.id).setValue(article.encoded) { _, _ in
    completion?()
    }
    }
    func load(_ completionHandler: @escaping ([Article]) -> ()) {
    reference.observeSingleEvent(of: .value) { snapshot -> Void in
    completionHandler(Article.build(snapshot.value))
    }
    }
    func added(_ completionHandler: @escaping (Article?) -> ()) {
    let handler: (FIRDataSnapshot) -> Void = { snapshot in
    completionHandler(Article.decodeSingle(snapshot))
    }
    reference.observe(.childAdded, with: handler)
    }
    'JSFCBTF4%,Λ࢖͍ɺ3FBMUJNF%BUBCBTFͷมߋΛ؂ࢹ

    View Slide

  39. protocol PhotoViewerViewModelProtocol: class {
    func didUpdate(_ state: PhotoViewerViewModel.State)
    }
    final class PhotoViewerViewModel {
    enum State {
    case list([Article])
    case add([Article])
    case update(Article)
    case loading
    case error(String)
    }
    func refresh() {
    guard reachability.isReachable else {
    delegate?.didUpdate(.error("σʔλΛऔಘͰ͖·ͤΜͰͨ͠"))
    return
    }
    delegate?.didUpdate(.loading)
    database.load { [weak self] articles in
    self?.delegate?.didUpdate(.list(articles))
    self?.subscribe()
    }
    }
    7JFX.PEFMͰ4UBUFΛఆٛɺ%BUBCBTFͷมߋʹԠͯ͡ঢ়ଶΛߋ৽͢Δ

    View Slide

  40. func didUpdate(_ state: PhotoViewerViewModel.State) {
    cameraButton.isEnabled = true
    switch state {
    case .list(let article):
    tableView.isHidden = false
    refreshControl.endRefreshing()
    SVProgressHUD.dismiss()
    dataSource = article
    tableView.reloadData()
    case .add(let articles):
    tableView.isHidden = false
    dataSource = articles + dataSource
    tableView.reloadData()
    SVProgressHUD.dismiss()
    case .loading:
    cameraButton.isEnabled = false
    tableView.isHidden = false
    SVProgressHUD.show(withStatus: "loading...")
    7JFX$POUSPMMFS͸4UBUFʹԠͯ͡දࣔΛ੾Γସ͑Δ

    View Slide

  41. ௨஌ɾ͓஌Βͤͷ࣮૷

    View Slide

  42. ௨஌ʹඞཁͳ΋ͷ

    View Slide

  43. ͓஌Βͤʹඞཁͳ΋ͷ

    View Slide

  44. View Slide

  45. ΞϓϦ͕ΞΫςΟϒʹͳͬͨ࣌ʹμ΢ϯϩʔυ

    View Slide

  46. final class FirebaseStorageManager {
    private let storageRef = FIRStorage.storage().reference(forURL: "gs://{project id}.appspot.com/")
    func newsLoad(_ completion: @escaping ([News]) -> Void) {
    storageRef.child("news.json").data(withMaxSize: maxSize) { (data, error) in
    guard error == nil, let data = data else { return }
    completion(News.decode(data))
    }
    }

    View Slide

  47. func applicationDidBecomeActive(_ application: UIApplication) {
    let storage = FirebaseStorageManager()
    storage.newsLoad { news in
    NewsHistoryContainer.news = news
    NotificationCenter.default.post(name: updateNewsCount, object: nil)
    }
    }

    View Slide

  48. w େࣄͳ৘ใ͸1VTI௨஌ˍ͓஌Βͤ഑৴
    w ձ৔·Ͱͷϧʔτ
    w ెา෼਺
    w J04%$Ͱಘͨ஌ݟ
    w આ໌จΛॻ͍ͯ΋ͳ͔ͳ͔ಡΜͰ΋Β͏͜
    ͱ͸೉͍͠
    w J04%$ͷΞϓϦͰ΋ࠔΓͲ͜Ζ΍ޙͰฉ͍
    ͯΨοΧϦ͢ΔΑ͏ͳ৘ใ͸UXJUUFSΞΧ΢
    ϯτͷ΄͔ɺ1VTI௨஌Ͱ഑৴ʢࠓ͔ΒͰ΋
    ݟͯͶʣ

    View Slide

  49. ݁ࠗࣜͳΒͰ͸ͷ1+ͷਐΊํ

    View Slide

  50. ͨͩͰ͑͞΍Δ͜ͱଟͯ͘ࡴെͱ͕ͪ͠
    ʢͱฉ͍ͨʣ

    View Slide

  51. ݁ࠗࣜͷλεΫΛ*TTVFͰҰݩ؅ཧ

    View Slide

  52. Ոఉ༻4MBDLʹ௨஌
    ४උ๩ͯ͘͠ʢԞ͞ΜͰ͸ͳࣗ͘෼͕ʣΠϥΠϥͯ͠͠·ͬͯ΋
    ΩϟϥΫλʔʹ௨஌͞ΕΔͱͪΐͬͱ࿨Ή

    View Slide

  53. w ΞϓϦͱ1VTI௨஌ͷ഑৴ɺจݴΛ
    ܾΊΔͷ͸Ԟ͞Μͷ໾ׂʹ
    w Ԟ͞Μ͸։ൃͱ͔શؔ͘܎ͳ͍
    ࢓ࣄ
    w ීஈɺΤϯδχΞ͕ͲΜͳ࢓ࣄΛ
    ͍ͯ͠Δ͔ͷཧղʹ΋ͭͳ͕Δ
    w ίʔυॻ͘ͷ͸΄ͱΜͲҰਓͰ׬
    ݁ͯ͠͠·͏ͷͰԞ͞Μʹʮਃ͠༁
    ͳ͍ʯײ͕ग़ͯ͘Δ
    w lؔΘ͍ͬͯΔzײɺνʔϜײ
    w ೉ͦ͠͏ɺྑ͘෼͔Βͳ͍ͱࢥ
    ΘΕͳ͍Α͏ʹ

    View Slide

  54. ͖Ίࡉ΍͔ͳέΞ
    w ஈ֊ެ։
    w ࠷ॳ͸Ϧςϥγʔߴͦ͏ͳਓʹ
    w खॱΛগͣͭ͠࡞Γঃʑʹ୭Ͱ΋
    ෼͔ΔΑ͏ͳखॱॻΛ࡞Γ্͛ͯ
    ͍ͬͨ
    w ࠷ޙͷํͰ྆਌ɺ਌଒ʹ഑෍

    View Slide

  55. ݁Ռ

    View Slide

  56. ૯Ξοϓϩʔυ਺

    ͪͳΈʹϓϩʹ͓ئ͍ͨ͠΋ͷ͸ຕ

    View Slide

  57. w ਓ͕ࡱͬͨຕͰ͸ͳ͘ɺ͍ΖΜͳਓ͕ࡱͬͨຕ
    w ྔͱͯ͠͸͍ͨ͘͢͝͞Μ͋ΔΘ͚Ͱ͸ͳ͍͕ɺผʑʹࣸਅΛ΋Β͏ΑΓ
    ΋ѹ౗తʹίϛϡχέʔγϣϯίετ͕গͳ͘ࡁΉ
    w ͍Ζ͍Ζͳਓ͕ࡱӨͨࣸ͠ਅΛݟΔ͜ͱ͕Ͱ͖ͯ໘ന͍

    View Slide

  58. ·ͱΊ
    w ݁ࠗࣜ΍J04%$ͷΑ͏ͳΠϕϯτΞϓϦͷ։ൃͰ'JSFCBTFͷػೳ͸ͱͯ΋༗ޮత
    ʹ࢖͑Δ
    w 1VTI௨஌ͳͲΞϓϦΛ࢖ͬͯ΋Β͏্Ͱඞཁͳػೳͷ࣮ݱ͕ૉૣ͘Ͱ͖Δ
    w σʔλͷಉظػೳͳͲڧྗͳػೳ͕'JSFCBTF4%,ʹ༻ҙ͞Ε͍ͯΔͷͰɺͦ
    ΕΛ࢖͏͜ͱͰΑΓ࢖͍΍͍͢ΞϓϦ͕։ൃͰ͖Δ

    View Slide

  59. Έͳ͞Μ΋ΠϕϯτͰ
    Կ͔࡞ͬͯΈ·ͤΜ͔ʁ

    View Slide

  60. View Slide