iOSDC https://iosdc.jp/2016/c/node/116
僕は怠惰な人間です。プログラミングの大半はデバッグに時間を費やすと思っているので、なるべく早く原因に辿りついたり効率のよいデバッグライフを送りたいと常々思っています。 プリントデバッグもいいのですが Xcode には便利な機能が色々とあります。それらを使うことで簡単に原因を特定できるケースがあります。 visualize されるのは分かりやすいですよね。 それらを tips で紹介できたらなと思います。
2016/08/20 iOS Developers Conference Japan@dealforestToshihiro MorimotoXcodeͰշదͳσόοάϥΠϑΛ͍ٻΊΔ
View Slide
Έͳ͞Μ͜Μͳܦݧ͋Γ·ͤΜ͔ʁࣗݾհ
8PSLT
͍͟ϦϦʔε͞ΕΔͱ...9DPEF1MVHJO
ͦ͏Ͱ͢ɺצͷ͍͍Έͳ͞Μ͓͔ΓͰ͢Ͷ
Xcode 8 ͔ΒXcode Plugin ͕ಈ͔ͳ͘ͳΓ·ͨ͠
RIP Xcode Plugin
͍ɺ͜Ε͔ΒຊͰ͢
XcodeͰշదͳσόοάϥΠϑΛ͍ٻΊΔ
iOS ΤϯδχΞʹͱͬͯ Xcode ͱ
࢜ʹͱͬͯͷ
ྉཧਓʹͱͬͯͷแஸ
Xcode ͳͯ͘͠ iOS ։ൃͰ͖·ͤΜ
Xcode ͷػೳΛ׆༻͢Εσόοά͕վળ͞ΕΔ߹͕ଟʑ͋Γ·͢
ϓϩάϥϛϯάͷେσόοάͩͱࢥ͍ͬͯ·͢
ݪҼʹͨͲΓͭͨ͘Ίʹใ͕ଟ͍ʹӽͨ͜͠ͱ͋Γ·ͤΜ
ͱ͍͏͜ͱͰීஈ͍ͯ͠Δσόοάͷ tips Λհ͍͖͍ͯͨ͠ͱࢥ͍·͢
• Ϋϥογϡͨ͠Β AppDelegate ͩͬͨ• Ͳͷ ViewController ͔Θ͔Βͳ͍• ىಈ࣌ʹಛఆͷ ViewController ʹ͍ͨ͠• ࣮ػͷϩάϑΝΠϧΛऔಘ͍ͨ͠ຊͷ͓͠ͳ͕͖
Ϋϥογϡͨ͠Β AppDelegate ͩͬͨ
͘͠Ξηϯϒϥͩͬͨ
• Exception Breakpoint ΛՃ• Diagonostics Λઃఆղܾํ๏
Exception Breakpoint ΛՃ
Exception Breakpoint Λઃఆ͓ͯ͘͠ͱɹɹexception ͕ൃੜͨ͠λΠϛϯάͰ Break ͯ͘͠ΕΔException Breakpoint ΛՃ
্ͨͩ͠ख͑͘ͳ͍έʔε͋ͬͯException લఏͷίʔυ͕ॻ͔Ε͍ͯΔͱࠓճͷҙਤͱҧ͏λΠϛϯάͰ Break ͯ͠͠·͏Exception Breakpoint ΛՃ
্ͨͩ͠ख͑͘ͳ͍έʔε͋ͬͯException લఏͷίʔυ͕ॻ͔Ε͍ͯΔͱࠓճͷҙਤͱҧ͏λΠϛϯάͰ Break ͯ͠͠·͏ex).storyboard ͕ͳ͚Ε .nib ʹϑΥʔϧόοΫ͢Δ try ͰΩϟον͍ͯͯ͠ break ͯ͠͠·͏Exception Breakpoint ΛՃ
Diagonostics Λઃఆ
•ෆਖ਼ͳϝϞϦૢ࡞Λݕ•dynamic library ؔ࿈ͷϩΪϯά (dlopen, dlsym )Diagonostics Λઃఆ
Ͳ͏ઃఆ͍͍͔͔ͯ͠Βͳ͍…
ͦΜͳΈͳ͞ΜͷͨΊͷΦεεϝͷઃఆͰ͢ ɹɹʢXcode 7.3.1ʣ
ύϑΥʔϚϯε͕ؾʹͳΔ߹Enable Address Sanitizer ΛΦϑʹͯ͠Լ͍͞
(lldb) po self(lldb) memory history 0x61800000e080thread ... name = 'Memory allocated at'frame #0: 0x00000001051bba97 libclang_rt.asan_iossim_dynamic.dylib`wrap_calloc + 199frame #1: 0x00000001064362fd libobjc.A.dylib`class_createInstance + 84frame #2: 0x0000000106440dc7 libobjc.A.dylib`_objc_rootAlloc + 41frame #3: 0x00000001072d6d25 UIKit`-[UIClassSwapper initWithCoder:] + 175frame #4: 0x00000001074c731b UIKit`UINibDecoderDecodeObjectForValue + 683...Enable Address Sanitizer Λ༗ޮʹ͍ͯ͠Δͱ…
Ͳͷ ViewController ͔Θ͔Βͳ͍
मਖ਼ͨ͠ΓػೳՃ͠Α͏ͱࢥͬͨ࣌ʹͲͷ ViewController ͔Θ͔Βͳ͍Ͳͷ ViewController ͔Θ͔Βͳ͍
ͦΜͳܦݧ͋Γ·ͤΜ͔ʁʁͲͷ ViewController ͔Θ͔Βͳ͍
ͰɺͲ͏͍͏ঢ়گͰى͜Δͷͱ͔Ͳͷ ViewController ͔Θ͔Βͳ͍
• ৽͍͠ϓϩδΣΫτʹؔΘΓ࢝Ίͨ࣌• స৬͔ͨͬ͠ΓͰΑ͔͘Βͳ͍࣌ɹ ͳͲͳͲ…Ͳͷ ViewController ͔Θ͔Βͳ͍
ͱ͍͑ϦϞʔτͰ࡞ۀ͍ͯ͠ΔͱӦۀ࣌ؒ֎ʹɺΘ͟Θ͟ฉ͘ͷͳͱ…Ͳͷ ViewController ͔Θ͔Βͳ͍
Symbolic Breakpoint with action ΛͬͯviewWillAppear / viewDidLoad ͕࣮ߦ͞ΕͨλΠϛϯάͰϩάʹදࣔ͢Δղܾํ๏
Symbolic BreakpointObjCͷ߹ viewWillApper: viewDidLoad
(lldb) bt 0 // suggest* thread #1: tid = 0x10503c9, 0x00000001088569f4dealforest`ViewController.viewWillAppear(animated=false, self=0x000061800000e080)-> () + 20 at ViewController.swift:19, queue = 'com.apple.main-thread', stopreason = breakpoint 6.1(lldb) po "[viewWillAppear] - \(self)”// custom format"[viewWillAppear] - "Action - Debugger Command
viewDidLoad ͱ viewWillAppear Λઃఆ͠ͱ͚େମϩάʹग़ྗ͞ΕΔͣ
ཧ༝ͱͯ͠ ViewController Ͱ࣮͓͔ͯ͠ͳ͍ͱSymbolic Breakpoint ͕ݺΕͳ͍ͨΊͰ͢
viewDidLoad ͕ͳ͍͔͠Εͳ͍͠viewWillAppear ͕ͳ͍͔͠Εͳ͍Ͱ྆ํͳ͍ͷগͳ͍ͣ
ϩά͕ᓔಃ͍͠ͱײͨ࣌͡Breakpoint Λແޮʹ͢Δ͚ͩͰ͢
νʔϜͰڞ༗͍ͨ͠߹Breakpoint Λڞ༗͢Δ͜ͱ͕Ͱ͖·͢
͓·͚
ͳͥ bt 0 ͕͓͢͢Ίͳͷ͔ͱ͍͏ͱ
Xcode Plugin - KZLinkedConsole ͱ૬ੑ͕ͱ͍͍͔ͯΒͰ͢
krzysztofzablocki / KZLinkedConsole
(lldb) bt 0* thread #1: tid = 0x10503c9, 0x00000001088569f4dealforest`ViewController.viewWillAppear(animated=false,self=0x000061800000e080) -> () + 20 at ViewController.swift:19, queue ='com.apple.main-thread', stop reason = breakpoint 6.1Action - Debugger CommandϦϯΫʹͳΓλοϓ͢Δͱ։͚Δ
ىಈ࣌ʹಛఆͷ ViewController ʹ͍ͨ͠
ભҠ͕໘͍͘͞ը໘ͷػೳΛ։ൃ͢Δ͜ͱʹͳΓ·ͨ͠ىಈ࣌ʹಛఆͷ ViewController ʹ͍ͨ͠
σόοά͢Δͱ͖ʹमਖ਼ͯ͠࠶ىಈͦͷޙɺը໘·ͰભҠͯ͠…͜ΕΛ܁Γฦ͢ىಈ࣌ʹಛఆͷ ViewController ʹ͍ͨ͠
ΊΜͲ͘͘͞ͳ͍Ͱ͔͢ʁʁىಈ࣌ʹಛఆͷ ViewController ʹ͍ͨ͠
Environment Variables Λ͍ɹɹɹɹɹɹɹɹɹɹɹɹ֘͢Δ ViewController Λදࣔ͢Δղܾํ๏
DF_STORYBOARD_NAME = Main:settings
දࣔ͢ΔॲཧΛdidFinishLaunchingWithOptions ʹՃif let env = NSProcessInfo().environment["DF_STORYBOARD_NAME"] {let names = env.componentsSeparatedByString(":")if let storyboardName = names.first {let storyboard = UIStoryboard(name: storyboardName, bundle: nil)let controller: UIViewControllerif let identifier = names.last where identifier != storyboardName {controller = storyboard.instantiateViewControllerWithIdentifier(identifier)}else {controller = storyboard.instantiateInitialViewController()!}window?.rootViewController = controller}}
Xcode ͔Βىಈͨ࣌͠ͷΈ༗ޮApp Switcher Ͱ kill ͯ͠ىಈ͠ͳ͓ͤແޮʹͳΔEnvironment Variables Λ͏ϝϦοτ
Ұ࣌తͳذΛ࡞Γ͍ͨ࣌ʹͱͯศར
• ڧ੍తʹ logout• API ͷϦΫΤετઌΛมߋ• localhost:3000• proxy• ϩάϨϕϧͷΓସ͑Environment Variables ͷ͍ॴ
࣮ػͷϩάϑΝΠϧΛऔಘ͍ͨ͠
ࣗલͰग़ྗ͍ͯ͠Δϩά͘͠DBϑΝΠϧ(Realm, CoreData, SQLite…)ΛΈ͍ͨ࣌͋Γ·͢ΑͶʁ࣮ػͷϩάϑΝΠϧΛऔಘ͍ͨ͠
ͱ͍͑औಘ͠Α͏ͱࢥ͏ͱ݁ߏΊΜͲ͍࣮͘͞ػͷϩάϑΝΠϧΛऔಘ͍ͨ͠
• iExproler Λ͍ iPhone ΛϚϯτ͠औಘ• PC ʹܨ͗ Xcode Ͱ Container Λऔಘɹɹɹɹ(͜ͷ߹ɺ͕ࣗՃೖ͍ͯ͠ΔνʔϜͷΞϓϦͷΈͰ͢)࣮ػͷϩάϑΝΠϧΛऔಘ͍ͨ͠
໘͍͘͞Ͱ͢Ͷ…ͬͱؾܰʹ͍ͨ͠ͷͰ࣮͢ػͷϩάϑΝΠϧΛऔಘ͍ͨ͠
LLDB Λͬͯ֘͢ΔϑΝΠϧΛ Slack ૹ৴ղܾํ๏
DEMO
(lldb) slack “Documents/default.realm”Please run ‘continue’(lldb) continueProcess 25152 resumingupload successSlack ʹϑΝΠϧΛૹ৴
Slack Ͱड͚औͬͨ࣌ͷը૾
ศརͰ͠ΐʁʁ
͍͍ͨͰ͢ΑͶʁʁ
https://gist.github.com/dealforest/702a848ba0a7a64b139985f5cad885f0
ίϚϯυΛಡΈࠐΉ$ cat ~/.lldbinit…command script import /slack.py
And more…
• Xcode Functions• memory visualizer• Xcode Plugin• LLDB• p, po, frame variable• watchpoint• facebook/chiselAnd more
• Xcode Settings- Diagonostics- Environment Variables• Breakpoint- Exception Breakpoint- Symbolic Breakpoint• LLDBRecap
গ͠ͰΈͳ͞ΜͷσόοάαΠΫϧ͕ɹɹɹɹշదʹͳΕ͍Ͱ͢
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠
͜ͷΑ͏ͳσόοάʹ·ͭΘΔΛɹɹɹɹମܥཱͯͯձࣾͰ͢Α͏ͳ͜ͱ ɹɹɹɹ͍ͯ͠ΔͷͰڵຯ͋Δํ͕͚Լ͍͞#એ