Under the Radar

Under the Radar 80: Debugging


00:00:00   welcome to under the radar a show about

00:00:02   independent iOS app development I'm

00:00:04   Marco Arment and I'm David Smith under

00:00:07   the radar is never longer than 30

00:00:08   minutes so let's get started so today we

00:00:12   wanted to dive into everybody's favorite

00:00:15   pastime as a developer and that is

00:00:18   debugging it is a topic that I think we

00:00:22   probably it's fun of weird in some ways

00:00:25   I think I probably spend at least half

00:00:28   if not a majority of my time in

00:00:30   development debugging code that I ride

00:00:32   yet in most of my like actual formal

00:00:36   preparation for being a software

00:00:38   engineer there was very very little time

00:00:40   and attention spent on it like almost

00:00:42   all of my classes and things are all

00:00:43   about focused on the actual development

00:00:46   in the architecture side of things

00:00:48   whereas the reality is we spend most of

00:00:50   our time you know fixing the problems

00:00:52   and issues that arise in our apps and

00:00:55   this year these can range from all kinds

00:00:57   of you know to different levels there's

00:00:59   the kind of while you're developing

00:01:01   debugging process where you know you

00:01:03   write some code you you know hit build

00:01:05   and run and you see if it works and if

00:01:08   it doesn't you try and work out why

00:01:09   there's the you know the act the sort of

00:01:12   more subtle something happens every now

00:01:15   and then and you're not really sure why

00:01:16   and you try and track that down and then

00:01:19   there's the you know you getting crash

00:01:21   reports or bug reports from customers in

00:01:23   the field and then you have to try and

00:01:25   track those down which is even more

00:01:27   exciting and challenging but in all of

00:01:31   them I think there is an element of you

00:01:34   know debugging is essentially you have

00:01:36   you sort of identify that there's some

00:01:38   problem you then try and reproduce that

00:01:42   problem in a way that you can then

00:01:44   observe that problem then you try and

00:01:48   isolate where and the actual you know

00:01:50   program that is happening and then you

00:01:52   can try and fix it and you kind of go

00:01:54   through this cycle of you know you

00:01:55   identify it you we produce it you

00:02:00   isolate it and then you can fix it and

00:02:01   you kind of cycle through that or at

00:02:03   least is the process that I tend to take

00:02:04   because if I don't go through each of

00:02:07   those steps I find that it's very hard

00:02:09   to actually make progress I mean if you

00:02:10   can't you know some bugs really are by

00:02:13   their nature

00:02:13   kind of hard to reproduce and if that's

00:02:15   the case like you know that's still a

00:02:17   bug and it's so problematic but you know

00:02:20   if I get a bug report that I can't

00:02:22   reproduce in any way

00:02:23   it's just as the same in some ways is

00:02:25   not having that bug report in the first

00:02:27   place because I can't do anything with

00:02:28   that information if I can't reproduce it

00:02:30   so you know my first step is always

00:02:32   let's reproduce this and then you know

00:02:34   this try and find the part of code and I

00:02:36   think having been a professional

00:02:39   developer for enough years now like I

00:02:41   feel like I have a better sort of sense

00:02:44   for where the bugs might be hiding you

00:02:46   know it's like we I've seen every you

00:02:49   know not every bug but I've seen a lot

00:02:50   of Fugs before and you kind of get this

00:02:52   sense of like huh you know this is it

00:02:54   this looks like this is a you know and

00:02:57   off by one error this is this looks like

00:02:59   this is a in you know cache and

00:03:01   validation error this looks like you

00:03:03   know I'm writing something incorrectly

00:03:04   here or I forgot a case in a switch

00:03:07   statement like you kind of get this

00:03:08   feeling for it and then you can kind of

00:03:10   go running around trying to find it and

00:03:12   of course there's also I guess the other

00:03:13   kind of debugging which is even super

00:03:15   fun which is where there's a bug in the

00:03:17   OS that you you know where your code is

00:03:21   all doing the right thing but then

00:03:23   you're getting weird results from the OS

00:03:26   and so that's an even more fun you know

00:03:28   fun line of debugging where you kind of

00:03:30   get the sense of at a certain you keep

00:03:32   going down and farther and farther down

00:03:33   the rabbit hole until eventually you're

00:03:35   like hit a brick wall at the end of it

00:03:36   you're like alright well I guess I file

00:03:39   a bug yeah and that's you know it's it's

00:03:43   often easy for us to jump to well this

00:03:47   must be a bug in the OS or my favorite

00:03:49   one this must be a bug in the compiler

00:03:50   or something like that when we can't

00:03:53   figure it out that is for the vast

00:03:56   majority of bugs that we face as

00:03:58   programmers that is almost never the

00:04:00   case it like first of all you are

00:04:03   unlikely to ever have a bug in the

00:04:04   compiler actually affect you and you

00:04:07   know as you go up the stack of you know

00:04:09   things that you're relying on like the

00:04:11   OS does have bugs libraries that you're

00:04:14   using will have bugs but if you run into

00:04:17   something in your app that that seems

00:04:20   like a bug and you were tempted to blame

00:04:22   the OS or a library or something like

00:04:25   that really make sure

00:04:27   that you can't figure out that it's your

00:04:29   bug first because chances are very very

00:04:32   good it's probably your bug the vast

00:04:35   majority of the time of those cases it

00:04:37   will really be your bug it's only a

00:04:39   question of whether you can find it but

00:04:40   don't just say oh well it's a bug in the

00:04:42   OS I guess I got a s I'll just deal with

00:04:44   this or move on or yell at them really

00:04:47   make sure it's not your bug first

00:04:49   because again the odds are strongly in

00:04:51   favor of it being yours yeah and then

00:04:54   because the reality is like most of our

00:04:56   time at least in these in my experience

00:04:57   like dealing with bugs I it's almost

00:05:00   always something I forgot to do or a

00:05:03   case that I forgot to consider when I'm

00:05:05   just originally doing it like in not

00:05:08   necessarily out of like laziness even

00:05:11   like sometimes it's that you know

00:05:12   sometimes you have the always classic

00:05:13   like you know you see an example where

00:05:16   it's like if error doesn't equal nil

00:05:18   then do something with it

00:05:20   it's like and then if you don't actually

00:05:22   do anything when eventually you do run

00:05:24   into the situation where the error is

00:05:25   not nil then all of a sudden things

00:05:27   break and you know that there's that

00:05:28   kind of laziness but more often it's

00:05:30   just like you forgot to do something and

00:05:32   then it comes back to bite you and I

00:05:34   feel like the what is it I think there

00:05:37   was a you know maybe maybe have been an

00:05:40   xkcd cartoon about this where it's sort

00:05:42   of that the stages of debugging where

00:05:44   you go from like it's like oh it's you

00:05:47   know you get a bug report you know like

00:05:48   oh no that can't be right I'm sure this

00:05:50   is I'm sure my code is good and then you

00:05:51   kind of like no it's actually it's

00:05:53   actually broken and then you go to the

00:05:54   like how did this ever work yeah okay

00:05:57   how on earth did this even work we you

00:05:59   you amazing how when you look back at

00:06:02   your own code you know this is think

00:06:04   code that you wrote with your own you

00:06:06   know your own hands on a keyboard you

00:06:07   put this into the empty into the into

00:06:09   Xcode you come back and look at your

00:06:11   like how when earth what am i doing like

00:06:13   and I feel like that is the hardest part

00:06:15   and or why do bucking is so hard is it's

00:06:18   you have to recreate all of this sort of

00:06:22   state and information that went into the

00:06:24   creation of the code hold that in your

00:06:26   mind and then run it through a scenario

00:06:29   that's happening you know and to then

00:06:31   see why it's doing something weird and

00:06:33   very often I find like the hardest thing

00:06:35   is to try and understand even what the

00:06:37   code is trying to do in the first place

00:06:39   or like why there's this weird exception

00:06:41   you know that was introduced there you

00:06:43   know your yours or you know decades ago

00:06:46   and you're like huh I wonder why I did

00:06:48   that I don't know anymore

00:06:50   and that's you know makes debugging

00:06:51   really really hard yeah and this is you

00:06:54   know it's also a major argument for

00:06:56   keeping things simple and not that

00:06:59   clever in the first place and yeah as we

00:07:02   talked about I think a while ago now you

00:07:04   know like I try to avoid overly clever

00:07:06   code Styles things like you know using

00:07:09   using really dense short hands or really

00:07:12   clever mechanics you know things like

00:07:16   generics in like you know Swift like

00:07:18   that kind of thing I'm like we you kind

00:07:19   of use like overly clever complex

00:07:22   language features or constructs where it

00:07:26   looks really cool and you feel really

00:07:27   smart when you do it but when you have

00:07:29   to come back and debug code you know in

00:07:32   six months and you have totally

00:07:34   forgotten what led you to to write that

00:07:37   and you and you've forgotten the

00:07:38   cleverness behind it and you have to

00:07:40   figure it out by looking at it or or you

00:07:42   know figuring out by by its effects it's

00:07:44   often very very hard to do that and you

00:07:46   know like you know you you often as a

00:07:49   programmer you you might eventually hear

00:07:51   the wisdom of like write code for

00:07:54   someone else to read but but really what

00:07:56   you should be doing is writing code for

00:07:58   yourself in three weeks to read because

00:08:01   you will have probably forgotten by then

00:08:03   why you did what you did so if you keep

00:08:06   things simple from the beginning and not

00:08:08   be too overly clever with the way your

00:08:10   right things and and make things you

00:08:12   know straightforward to read and to you

00:08:15   know kind of self document then you will

00:08:17   be doing yourself a huge favor

00:08:19   documentation you know separate

00:08:21   documentation can help with some of

00:08:23   these things but I found in practice

00:08:25   that maybe it's just me I don't document

00:08:27   things that well I try to just write

00:08:29   things that are that are obvious when

00:08:31   you look at them and that that you know

00:08:32   just have good names and straightforward

00:08:34   approaches and that tends to work very

00:08:37   well and you know that can never be out

00:08:38   of date because it's the code itself and

00:08:41   then for for minimizing bugs to begin

00:08:45   with I think it's it's again very

00:08:47   important not to be too clever and and

00:08:49   to realize you know for me many of my

00:08:52   bugs come from

00:08:54   quick workarounds or quick hacks that I

00:08:57   do when I encounter some other bug and

00:09:00   and so one great example of this then

00:09:03   that I'm sure many iOS programmers face

00:09:05   is whenever you are doing something in

00:09:09   in like a launch loop or or in in a UI

00:09:13   you know response or something and

00:09:15   there's some weird behavior that or some

00:09:18   weird precondition that you can't quite

00:09:20   accommodate in a straightforward way so

00:09:23   you just dispatch async to the next run

00:09:26   loop of the main queue and you say all

00:09:28   right dispatch async got to make you do

00:09:30   this thing on the next run and that's a

00:09:33   really nice quick way to to avoid a lot

00:09:36   of a lot of like you know weird

00:09:38   complexity or obvious bugs as you're

00:09:41   developing but I have found in almost

00:09:43   every case that using a dispatch async

00:09:47   is almost always a bad idea like when

00:09:50   you're just like I'm deferring work till

00:09:52   the till later on the main queue or

00:09:53   something like obviously there are uses

00:09:55   where it where it's fine but like what

00:09:57   if that's your approach to solve a

00:09:58   problem then you get into concurrency

00:10:01   bugs

00:10:02   and weird weird conditions there that

00:10:05   are really hard to fix and diagnose and

00:10:09   reproduce and it again it's like one of

00:10:13   those areas where it seems like a clever

00:10:16   thing when you're writing it and and in

00:10:19   the case of like bug avoidance like it

00:10:21   seems like oh this will be a quick fix

00:10:22   for this weird little bug I'll just wrap

00:10:24   it in dispatch async and that will that

00:10:26   will fix the problem but then you

00:10:28   introduce all these weird other problems

00:10:31   that might be non-obvious and those

00:10:33   those become very hard to debug so in

00:10:38   addition to keeping code simple as you

00:10:40   write it for the purposes of debugging I

00:10:42   also would strongly recommend avoiding

00:10:45   concurrency if you can and avoiding

00:10:47   playing with with threads and queues

00:10:50   when when not necessary or when not

00:10:53   warranted because I feel like what

00:10:55   you're doing there I mean I'm very

00:10:56   guilty of that thing there I've done the

00:10:59   you know dispatch async fix probably a

00:11:02   hundred times 200 times my career like

00:11:05   all the time and I cannot I cannot

00:11:06   overstate how men

00:11:08   bugs that I've had to fix end up being a

00:11:11   poorly used dispatch async yeah I think

00:11:14   what the reality is what you're doing

00:11:16   and this is maybe a maturity thing but

00:11:19   it's the quiet sea understanding that

00:11:20   like when I do that now I understand

00:11:22   that I'm not fixing the problem I'm

00:11:24   changing the bug from whatever it is say

00:11:27   see I said a bug that happens you know

00:11:29   one out of every hundred times the app

00:11:31   is of the app runs and you know that's a

00:11:34   problem you know 1% of users are hitting

00:11:35   this issue I wrap it in dispatch async

00:11:37   what I'm doing is not removing that

00:11:40   problem what I'm doing is changing it

00:11:42   into a like 1 in 10,000 bug which is

00:11:45   better but also incredibly difficult now

00:11:48   to actually like properly fix and

00:11:51   diagnose and reproduce etc etc like it

00:11:54   is the kind of fix where it isn't

00:11:57   actually solving it it's just making it

00:11:58   less likely which sometimes you know

00:12:00   pragmatically I've you know there I'm

00:12:02   sure there are many places in you know

00:12:03   my shipping apps where I have that and

00:12:05   it's just one it's like a conscious

00:12:06   choice that you're just like well the

00:12:08   actual fix is too hard or would require

00:12:11   a massive refactoring or some kind of

00:12:13   you know thing where you can make this

00:12:15   trade-off in choice and you say you know

00:12:16   like I'm just gonna fix this by patching

00:12:18   it and I know that what I'm doing is

00:12:20   gonna cause a problem for me down the

00:12:22   road I know that I'm you know there is

00:12:24   this bug is hasn't magically disappeared

00:12:26   as a result of this but like it's a

00:12:28   conscious choice and that's a balance

00:12:30   but yeah ultimately you know the most

00:12:34   when you're writing the code you're kind

00:12:35   of trying to do your future self a favor

00:12:36   as much as you can because I think one

00:12:39   of the things that I struggle with - and

00:12:40   I'm writing code is the realization that

00:12:42   I all of these things that seem obvious

00:12:45   to me when I'm writing the code because

00:12:48   I'm in a mindset where I'm focused

00:12:50   entirely on whatever the solving this

00:12:51   problem is like there's all these things

00:12:52   that just seem obvious like of course

00:12:54   you know like this is the way this works

00:12:56   you know that's why this is set up this

00:12:58   way this value will you know will always

00:13:00   transform from this to this like there's

00:13:02   all these things that seem obvious and

00:13:03   then in the future they're entirely

00:13:06   non-obvious

00:13:07   and the didn't think the biggest

00:13:10   difficulty I have with things like

00:13:11   documentation is that it's it kind of

00:13:15   impossible to know what your future self

00:13:17   is going to want to know

00:13:20   because everything seems obvious and

00:13:23   kind of trivial at in the present and so

00:13:27   like I think I'm kind of like you I'd

00:13:29   tend to only document code in my apps

00:13:31   that where I'm doing something that is

00:13:33   clearly weird or like strange you know

00:13:37   where you have some kind of magic number

00:13:39   it's you have to introduce into

00:13:41   something worth like I know why am i

00:13:43   multiplying this value by one point six

00:13:45   three two like there's a reason for that

00:13:47   and if there is like you know that's the

00:13:49   kind of thing that you write down but

00:13:51   otherwise you end up with like writing

00:13:52   your program twice if you're overly

00:13:54   documenting it so as you know as much as

00:13:56   when I'm debugging I kind of wish my

00:13:58   past self had written all this stuff

00:14:00   down

00:14:00   the reality is my past I wouldn't

00:14:03   actually know what I need to know right

00:14:04   now because if they did they could have

00:14:06   just write in you know made the code

00:14:07   more obvious or clear in the first place

00:14:09   probably or these that's what I tell

00:14:11   myself we respond to this week by

00:14:15   Pingdom start monitoring your websites

00:14:17   in servers today at Pingdom comm slash

00:14:20   radar you get a 14-day free trial I'm

00:14:22   gonna use code radar at checkout you got

00:14:24   20% off your first invoice Pingdom is a

00:14:27   wonderful monitoring service they are

00:14:30   focused on making the web faster and

00:14:32   more reliable for everyone who has a

00:14:34   site because they offer powerful easy to

00:14:37   use monitoring tools and services so if

00:14:39   you're a premium user you can monitor

00:14:41   the availability and performance of your

00:14:42   servers your databases or your website

00:14:45   and it's so easy to do they test from

00:14:48   more than 70 global test servers and

00:14:50   they can they can emulate visits to your

00:14:52   site as often as every minute and they

00:14:54   can do cool things like cookies and

00:14:56   logins and everything else too because

00:14:57   you know these days websites are

00:14:59   becoming more and more sophisticated and

00:15:00   very often include multiple different

00:15:02   parts with several different

00:15:04   dependencies maybe you dependent on

00:15:05   external service or maybe only the login

00:15:07   screen does this one thing in your code

00:15:09   and you need to check all these things

00:15:11   and you can do all that with Pingdom

00:15:13   with and loads more in addition to that

00:15:15   too they can make it possible to monitor

00:15:17   the availability of all these key

00:15:18   interactions people have with your site

00:15:20   because you know a lot of times it's

00:15:22   more complex than your site is up or

00:15:24   your site is down so stuff breaks on the

00:15:27   internet all the time Pingdom knows this

00:15:29   they detect around 13 million outages a

00:15:31   month

00:15:32   so regardless of whether you have a

00:15:33   small website or you're managing a whole

00:15:35   infrastructure it is very important to

00:15:37   monitor the availability and performance

00:15:39   and all in Pingdom when it goes down

00:15:41   they alert you in any way you want you

00:15:44   can have text messages you can have push

00:15:46   notifications emails it's so

00:15:48   configurable we've even used it in the

00:15:50   past to monitor other people's websites

00:15:52   like David and I have both independently

00:15:54   used it to monitor the WDC page for

00:15:57   changes and like in the past when it was

00:15:59   really important to know when WTC

00:16:01   tickets went on sale I've used Pingdom

00:16:02   for a very long time

00:16:03   highly recommended check it out today

00:16:05   and you will be the first to know when

00:16:07   your site is down or being too slow so

00:16:10   go to Pingdom comm slash radar for a

00:16:13   14-day free trial and use code radar to

00:16:16   get 20% off your first invoice thank you

00:16:19   very much to Pingdom for their support

00:16:20   of this show and relay FM so the other

00:16:24   thing is probably worth diving into a

00:16:25   little bit too is the way in which we

00:16:27   actually do debugging because I maybe

00:16:31   it's you know maybe it's a shocking real

00:16:33   revelation but I am I believe what is

00:16:35   technically called a caveman debugger

00:16:37   the printf debugging I do all of my

00:16:41   debugging using you know NSLog yep in

00:16:46   the console which I you know I think is

00:16:47   often disparagingly referred to as

00:16:49   caveman debugging which is fine I'm sure

00:16:51   there are better ways to do that and I

00:16:53   mean every now and then I'll go to WDC

00:16:55   session where they're talking about all

00:16:57   the crazy things you can do in you know

00:16:59   in Xcode where you can set conditional

00:17:01   breakpoints and you know all this kind

00:17:03   of really clever stuff and in the end

00:17:05   what I always do is just INF just NS

00:17:07   logging tons of data to the console

00:17:10   because it's it's one of those things

00:17:13   where most of what debugging is trying

00:17:15   to do is it's like you're trying to

00:17:17   unwind the state machine that is your

00:17:19   app or you're trying to work out we know

00:17:21   it's like your app is in this probably

00:17:23   you're in a good state then something

00:17:25   happens and you're in a bad state like

00:17:27   that is you know at a very high level

00:17:28   that is what a bug is and what you're

00:17:31   trying to do is identify that we know

00:17:33   what point it's going from that good

00:17:36   state to that bad state like what is

00:17:37   happening there and you know I mean I've

00:17:40   been professionally developing for 17

00:17:43   years now or something and I still like

00:17:44   that the most

00:17:45   effective and powerful tool is just n s

00:17:47   logs everywhere and you get kind of good

00:17:51   at it like I'm I can identify and find

00:17:53   things fairly quickly this way because

00:17:55   you kind of get the sense of you know

00:17:56   you're a you're trying to isolate where

00:17:58   in the code it's happening and so you'll

00:18:00   end up putting ns logs you know in

00:18:02   different in different parts of your app

00:18:04   that you think might be part of it and

00:18:05   trying to work out which ones getting

00:18:07   you know which code is getting hit when

00:18:09   you when you do it and then something

00:18:12   that I also find really helpful is when

00:18:14   I take I format my NS logs as tab

00:18:19   delimited text so like often will have

00:18:22   like several variables that I'm trying

00:18:23   to observe and watch and I NS log those

00:18:27   as you know a tab delimited set of

00:18:30   strings because then I can take the

00:18:31   output from the console and I can copy

00:18:33   paste that into Excel and it'll put it

00:18:35   into columns for me that's interesting

00:18:38   and you can then you know you can take

00:18:41   that data and then look at it over

00:18:43   multiple runs and you can start you know

00:18:44   it's a way to actually make the day and

00:18:46   make it into something that's useful and

00:18:47   you know like at least for me in the way

00:18:51   that my mind works that's how I debug

00:18:52   the best is when I'm taking the state

00:18:54   I'm taking something out of the console

00:18:55   looking at it often in Excel and it

00:18:58   would kind of fall finding the pattern

00:18:59   finding the thing and then I can

00:19:01   actually go and fix it and like I don't

00:19:05   know if that works for me

00:19:06   and you know I I sometimes I feel bad

00:19:10   about it I think they have all these

00:19:11   really powerful and clever tools but the

00:19:14   reality is I think the hardest part too

00:19:16   is that so much of these this kind of so

00:19:19   much of debugging is like the hardest

00:19:20   part is often the reproduction part and

00:19:23   getting everything like it's hard to

00:19:26   observe these issues sometimes and so

00:19:28   like the nice thing about a console.log

00:19:29   is that you can have those running

00:19:32   without being attached to the debug

00:19:34   server for example like you can have

00:19:37   that you know you can you can create

00:19:39   these situations where these things

00:19:40   happen sometimes in like sometimes it

00:19:42   gets really awkward to have your a to

00:19:44   have your app attach the debugger

00:19:46   sometimes when it is attached the

00:19:48   debugger the app goes the bug goes away

00:19:49   like there's lots of weird situations in

00:19:52   issue square NSLog debugging is the best

00:19:55   but I'm very aware that by doing it that

00:19:58   way I am

00:19:59   you know not taking advantage of more

00:20:00   sophisticated tools but I know for

00:20:02   myself like that's what works yeah I

00:20:05   mean and it there's also there's lots of

00:20:07   different kinds of bugs and and you know

00:20:09   a lot of these different methods are

00:20:11   more or less suitable to different ones

00:20:13   like you know for example NS log

00:20:14   debugging which I do a lot myself is

00:20:18   it's it's not necessarily the best

00:20:20   option if you have like like I'd like

00:20:24   kind of nitty-gritty like code level bug

00:20:25   that this function isn't always

00:20:26   returning the right value like for that

00:20:28   I prefer to use conditional breakpoints

00:20:29   so I can see like you know whenever this

00:20:31   value is something out of whack stop

00:20:33   here and then I will inspect the stuff

00:20:34   around it but you know and it's log

00:20:37   debugging is a lot more helpful for

00:20:39   things like you know larger systems

00:20:42   interacting with each other many kind of

00:20:44   you know large operation the concurrency

00:20:47   things were like you're not really sure

00:20:48   where the bugs might be but you kind of

00:20:50   want to get a good idea of of what is

00:20:53   going on in the system it's also NSLog

00:20:55   debugging is also very very helpful in

00:20:57   situations in which the debugger itself

00:21:00   is impractically slow to do things so a

00:21:04   lot of swift context this is the case

00:21:06   from what I've heard it's also very much

00:21:08   the case when you're debugging on device

00:21:10   on the watch because like then like the

00:21:13   round-trip between your computer running

00:21:15   Xcode and the phone and the slow watch

00:21:18   hardware like trying to try to break

00:21:19   watch apps

00:21:20   you know like with breakpoints and

00:21:22   inspect local variables around and you

00:21:24   know running things in the in the debug

00:21:26   command line is so slow on the like when

00:21:29   doing things on the watch that sometimes

00:21:31   it's better off to just do something you

00:21:32   know doot-doot-doot a different way do

00:21:34   printf debugging or whatever else for me

00:21:36   it's also I also debug very differently

00:21:38   if I'm looking at a crash report versus

00:21:41   some kind of behavior in the app that

00:21:43   I'm catching live it's it's very

00:21:45   important to to look in iTunes Connect

00:21:49   and to look at the or a you know rather

00:21:51   I guess now it's in the organizer in

00:21:52   Xcode to look at the crash report that

00:21:56   Apple's getting for you you know look at

00:21:58   look at what's being gathered there

00:21:59   there's a whole lot of different

00:22:01   problems that your app can have in the

00:22:03   wild and the fact that we can get our

00:22:05   apps it's that we can get our crash

00:22:07   reports basically all the time from

00:22:09   Apple that like whenever an app crashes

00:22:11   we get notified

00:22:12   about that that's pretty awesome and of

00:22:14   course also lots of different other

00:22:15   services as well but there are some

00:22:17   types of crashes that only apples crash

00:22:20   logs will generally reliably be able to

00:22:22   report to you that includes things like

00:22:24   if i OS kills your app for some reason

00:22:27   that isn't necessarily a crash but if

00:22:30   your app is getting killed in the

00:22:30   background or something or if your

00:22:32   extensions are getting killed

00:22:34   then that's things that iOS can can

00:22:36   provide very useful feedback to if you

00:22:38   look for it and that's all in the Xcode

00:22:40   organizer and one of the things I can

00:22:42   recommend highly is look at those and a

00:22:46   lot of times the organizer won't tell

00:22:47   you like if you get like in my I was

00:22:50   just spending a lot of time debugging

00:22:51   crashes and my today widget or my widget

00:22:53   I guess and if you look at just the

00:22:56   crash log it's not very helpful in the

00:22:58   organizer but if you right-click and

00:23:01   show and finder on that crash and you

00:23:03   dive into the bundle and you can get the

00:23:05   raw crash logs that are inside of that

00:23:07   bundle when you look at the raw logs you

00:23:09   can get a termination code and a lot of

00:23:11   times that is springboard telling you

00:23:13   something and there's a great technical

00:23:15   note tn 21:51 understanding and

00:23:18   analyzing application crash reports and

00:23:20   this tells you all the crazy codes that

00:23:23   your app might be killed with so one of

00:23:25   the things is that I was facing is I was

00:23:27   my extension was accessing the sequel

00:23:30   Lite database in the shared app group

00:23:32   container I don't recommend doing this

00:23:34   now but now I know better

00:23:37   but if you are accessing an SQLite

00:23:39   database in a shared container in an

00:23:41   extension at the time that the OS

00:23:43   suspends you it will kill your app with

00:23:46   a certain code that says deadlock in hex

00:23:48   and if you didn't look at this document

00:23:50   and if you didn't find that crash report

00:23:52   and find that code and if you didn't

00:23:54   then look at this document to see that

00:23:56   what that means what it tells you right

00:23:57   here

00:23:58   it's un terminated by the US cause it

00:23:59   held on to a file lock or sequel like

00:24:01   database during suspension and I didn't

00:24:04   like you know and before I found all

00:24:06   this out I just didn't know why my

00:24:08   extension just kept crashing for

00:24:10   everybody and people kept reporting

00:24:11   things like hey your app is crashing in

00:24:13   the background for some reason getting

00:24:14   all these logs on my phone what's going

00:24:15   on iOS tells you these things like it's

00:24:18   telling you useful information here and

00:24:19   so if you if you look at those crash

00:24:23   logs in the Xcode organizer and if you

00:24:25   look up what these

00:24:26   for you know termination codes mean

00:24:27   you'll probably find out something

00:24:29   useful and and this is all like and and

00:24:32   we have wonderful things like if you're

00:24:34   kind of wondering whether you fixed a

00:24:36   rare crash or not you can look at the

00:24:38   analytics section of iTunes Connect and

00:24:40   it will graph for you how many crashes

00:24:43   per day your app is having and you can

00:24:45   cut and it marks on the graph where your

00:24:48   updates occur so you can say oh look

00:24:49   when when this update was released the

00:24:53   crashes dropped by half so the thing I

00:24:55   fixed I probably fit the thing I think I

00:24:58   fixed I probably did fix there's all

00:25:00   sorts of useful things you can get from

00:25:02   crash logs and things of that and and

00:25:04   one of the reasons why I do also as I

00:25:07   said earlier kind of recommend against

00:25:09   unnecessary use of dispatch async is

00:25:11   because that makes your crash logs less

00:25:13   useful to you because it it usually the

00:25:16   crash logs will not report where the

00:25:19   block was dispatched from some of the

00:25:22   more advanced ones like hockey a try to

00:25:24   do this and they have mixed degrees of

00:25:26   success in my experience and so if your

00:25:29   code is simpler than any crash log you

00:25:32   get will also be more useful to you yeah

00:25:35   if you crash logs are definitely like a

00:25:38   great source for us so much of this

00:25:40   stuff and I feel like in general I will

00:25:42   say that Xcode as much as I don't use

00:25:45   all of its tools like some of this stuff

00:25:46   that you're talking about if going into

00:25:48   the organizer like there's some really

00:25:49   useful you need tools that we have at

00:25:53   our head at our you know sort of at our

00:25:55   disposal to be tracking some of this

00:25:56   stuff down now which I don't think we we

00:25:58   had before I mean it makes me think even

00:26:00   of one of the other tools that I use a

00:26:02   lot in debugging in a strange way is

00:26:05   version control sin specifically get

00:26:09   blame is often incredibly helpful in

00:26:12   trying to track down weird situations in

00:26:16   in my apps beware you know code is doing

00:26:20   something weird and I'm trying to work

00:26:21   out why I structured it in the way I

00:26:23   structured it and this is something that

00:26:24   I love in Xcode where you can go into

00:26:26   the top right where you go into the

00:26:28   source control thing and you can do

00:26:29   blame and it will show you all of you

00:26:32   knows for every line of code in your app

00:26:34   it'll show you which commits that line

00:26:36   of code was introduced into your

00:26:39   with and so you often will end up

00:26:41   happening there it's like by using that

00:26:43   view I can be a see like huh that's

00:26:44   weird

00:26:45   you know here's this one random line of

00:26:47   code that is left over from an old

00:26:49   version that everything else was updated

00:26:51   or you know situations like that and you

00:26:54   know Xcode is really and then you can

00:26:55   not think if you double-click on it you

00:26:57   know show you that commit and I'll show

00:26:58   you the relevant how that you know how

00:27:00   that file a line of how that how that

00:27:02   file changed with that commit and that's

00:27:05   another example of one of these little

00:27:06   tools in Xcode where it's like it helps

00:27:08   you understand what's going on in the

00:27:10   same way that yeah like those that's a

00:27:12   really great one I mean I love in their

00:27:13   crash logs were you know that can help

00:27:15   you take you right to where the crash

00:27:17   happened rather than sitting there and

00:27:19   you know trying to you know work out

00:27:21   which we know is if this crash happened

00:27:24   in this you know and this this file on

00:27:25   this line number like well I mean that's

00:27:28   useful but it's also much way more

00:27:30   useful to just take me to that line

00:27:31   number so there's definitely some great

00:27:33   tools in Xcode I think make a lot of

00:27:35   debugging a lot simpler and I'm very

00:27:37   grateful for I would also say when

00:27:40   you're when you're running your app and

00:27:41   you're trying to figure out maybe maybe

00:27:42   what's going on with a bug always watch

00:27:44   that that pain in Xcode shows you the

00:27:47   running CPU usage and memory of the app

00:27:50   and of course you can go into

00:27:51   instruments and get you know like a more

00:27:52   fine-grained version of this but like

00:27:54   yesterday there was this really tricky

00:27:55   bug that I could not figure out that the

00:27:57   app too started behaving really weirdly

00:27:58   when loading episodes of a certain

00:28:01   podcast and it like really weirdly and

00:28:03   it would eventually disconnect from

00:28:05   Xcode it was a massive massive weird bug

00:28:07   and springboard crash and what led me to

00:28:10   the solution was that I was I happen to

00:28:13   be glancing at that pain that was

00:28:14   showing me that the resource graphs in

00:28:16   Xcode that would during one of the runs

00:28:18   and I noticed that right before it

00:28:20   crashed memory usage skyrocketed all the

00:28:23   way up to like a gig and then everything

00:28:25   freaked out and blew up and so then I

00:28:27   was able to sit to say hey wait a minute

00:28:29   that's unusual that stands out let me

00:28:32   run it under the the allocations

00:28:33   instrument run that can show you where

00:28:36   all your memory is being used and I did

00:28:39   I so I did that and found out figured

00:28:42   out what the bug was within like a half

00:28:43   hour after that this is a bug has been

00:28:44   bothering me for weeks I couldn't figure

00:28:46   it out and then within a half hour of

00:28:48   noticing hey this thing is out of the

00:28:49   ordinary on the memory meter here

00:28:51   I had the fix so like you know use the

00:28:54   tools that are available to you when we

00:28:57   know when appropriate or just use NS log

00:28:59   and printf debugging everywhere yeah and

00:29:02   I mean what that you would you down

00:29:04   there there was one thing that I will

00:29:05   say that I love about debugging is that

00:29:07   so often you get to the end and there's

00:29:09   like a relatively straightforward

00:29:10   solution that fixes the problem and like

00:29:13   that is one of the greatest joys of

00:29:15   being a soft software development when

00:29:16   you like you think you see the problem

00:29:18   you see the solution and you can

00:29:20   implement it and like it's gone and this

00:29:22   thing that was problematic and hurting

00:29:24   your users is now just completely

00:29:26   vanished and like that's like a great

00:29:28   victory and I always love when that

00:29:29   happens

00:29:30   doesn't always happen but when it does

00:29:31   it's absolutely awesome so it's the one

00:29:33   reason I love debugging that's why we do

00:29:35   all this right that that feeling and

00:29:37   when it finally works we're like yes I

00:29:39   love that feeling all right thanks

00:29:41   everybody for listening this week and

00:29:43   we'll talk to you next week bye