Improve Debugging Skills | iOS | Swift/Obj C | Xcode

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys welcome to my channel i code i am pallav and on this channel i upload videos related to ios programming every sunday and today it's about improving the debugging skills i agree that as an ios developer it's really important to have in-depth knowledge of swift grip over the frameworks like foundation uik swift ui etc but at the same time it's even more important to have good debugging skills because we invest a significant amount of time in bug fixes performance improvement and all these require really good debugging skills so today in this video we will look at different use cases and we'll try to explore different ways of debugging through them we will be looking at all these developing skills and the first one is break point so we'll see different types of breakpoints not just the conventional the user defined breakpoints but the other breakpoints that are available to us and then we will see the lndb so how to use it efficiently the low level debugger the commands like popv and then we will see that how to look into the container of the device so for certain bugs we we need to look into the devices containers we will see that how can we do that and then we will see the network link conditioner so for some specific kind of bugs that are only replicated in the bad network scenarios we need to replicate the bad network scenario so for that we'll see that what is network link conditioner and how can we use it and then we will be identifying the issues which occur only on device and not in debug mode at last we will see view hierarchy along the way i'll be giving some extra piece of useful information so for example when looking at view hierarchy i'll tell you that how can we print and tab view hierarchy without using an external tool so you might consider watching complete video let's dive in so let's start with the breakpoints breakpoints is one of those debugging ways which is exhaustively used by developers and it is very easy to use so what breakpoint does is it it holds the control it stops the control at a specific point and then we can inspect the values of the variable which are available at that scope so the first and the easiest one is the user defined breakpoint so let's say if i write where a is equal to 10 and where b is equal to 20 and if i put that print statement here saying a plus b but at this point in time i want to check that what is the value of a and b what i can do is i can simply put a breakpoint here by just clicking on to the cutter and then i can give it a run once it will run the control will stop at line number 17 where the break point is there and then we can inspect the values of the variables which are available in the scope so here i can see i can just hover on on the variable and it will print the value so say 10 and b is 20. so this is one of the easiest and the most widely used ways of using the breakpoints so breakpoints can do a lot more than this there are other types of breakpoints so if we click here on the breakpoints tab there's a small plus button here if we click on this we get to see that there's swift error breakpoint exception breakpoints and symbolic breakpoints and few other types of breakpoints so if we put an exception breakpoint it will halt the control it will stop the control as soon as the crash is encountered so it is of great use the other one is swift at a break point so let's let's try and use swift error breakpoint it basically stops the control at the point from where the swift error is thrown so you can imagine that in a large project where you are having a chain of methods calling each other let's say method a calls method b method b calls method c method c calls method d and method d throws an error which is passed all the way back to method a now we want to identify that what is the origin of the error which method is actually throwing the error though it is being handled back at the method a but you want to identify that what is the root cause from which method the error is actually being thrown now this can be done very easily using swift error breakpoint so let's see this i'm having a saved code snippet so we'll just use it here in the viewed load method c is being called method c calls method b b calls a and from a we are throwing an error though this error is being handled at the top and viewed at load but let's try to identify that what is the root cause which method is actually throwing the error whether it's b it's c or it's a so with swift error breakpoints enabled if we run this let's see that where does the control stops the control is stopped at line number 32 which is the root cause which is the culprit so method a and specifically this line number 32 is throwing the error so control is stopped here and we just saw that how easy it is to identify that exactly at what point the error is being thrown so in the breakpoints we saw the user defined breakpoints the conventional ones which are just enabled by clicking onto the gutter they can be used for inspecting the values of the variables available in that scope and then the exception breakpoint so we can use it for identifying the point from where the crash is occurring then the third one the swift error breakpoint this can be used to identify the point from where the error is being thrown no matter how deep is the chain swift editor breakpoint just works like a charm and do you know that you can actually share the breakpoints so if i just put a breakpoint here and here i can actually share this with my teammate next time when you are guiding your teammate while debugging an issue then put a breakpoint at line number 212 put a breakpoint line number 103. rather you can try sharing the breakpoints so they are dragged by get exactly like your source code so if your teammate removes the break point and then you take the pull the break point on your copy will also be removed so that's the thing that that needs to be taken but you can share the breakpoints it can be of you sometimes let's see the second way of debugging that is lldb lldb or low level debugger is another great way of debugging and i'm sure that you guys would have used po for printing the description of the variables but here what i want to focus on is that pu is far more useful than just printing the statements it can be actually used to execute the commands to execute the statements it works just like your source code is being compiled and executed so in the same way lldb actually generates the source code from your po commands compile it with the embedded swift and clank compiler before executing it so let's see this by a use case i'm having a struct employee so we'll just use it here so here we are having nothing much just id name joining date and is eligible for a gratuity so it's both and i have mentioned this here for a purpose that we'll see in a minute but before that let's create an object of this so say where employee is equal to employ and id one name say john joining date say today's date and is eligible for gratuity save false print employee dot name now i'll just put a break point here so that we can play with the ledb commands the pop and the v and we'll give it a run now using po command we can obviously print the description of the object so if i if i go for po employee we get the description of the employee but apart from this what we can do is we can actually execute the statements using po so if i try po employee dot joining date is greater than date so here this this statement has been executed and this way we can actually make some use of it in certain scenarios we need to execute something on the runtime to check certain things so pu can be of use there and now let's see the p command so p can also print the description of the object but when the same thing was being done by p o what is the use of p so let's say that if i want to change the value of a variable at runtime i can do that using p so p is just an alias of expr so you can also try the exp thing but i prefer p and to see p in action let's change this print statement so let's first stop this and instead of this let's put it like print is eligible sorry employee dot is eligible for graduating let's use ternary here and if it is eligible for graduating let's print that eligible and if not let's print not eligible and now let's give it error so here we'll try changing the value of this variable is eligible for graduating let's first test that what is its current value so p employee dot is eligible for gratuity and it's false and now let's try changing it so if i go for p employee dot is eligible for gratuity is equal to true and now if i try printing it we are actually getting true so is this just for this ledb console or the value has actually been changed so that we can confirm by continuing the execution and we see that our print statement prints the eligible which means that we have actually changed the value of this variable is eligible for graduating so this way you can test a lot of scenarios where where you need to change the value of variable so let's say that you are fetching the response from api and in the response there's some variable whose value is false but you wanted to test the flows for which the value should have been true so you can very easily do that just put a breakpoint and just change the value that's all so till now we saw that okp you can be used for printing the description of the variables p can be used for the same as well as for changing the values of the variables at runtime and this is fine but then what is the need of the third command v why is v useful so to understand it let's introduce the little complexity here so instead of this struct employee let's just change this to say software developer and let's make a protocol employee to which this software developer confirms and instead of making the object of employee let's make this let's make the object of software developer john and false and let's explicitly mention the type as employee no need of this print statement here so just put a friend saying let's test and let's put a breakpoint over here so now we will see that what is the limitation of p o and p and then we'll understand that why is it so so let's first run it and now if i want to see that what is the name of the employee using the po command if i go for pu employee dot name employee has no member name if i try p here p employee the lower case p p employee dot name the same error but if i try v employee dot name i'm getting the name john so what is different between v and p let's try and understand that p u and p didn't work because they compute the dynamic types of the result while v does not compile your expressions at all it just prints the values available in the stack frame so here the static type that we gave was employee and employee does not know that what is name joining date or is eligible for graduating that's where pure and q didn't work well we took the values from the stack frame and hence it was knowing employee name so when i say that v does not compile your statements we can actually confirm it by writing v employee dot name dot say uppercase this does not work because v is not compiling the statement this is not being executed again what p u and p used to do so there are some upside and downsides of both if we go for using p o or p here we could have used employ.name data per case so we know the pros and cons both of p o p and v and we can actually use them very efficiently while i debugging now let's see network link conditioners now comes those issues which occur only in low network or bad network scenarios and in order to fix them we need to simulate we need to replicate the bad network scenario and to do so apple has provided a tool called network link conditioner it is available for both device and simulator so let's see it this can be downloaded from developer.apple.com i'll put the link in the description once you download it from there you will get this directory hardware and inside hardware there will be this network link conditioner so just double click it and install it once you install this network link conditioner you will see something like this so let's test that how this network link conditioner works so i'll just hit this fast.com here to get my internet speed that what what is it coming now so it is somewhere around 50 mbps and now what i'll do is that i will turn on the network link conditioner so i'll just go to the system preferences and here it is having this network link condition that i just installed so i click on it and i'll turn it to say 100 loss then i'll turn the network link conditional on now if i reload i'm getting the speed as zero and we can even change the profile so if we go back to the network link conditioner and i can change this from 100 loss to 3g so in three g maybe i'll get some speed not as good as my my wi-fi speed but because i i intentionally want my speed to be low for replicating those scenarios which occur in bad networks so if i put this on 3g and if i refresh this so i'll get some speed maybe around 100 200 kbps 500 kbps but not as good as wi-fi so we can toggle this we can create our own profile and we can control the bandwidth latency the packet loss and everything so this can be done and because our simulator uses the same internet connection as that of our macbook so this will control the network speed and we can use this on the device also so for enabling it on device what we need to do is go to the settings in the settings you will find the developer section go to the developer section and you will find network link conditioner over there just toggle the enable and disable mode of the network link conditioner and then we can use it so if i go for testing the speed on device if i hit the fast dot com without network link conditional enabled i'm getting the good speed near about 20 mbps 30 mbps but now if i turn the network link conditioner on with hundred percent loss i'll get the 0gbps as we saw and then if i change the profile then if i change the mode to maybe 3g then probably i'll get the speed somewhere around 100 kbps 500 kbps but that's enough for simulating the bad network scenarios to replicate our issues so it's a great tool for debugging such such issues and scenarios now let's discuss another way of debugging what i call it as looking into the container of the device so for this assume a use case that that you are working on a project which is having the involvement of database in it for now we will consider the sqlite database but it can be any other database here you need to verify that whether your records are getting inserted in the database or not for this i'm having this file database helper there's nothing much in it it just opens a db and just creates a table so we are creating a table for employees it is having just name and designation of the employee and then there is this method insert through which we'll try to insert our records so let's try and do that i'm having this instance of database helper over here and here what i'll do is i'll just use this database helper dot insert and we'll insert a record say john and designation is say software developer so i'll give it a run and in the insert method i have put the log saying that recording set it successfully so if it does it should print that statement but again we will verify it so successfully inserted row so that is that is a confirmation that the report has been inserted but now in certain scenarios some issues might happen and for which we need to look into the container this is not specific for looking into a database but this is a technique that you can use for looking into the device container so maybe confirming that whether the file has been downloaded or not or maybe the images that you are caching the caching has been done properly or not so it's a way that you can use in various scenarios so i'll use this tool sim sim and using this will go to our application debugging and in the finder so basically this directory this folder is the container where all the data all our document directory for this particular application is stored so let's go here and verify here's our database that we created employees.db and if i open this using sqlite browser and if i go for browsing the data our record should be there john software developer the data that we inserted is here so this is one of the ways through which you can look into the container and this is pretty straightforward on the simulator but but if you're running on device then it is not that straight forward so let's look at the way that how can we get the container when we are running our application on the actual device instead of a simulator for downloading the container on device click on windows and then select device and simulator there you will find your application click on it and below that there's a small settings button click on the settings button there will have an option for downloading the container so click on it and download the container this container will be exactly same as we downloaded for the simulator so just download it this is how it will look like it will be xcm data so right clicking on it and if we click on show package content we will get the directory here in the app data we'll get our employees db same as we got for the simulator so again we can click on this and we can explore the database in the sqlite browser or we can view the files downloaded or the images cached whatever we wanted to do with our container we can do for the device too and the way for downloading the container on the device is easy just go to windows devices and simulator select your app and click on the settings button for downloading the container as simple as that now let's discuss about even more complex problem so at times we encounter such issues which are not replicated on the simulator they occur only on device and that too only in the release mode or what we can say that they do not occur in the debug mode so if you directly run your application from the xcode the issue won't replicate if you have not encountered any such issue like you but sometime in your developer career you might encounter such issue and then this technique will help you so i experienced one of such issues recently if you download a video which is a challenge stream technically m3u at five so if you download a hls stream using av asset download task it does not download on the simulators for that you will have to use device and even more complex is that if you try to get the functionalities like storing the progress that is the partial download so assume that you are downloading a content you pause it and then you kill the app and on relaunch if you want to continue it from the point you left you will have to store the progress this cannot be done in the debug mode so apple has not mentioned this in the documentation but i faced this problem so the two conditions here are at first you cannot download it on the simulator and the second one is that the resuming of the progress resuming of the download from the point where it was left cannot happen in the debug mode so if i run the application directly from the xcode it won't work in this case if some issue occurs what's the way for debugging it so a workaround that i thought of is creating a log file because we know that the container of our application can be downloaded from the device so what if we place a log file there and put the necessary logs over there once we encounter the issue we can get the log file from the downloaded container and can inspect it that water logs have been printed and from where did the printing of the logs stock that will give us a fair idea of how to debug issues like this now the only point is that how to create a log file and that's a piece of cake so let's look at it for that i'm having this saved code snippet create log file so it's just a function where we are getting the path of the document directory giving a file name so i just used date over here it's just file name and then we are opening the file in the append mode so let's do one thing let's put a log here and one thing that you need to take care of that print won't be treated as long here so for for this for creating or saving the logs in the log file we'll have to use nslog so if i put ns log here first law and then some some piece of code so nothing much let's say that is equal to 10 or or anything that we wanted to come wanted to do and then maybe in this log second log if i give it a run my bed i haven't called this function so let's first call this function that create log file and now if i give it a run so our document directory should have the file that we created and it should have these logs first log and second log so let's try exploring our container using simpson so debugging one finder and here here's the file that we just created so if i just view it first log and second log so this is a workaround this is a kind of way that we can use for for identifying the issues which do not occur on the simulators always do not occur in the debug mode what you can do is you can just just create a log file put some logs in it and then later can go through them to have a fair idea that what went wrong the last part of this video using view hierarchy for debugging ui related issues looking at the view hierarchy gives us a clear picture that which view is placed over which view so if we face the issues like that view is not visible or partially visible we can go to the view hierarchy and can solve these issues pretty easily so here i am having this application this is just for showing the viewer key so it has nothing much but just a list of movies so if i want to view the view hierarchy here all i need to do is just click on this button here and this will open the view hierarchy which will give me a clear picture that how is the placement of the views which we use covering which view and we can even rotate it to have a three dimensional view this will give us an idea that which view is beneath which view and we can even look at the frames so if we go here here we can select the view and can look at the frame that actually what is the frame so 187.55 and 137 this is the frame of this particular view we can look at this hierarchy that how it goes which view is falling under which view if we explore this the entire hierarchy is visible so this is a great tool for debugging the ui related issues and one thing that i said in the starting of this video that we can print in tab view hierarchy without using any external tool so let's try that that how can we do that so i just resume it here and i'll put a break point here in the dead select so just that i can use the view here and po self dot view dot value for key and the key is recursive description so if i hit enter here you can see that entire view hierarchy that we are having that we saw in the debug view hierarchy section we actually get it here so it gives us even more clear picture that exactly what is the frame of which view which view is falling under which view so parent child and the entire hierarchy with all the description printed here so even this can be useful at times we can use all these techniques to debug the ui issues and it helps a lot so this was pretty much for this video a new video comes out every sunday so stay tuned and stay safe let's write better code together happy coding
Info
Channel: iCode
Views: 4,293
Rating: undefined out of 5
Keywords: debugging, debugging skills, iOS debugging skills, swift debugging, xcode, iOS, iOS programming, iOS debugging, breakpoints, debuggers, lldb, po, lldb p, lldb v, low network issues, network link conditioner, view hierarchy, container of device, non reproducible issue, creating log file, log file, swift error breakpoint, exception breakpoint, how to debug crash, how to debug issues in iOS
Id: ipuxycB1ewY
Channel Id: undefined
Length: 26min 1sec (1561 seconds)
Published: Sat May 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.