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.7k
モバイルアプリで困らないエラーハンドリングとロギングのベストプラクティス
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
200
Dependency Injection Pattern for iOS App
yoichitgy
1
300
Dependency Injection Pattern for iOS Apps
yoichitgy
2
420
Practical Structure to Configure Dependency Injection in Swift for iOS
yoichitgy
1
540
Architecture and ReactorKit
yoichitgy
1
690
GDPRについて
yoichitgy
2
1.6k
More about Crashlytics and Less about GDPR ;)
yoichitgy
2
320
How to contribute to try! Swift Tokyo 2018
yoichitgy
0
95
Dependency Injection in Practice (iOSCon)
yoichitgy
0
500
Other Decks in Programming
See All in Programming
Understanding Apache Lucene - More than just full-text search
spinscale
0
130
AI駆動開発の本音 〜Claude Code並列開発で見えたエンジニアの新しい役割〜
hisuzuya
4
520
DevinとClaude Code、SREの現場で使い倒してみた件
karia
1
1.1k
maplibre-gl-layers - 地図に移動体たくさん表示したい
kekyo
PRO
0
290
コーディングルールの鮮度を保ちたい / keep-fresh-go-internal-conventions
handlename
0
210
AHC061解説
shun_pi
0
400
生成 AI 時代のスナップショットテストってやつを見せてあげますよ(α版)
ojun9
0
260
CDIの誤解しがちな仕様とその対処TIPS
futokiyo
0
220
SourceGeneratorのマーカー属性問題について
htkym
0
200
ふつうの Rubyist、ちいさなデバイス、大きな一年
bash0c7
0
1.1k
Claude Codeログ基盤の構築
giginet
PRO
7
3.4k
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
750
Featured
See All Featured
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
74
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.1k
How to train your dragon (web standard)
notwaldorf
97
6.6k
Believing is Seeing
oripsolob
1
86
A Soul's Torment
seathinner
5
2.5k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
150
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
290
AI: The stuff that nobody shows you
jnunemaker
PRO
3
450
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.5k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
110
Skip the Path - Find Your Career Trail
mkilby
1
85
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
1
160
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%$