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

4239ea2bf38d7178476faa8787683105?s=47 Motoki Narita
September 17, 2017

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

4239ea2bf38d7178476faa8787683105?s=128

Motoki Narita

September 17, 2017
Tweet

Transcript

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

  2. "CPVUNF w HJUIVC UXJUUFS RJJUBNPUPLJFF w J04%$+BQBOελοϑ w גࣜձࣾι΢κ΢ͰϝϧΧϦΧ΢ϧͷ։ൃΛ͍ͯ͠ΔJ04ΤϯδχΞ w

    ι΢κ΢͸ϝϧΧϦʹଓ͘৽ͨͳαʔϏεΛ࡞ΔձࣾͰ͢ w γΣΞαΠΫϧαʔϏεNFSDIBSJ४උத w ϋʔυ΢ΣΞ΋Ͱ͖ΔPSڵຯ௡ʑͳJ04ΤϯδχΞɺେืूத
  3. None
  4. ͖ΐ͏࿩͢͜ͱ

  5. ڈ೥݁ࠗࣜΛڍ͛ͨͱ͖ʹɺ
 ઐ༻ͷJ04ΞϓϦΛ։ൃ͓ͨ͠࿩

  6. ݁ࠗࣜ)BDL

  7. ͳͥ։ൃͨ͠ͷ͔ʁ

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

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

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

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

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

  13. ͳΜΒ͔ͷ࡞ۀ͕๛෋ w ࡱΔˠͳΜΒ͔ͷ࡞ۀˠΞοϓϩʔυ w ͳΜΒ͔ͷ࡞ۀ͕໘౗Ͱ͋ΔʢΞϓϦ։͍ͯɺࣸਅબΜͰɺૹΔʣ w ͳΜΒ͔ͷ࡞ۀͷखஈ͕ͨ͘͞Μ͋ΔʢΞϓϦ͍ͬͺ͍ʣ w -*/& 'BDFCPPL.FTTFOHFS

    ϓϦϯτΞ΢τ &NBJMʜ w ํ๏͕͋Γ͗͢Δ͜ͱʹՃ͑ͯૹΔखஈΛܾΊΔίϛϡχέʔγϣϯ͕໘౗ w ๨ΕΔɺͦͯ࣌͠͸ྲྀΕΔ
  14. खஈʹ͍ͭͯ͸ Կ΋ߟ͑ͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠

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

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

    w ๨ΕΔɺͦͯ࣌͠͸ྲྀΕΔˠʮࡱΔʯʮΞοϓϩʔυʯΛಉ࣌ʹߦ͏
  17. ։ൃ͢Δͧɾɾɾʂ

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

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

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

  21. ͋ΕɺϜϦʁ

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

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

  24. ࡉ͔͘ w ࣸਅʢλΠϜϥΠϯʣ w Χϝϥ͔ΒͷΞοϓϩʔυ w ΞϧόϜ͔ΒͷΞοϓϩʔ υ w Ξοϓͨࣸ͠ਅʹ-JLFతͳ

    ͜ͱ͕Ͱ͖Δ w Ξοϓͨࣸ͠ਅʹίϝϯτ Ͱ͖Δ w ࣸਅΛՃ޻Ͱ͖Δ w 1VTI௨஌ w ݁ࠗࣜલ೔ʹʮ໌೔͸ΑΖ͘͠ ͓Ͷ͕͍͠·͢ʯͱ͔ૹΓ͔ͨͬ ͨ w ੮࣍දӾཡ w ͜Ε෼͔ͬͯΔͱخ͍͠͸ͣ w ͓஌Βͤը໘ w Կ͔͋ͬͨΒ͜͜ʹදࣔͯ͠ʮಡ ΜͰͶʯ͕͔ͨͬͨ͠
  25. ࡟ͬͨͭ΋ΓͰ΋ͨ͘͞Μ

  26. ՝୊੔ཧ w εέδϡʔϧ w ϦϦʔε೔݁ࠗࣜ౰೔ʜͩͱؒʹ߹Θͳ͍ͷͰ೔͘Β͍લ w αʔόαΠυʢͳʹΛ࢖͏ʹͯ͠΋ઈରؒʹ߹Θͳ͍ʣ w ࣌ظʢ৽͍͠04 4XJGUͳͲ͕ग़Δ͔ग़ͳ͍͔ͷλΠϛϯάʣ

    w ഑෍ w Πϯετʔϧ͢ΔਓΛͬͪ͜Ͱίϯτϩʔϧ͍ͨ͠ w Ϣʔβʔ w ࣗ෼ͨͪͷ༑ୡಉੈ୅ w ෕਌ɺ฼਌ɺ਌଒ εϚϗ࢖͍׳Εͯͳ͍ਓ͕ଟ͍  w 04͸ʜʁJ04ͷਓ͍ͨΒͲ͏͠Α͏
  27. ΍Βͳ͍͜ͱΛܾΊͨ

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

    w Πϯετʔϧํ๏͕෼͔Βͳ͍ਓ͸έΞ͢Δ
  29. ࣮૷

  30. ΍Γ͍ͨ͜ͱ w ࣸਅ w Χϝϥ͔ΒͷΞοϓϩʔυ w ΞϧόϜ͔ΒͷΞοϓϩʔ υ w Ξοϓͨࣸ͠ਅʹ-JLFతͳ

    ͜ͱ͕Ͱ͖Δ w Ξοϓͨࣸ͠ਅʹίϝϯτ Ͱ͖Δ w ࣸਅΛՃ޻Ͱ͖Δ w 1VTI௨஌ w ݁ࠗࣜલ೔ʹʮ໌೔͸ΑΖ͘͠ ͓Ͷ͕͍͠·͢ʯͱ͔ૹΓ͔ͨͬ ͨ w ੮࣍දӾཡ w ͜Ε෼͔ͬͯΔͱخ͍͠͸ͣ w ͓஌Βͤը໘ w Կ͔͋ͬͨΒ͜͜ʹදࣔͯ͠ʮಡ ΜͰͶʯ͕͔ͨͬͨ͠
  31. ΄΅શͯ'JSFCBTFͰ࣮ݱՄೳ

  32. ΍Γ͍ͨ͜ͱ w ࣸਅʢλΠϜϥΠϯʣ w Χϝϥ͔ΒͷΞοϓϩʔυ w ΞϧόϜ͔ΒͷΞοϓϩʔ υ w Ξοϓͨࣸ͠ਅʹ-JLFతͳ

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

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

    ࣸਅΛՃ޻Ͱ͖Δ
  36. ඞཁͳ΋ͷ

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

  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ͷมߋΛ؂ࢹ
  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ͷมߋʹԠͯ͡ঢ়ଶΛߋ৽͢Δ
  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ʹԠͯ͡දࣔΛ੾Γସ͑Δ
  41. ௨஌ɾ͓஌Βͤͷ࣮૷

  42. ௨஌ʹඞཁͳ΋ͷ

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

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

  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)) } }
  47. func applicationDidBecomeActive(_ application: UIApplication) { let storage = FirebaseStorageManager() storage.newsLoad

    { news in NewsHistoryContainer.news = news NotificationCenter.default.post(name: updateNewsCount, object: nil) } }
  48. w େࣄͳ৘ใ͸1VTI௨஌ˍ͓஌Βͤ഑৴ w ձ৔·Ͱͷϧʔτ w ెา෼਺ w J04%$Ͱಘͨ஌ݟ w આ໌จΛॻ͍ͯ΋ͳ͔ͳ͔ಡΜͰ΋Β͏͜

    ͱ͸೉͍͠ w J04%$ͷΞϓϦͰ΋ࠔΓͲ͜Ζ΍ޙͰฉ͍ ͯΨοΧϦ͢ΔΑ͏ͳ৘ใ͸UXJUUFSΞΧ΢ ϯτͷ΄͔ɺ1VTI௨஌Ͱ഑৴ʢࠓ͔ΒͰ΋ ݟͯͶʣ
  49. ݁ࠗࣜͳΒͰ͸ͷ1+ͷਐΊํ

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

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

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

  53. w ΞϓϦͱ1VTI௨஌ͷ഑৴ɺจݴΛ ܾΊΔͷ͸Ԟ͞Μͷ໾ׂʹ w Ԟ͞Μ͸։ൃͱ͔શؔ͘܎ͳ͍ ࢓ࣄ w ීஈɺΤϯδχΞ͕ͲΜͳ࢓ࣄΛ ͍ͯ͠Δ͔ͷཧղʹ΋ͭͳ͕Δ w

    ίʔυॻ͘ͷ͸΄ͱΜͲҰਓͰ׬ ݁ͯ͠͠·͏ͷͰԞ͞Μʹʮਃ͠༁ ͳ͍ʯײ͕ग़ͯ͘Δ w lؔΘ͍ͬͯΔzײɺνʔϜײ w ೉ͦ͠͏ɺྑ͘෼͔Βͳ͍ͱࢥ ΘΕͳ͍Α͏ʹ
  54. ͖Ίࡉ΍͔ͳέΞ w ஈ֊ެ։ w ࠷ॳ͸Ϧςϥγʔߴͦ͏ͳਓʹ w खॱΛগͣͭ͠࡞Γঃʑʹ୭Ͱ΋ ෼͔ΔΑ͏ͳखॱॻΛ࡞Γ্͛ͯ ͍ͬͨ w

    ࠷ޙͷํͰ྆਌ɺ਌଒ʹ഑෍
  55. ݁Ռ

  56. ૯Ξοϓϩʔυ਺  ͪͳΈʹϓϩʹ͓ئ͍ͨ͠΋ͷ͸ຕ

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

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

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

  60. None