Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
モバイルアプリで困らないエラーハンドリングとロギングのベストプラクティス
Search
Yoichi Tagaya
September 16, 2017
Programming
21
6.5k
モバイルアプリで困らないエラーハンドリングとロギングのベストプラクティス
iOSDC 2017 in Tokyo, September 16-17, 2017
https://iosdc.jp/2017/node/1482
Yoichi Tagaya
September 16, 2017
Tweet
Share
More Decks by Yoichi Tagaya
See All by Yoichi Tagaya
Dependency Injection
yoichitgy
0
160
Dependency Injection Pattern for iOS App
yoichitgy
1
270
Dependency Injection Pattern for iOS Apps
yoichitgy
2
400
Practical Structure to Configure Dependency Injection in Swift for iOS
yoichitgy
1
500
Architecture and ReactorKit
yoichitgy
1
660
GDPRについて
yoichitgy
2
1.5k
More about Crashlytics and Less about GDPR ;)
yoichitgy
2
300
How to contribute to try! Swift Tokyo 2018
yoichitgy
0
89
Dependency Injection in Practice (iOSCon)
yoichitgy
0
460
Other Decks in Programming
See All in Programming
F#で自在につくる静的ブログサイト - 関数型まつり2025
pizzacat83
0
310
Spring gRPC で始める gRPC 入門 / Introduction to gRPC with Spring gRPC
mackey0225
2
520
AWS CDKの推しポイント 〜CloudFormationと比較してみた〜
akihisaikeda
3
290
Datadog RUM 本番導入までの道
shinter61
1
310
ktr0731/go-mcpでMCPサーバー作ってみた
takak2166
0
170
カクヨムAndroidアプリのリブート
numeroanddev
0
430
データの民主化を支える、透明性のあるデータ利活用への挑戦 2025-06-25 Database Engineering Meetup#7
y_ken
0
280
データベースコネクションプール(DBCP)の変遷と理解
fujikawa8
1
270
Team topologies and the microservice architecture: a synergistic relationship
cer
PRO
0
910
PHP 8.4の新機能「プロパティフック」から学ぶオブジェクト指向設計とリスコフの置換原則
kentaroutakeda
1
260
Haskell でアルゴリズムを抽象化する / 関数型言語で競技プログラミング
naoya
17
4.8k
なぜ適用するか、移行して理解するClean Architecture 〜構造を超えて設計を継承する〜 / Why Apply, Migrate and Understand Clean Architecture - Inherit Design Beyond Structure
seike460
PRO
0
220
Featured
See All Featured
Music & Morning Musume
bryan
46
6.6k
GitHub's CSS Performance
jonrohan
1031
460k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.8k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
How to Ace a Technical Interview
jacobian
277
23k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
107
19k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Into the Great Unknown - MozCon
thekraken
39
1.9k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
Transcript
!ZPJDIJUHZ ϞόΠϧΞϓϦͰࠔΒͳ͍ ΤϥʔϋϯυϦϯάͱ ϩΪϯάͷϕετϓϥΫςΟε ଟլ୩ ༸Ұ iOSDC JAPAN 2017
!ZPJDIJUHZ ࣗݾհ ʙ ଟլ୩ ༸Ұ • Swinject (Dependency Injection Framework)
ͷ࡞ऀ ‣ ଟͷϓϩμΫγϣϯ࠾༻ ‣ GitHubελʔ: ͏͙͢2000 • ϝϧΧϦͷiOSΤϯδχΞ ‣ ओʹΞϝϦΧ൛ΞϓϦΛ୲ ‣ 9/30 () Mercari Tech Conf 2017ͰDIͷΛ͠·͢ J04%$ͰlίʔυੜʹΑΔ੩తͳ%FQFOEFODZ*OKFDUJPOzCZ!JTILBXBPO4FQ
!ZPJDIJUHZ •ɹΤϯδχΞͷεΩϧ •ɹίʔυϨϏϡʔ •ɹϢχοτςετ •ɹ6*ࣗಈςετ •ɹखಈςετ •ɹΤϥʔϩά ࠓͷ ΞϓϦͷ্࣭ʹඞཁͳ͜ͱ
!ZPJDIJUHZ ͜Μͳͷݟͨ͜ͱ͋Γ·ͤΜ͔ʁ ΫϥογϡͰ1ˑϨϏϡʔͷཛྷ ࠶ݱ͠ͳ͍ Ͳ͏͢Ε͍͍͔͔Βͳ͍ ΞϓϦΛόʔδϣϯΞοϓͨ͠
!ZPJDIJUHZ Ϋϥογϡϩάͱ͍͑
!ZPJDIJUHZ Crashlytics IUUQTXXXGBCSJDJP $SBTIMZUJDTΛਂ͘୳ͬͯΈΑ͏
!ZPJDIJUHZ CrashlyticsͰҰ൪ॏཁͳ͜ͱ IUUQTEPDTGBCSJDJPBQQMFDSBTIMZUJDTUFTUDSBTIIUNMUSPVCMFTIPPUJOH func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
[UIApplicationLaunchOptionsKey: Any]? ) -> Bool { Fabric.with([Crashlytics.self]) return true } ϩάΫϥογϡޙʹΞϓϦ͕࠶ىಈͨ࣌͠ʹૹΒΕΔ application:didFinishLaunchingWithOptionsΛແࣄʹ௨ա͠ͳ͍ͱμϝ
!ZPJDIJUHZ ىಈ࣌ application:didFinishLaunchingWithOptionsͰͦ͠͏ͳ͜ͱ • ֤छϑϨʔϜϫʔΫͷॳظԽ •ɹ%BUBCBTFͷϚΠάϨʔγϣϯ •ɹΩϟογϡͷΫϦΞ ϝΠϯεϨουΛ࣌ؒࢭΊͳ͍
!ZPJDIJUHZ ಛʹґଘϥΠϒϥϦʹҙ IUUQTHJUIVCDPNQJOUFSFTU1*/3FNPUF*NBHFJTTVFT 1*/3FNPUF*NBHFࣗମ͍͍ϥΠϒϥϦͰ͢
!ZPJDIJUHZ ͦΕͰ
!ZPJDIJUHZ Crashlyticsͬͯ Πϯετʔϧ͢ΔҎ֎ʹ Կ͔ඞཁͳͷʁ
!ZPJDIJUHZ Crashlyticsʹ ศརͳՃใ͕͋Δ
!ZPJDIJUHZ ϢʔβใͷՃ γϯάϧτϯϝιου આ໌ TFU6TFS*EFOUJpFS @ 6TFS*EΛઃఆ͢Δ TFU6TFS&NBJM @ &NBJMΛઃఆ͢Δ
6TFS*E͕͋Εී௨ෆཁ TFU6TFS/BNF @ Ϣʔβͷ໊લΛઃఆ͢Δ 6TFS*E͕͋Εී௨ෆཁ ΧελϚʔαϙʔτͷใ͔ΒௐΔ࣌ʹศར &NBJMͱϢʔβͷ໊લ໌Β͔ͳݸਓใͳͷͰҙ
!ZPJDIJUHZ Key/ValueͷՃ γϯάϧτϯϝιου આ໌ TFU0CKFDU7BMVF @GPS,FZ 4USJOHͳͲΛ,FZʹରͯ͠ઃఆ͢Δ TFU#PPM7BMVF @GPS,FZ #PPMΛ,FZʹରͯ͠ઃఆ͢Δ
TFU*OU7BMVF @GPS,FZ *OUΛ,FZʹରͯ͠ઃఆ͢Δ TFU'MPBU7BMVF @GPS,FZ 'MPBUΛ,FZʹରͯ͠ઃఆ͢Δ 3FNPUF$POpH "#5FTU %PXOMPBEͨ͠Ϧιʔε+4ͷ7FSTJPOʹ ࠷େݸͷ,FZ·Ͱͭͷ,FZ7BMVF͕,#·Ͱ ,FZ͕ͨ͘͞ΜඞཁͳΒ+40/จࣈྻʹ͢Δ͜ͱݕ౼
!ZPJDIJUHZ ΧελϜϩάͷՃ ؔ આ໌ $-4-PHW @GPSNBU BSHT Ϋϥογϡൃੜલͷϩά͕Ϋϥογϡʹඥ͚ΒΕΔ ΫϥογϡͷݪҼʹͳΔલͷಈ࡞͕Θ͔Δ
ϩά࠷େ,# ߦจࣈ͘Β͍ͳΒߦ͘Β͍ ͋;ΕͨΒݹ͍ͷ͔Βফ͞ΕΔ Ϣʔβߦಈ Πϕϯτ ͷϩά"OTXFST'JSFCBTFͳͲΛ͏
!ZPJDIJUHZ ඇΫϥογϡͷϨϙʔτΛՃ γϯάϧτϯϝιου આ໌ SFDPSE&SSPS @ ॏେͳΤϥʔͰϩάΤϯτϦʔΛ࡞Δ Ϩϙʔτ/PO'BUBMTάϧʔϓʹ·ͱΊΒΕΔ ΞϓϦ࠶ىಈ࣌ʹ$SBTIMZUJDTʹૹ৴͞ΕΔ
Ϋϥογϡ͠ͳ͍͕ॏେͳΤϥʔΛ$SBTIMZUJDTͰ֬ೝͰ͖Δ ϩάʹΔͷΞϓϦ࠶ىಈ·Ͱͷ࠷େݸͷΤϥʔ·Ͱ $16ίετ͕͔͔ΔͷͰΦϒβʔόʔޮՌʹҙ %8"3' %FCVH8JUI"UUSJCVUFE3FDPSE'PSNBU VOXJOEJOH
!ZPJDIJUHZ CrashlyticsΛ OSLogͱΈ߹Θͤͯ ࣗ࡞ͷϩΨʔΛ࡞Γ·͢
!ZPJDIJUHZ OSLog/os_log var osLog = OSLog( subsystem: “com.my-company.LoggingSample", category: “ViewModel”
) os_log(“Hello world!”, log: osLog, type: .default) ͍ํ J04͔Β͑ΔΑ͏ʹͳͬͨϩάͷΈ
!ZPJDIJUHZ OSLogType IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOPTMPHHJOH ϩάϨϕϧ อଘઌ ಛ EFCVH ͳ͠ σόοά༻
JOGP ϝϞϦʔ όοϑΝʔ͕͍ͬͺ͍ʹͳͬͨΒফ͑Δ Τϥʔ͕ى͖ͨ߹อଘ͞ΕΔ EFGBVMU ετϨʔδ ࠷ॳόοϑΝʔʹอଘ͞ΕΔ ͍ͬͺ͍ʹͳͬͨΒετϨʔδʹҠ͞ΕΔ FSSPS ετϨʔδ ϓϩηεͷΤϥʔͰ͏ GBVMU ετϨʔδ ෳϓϩηε͕ؔΘΔΤϥʔͰ͏
!ZPJDIJUHZ Console App IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED IUUQTNFEJVNDPN!BCKVSBUPVOJpFEMPHHJOHBOEBDUJWJUZUSBDJOHBB⒎FGC • "DUJWJUZ5SBDJOHͱΈ߹ ΘͤΔͱศར • ෳϓϩηε͕ؔΘΔΞ
ϓϦͷσόοάͰศར w .BD"QQ w 8BUDI"QQ • ݱঢ়4XJGU͔Β ͑ͳ͍ w ͏ʹԼͷϦϯΫࢀর
!ZPJDIJUHZ ͔͠͠ͳ͕Β ࠓճγϯϓϧͳ༻๏ʹཹΊ·͢ # $SBTIMZUJDT͚ͩͰेڧྗ
!ZPJDIJUHZ ࣗ࡞ϩΨʔͷϩάϨϕϧ ϩάϨϕϧ ༻్ ॲཧ EFCVH %FCVH࣌ʹ͚ͩ ݟ͍ͨใ $POTPMFʹͷΈग़ྗ
JOGP "1*ίʔϧ τϨʔε $POTPMFͱ$-4-PHWͷग़ྗ FSSPS ϋϯυϦϯά ՄೳͳΤϥʔ $POTPMFͱ$-4-PHWͷग़ྗ $-4-PHWͷϝοηʔδݕࡧੑΛ্͛Δ GBUBM ఆ֎ͷΤϥʔ $POTPMFʹग़ྗ SFDPSE&SSPSͰ$SBTIMZUJDTͷϨϙʔτΤϯτϦʔΛ࡞Δ BTTFSUJPO'BJMVSFೖΕͯ%FCVHϏϧυͰམͪΔΑ͏ʹ͢Δ
!ZPJDIJUHZ LogΫϥε final class Log { static func debug(message: String)
{ os_log("⚒%@", type: .debug, message) } static func info(message: String) { os_log("ℹ%@", type: .debug, message) CLSLogv("%@", getVaList([message])) } static func error(message: String) { os_log("❗%@", type: .debug, message) CLSLogv("[Error] %@", getVaList([message])) } }
!ZPJDIJUHZ LogΫϥε final class Log { static func fatal( message:
String, file: String = #file, function: String = #function, line: Int = #line) { os_log("%@", log: .default, type: .debug, message) let fileName = file.components(separatedBy: "/").last ?? "" let error = NSError( domain: "\(fileName):\(function)", code: line, userInfo: ["message": message] ) Crashlytics.sharedInstance().recordError(error) assertionFailure(message) } }
!ZPJDIJUHZ final class Log { static func error(error: Error) {
let message = String(reflecting: error) os_log("❗%@", log: .default, type: .debug, message) CLSLogv("[Error] %@", getVaList([message])) } static func fatal(error: Error) { let message = String(reflecting: error) os_log("%@", log: .default, type: .debug, message) Crashlytics.sharedInstance() .recordError(error as NSError) assertionFailure(message) } } LogΫϥε
!ZPJDIJUHZ Demo -PHTXJGUIUUQTHJTUHJUIVCDPNZPJDIJUHZBEBBEFGFBBCB "QQ%FMFHBUFTXJGUIUUQTHJTUHJUIVCDPNZPJDIJUHZFEBGBCGFCFBCDF 7JFX$POUSPMMFSTXJGUIUUQTHJTUHJUIVCDPNZPJDIJUHZFCBFGEECBBD
!ZPJDIJUHZ Demoͨ͜͠ͱ
!ZPJDIJUHZ Demoͨ͜͠ͱ
!ZPJDIJUHZ guard let something = something else { // Swallow
return } guard !array.isEmpty else { // Swallow return } guard let something = something else { Log.fatal(message: "something is nil unexpectedly.") return } guard !array.isEmpty else { Log.fatal(message: "array is empty.") return } ࠷ޙʹ ෆਖ਼ͳঢ়ଶΛҿΈࠐΜͰ͍ͨΒ࠷ѱͰϩάΛૹ͓ͬͯ͜͏ ݱࡏͷ࣮Ͱ͋Γ͑ͳͯ͘কདྷͷόάΛݕ͢ΔͨΊ
!ZPJDIJUHZ %BUF 4QFBLFS 5JUMF !UFOOUFOO (PʹΑΔJ04ΞϓϦͷ։ൃ !DIVHBO[Z ϝϧΧϦͰ࣮ࢪͨ͠աڈ࠷େنͷ"#ςετʮυϩϫʔWTԼλϒʯͷཪ
!LJUBTVLF *OUSPEVDJOHQSPUPCVGJO4XJGU !KBSJOPTVLF 64൛.FSDBSJΛ·Δ͝ͱ͔Β࡞Γͨ͠ !NPUPLJFF ݁ࠗࣜΛࢧٕ͑ͨज़'JSFCBTFΛ׆༻ͨ͠αʔόϨεJ04ΞϓϦέʔγϣϯ։ൃ !EUWE ϝϧΧϦΞοςΛࢧ͑ΔΦʔτϚτϯ !KPMMZKPFTUFS པΉ͔Βϓογϡ௨ͷ͍ํΛ͓Ζ͔ͦʹ͠ͳ͍Ͱ͘Εʂ ʙϓογϡ௨ͷදݱɺྺ࢙ɺ࠷৽ಈ·Ͱʙ Thank you .PSFGSPN BUJ04%$