- Swift 2 Blueprints
- Cecil Costa
- 718字
- 2021-07-09 21:36:42
Debugging
Debugging is an everyday task for a developer that is usually done to fix a bug. There is no right or wrong way for debugging, and there is no formula to find where the issue is. On the other hand, we have some tricks that can help us find where the bug is. In this section, you are going to see some of them. They can be very useful if you would like to modify any app in this book and you don't get the expected result.
First of all, let's see a common problem. Swift was created to be compatible with Objective-C and Objective-C in its early days was created to be some kind of Smalltalk over the C layer. The idea at that time was to create a language where containers and functions didn't need to be of only a specific type like an array of integers, even the value returned from a function could be of any type. You can see, for example, NSArray
, NSDictionary
, and NSSet
that can store NSString
, NSNumber
, and the objects of any other class in the same container.
How Swift receives this kind of information? One way is by using generics but, usually, they are received as AnyObject
. Sometimes, the debugger is not able to show you the right variable type. For a better example, have a look at the following code:
var request = NSURLRequest(URL: NSURL(string: "http://date.jsontest.com/")!)
NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil)
// json Type???
}.resume()
In this case, you can ask yourself what is the JSON variable type? Of course, the first step is to check the debugger information, but you might get some information like the following one:

You can check with the is
operator like if json is Int
, but it can be very exhausting and, sometimes, even impossible. For scenarios like this, you can use the _stdlib_getDemangledTypeName
function, which displays the variable type name. In this case, we can add the following println
instruction to our code, as it is shown in the next code:
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) println("json variable type: \( _stdlib_getDemangledTypeName(json!) )") }.resume()
Now, you can see on the log console that, in this case, it is a dictionary as follows:

Another important thing to bear in mind is lldb, which is the debugger command line. It can look complex and not much intuitive, but when you get used to it, it is very useful and logical. For example, you can set breakpoints using a pattern like br s -r viewDid*
to add breakpoints in functions like viewDidLoad
and viewDidAppear
.
Of course, there are tasks that you can do with lldb and also with Xcode like using the lldb command po [[UIWindow keyWindow] recursiveDescription]
, which gives you the window view hierarchy, or simply using the new Debug View Hierarchy button (displayed next) that comes since Xcode 6, which gives you 3D information on the current view.

Once it is pressed, you can rotate the image and have an output similar to the following screenshot:

A very common problem in our apps is the excess of memory usage. When we start receiving memory warnings, we need to check the amount of memory that is being increased in some parts of our code. To do it, just keep a function to retrieve the memory whenever you want. The following code is valid to retrieve the amount of memory that is being consumed:
func getMemoryUsage() -> mach_vm_size_t{ let MACH_TASK_BASIC_INFO_COUNT = sizeof(mach_task_basic_info_data_t) / sizeof(natural_t) let flavor = task_flavor_t(MACH_TASK_BASIC_INFO) var size = mach_msg_type_number_t(MACH_TASK_BASIC_INFO_COUNT) var pointer = UnsafeMutablePointer<mach_task_basic_info>.alloc(1) let kerr = task_info(mach_task_self_, flavor, UnsafeMutablePointer(pointer), &size) let info = pointer.move() pointer.dealloc(1) if kerr == KERN_SUCCESS { return info.resident_size } else { let message = String(CString: mach_error_string(kerr), encoding: NSASCIIStringEncoding)! fatalError(message) } }
Then, call this function in some parts of your code where you think there is memory wastage and print it like the following code:
println("File: \(__FILE__) at line \(__LINE__) memory usage \(getMemoryUsage())")
Note
There are third-party products that can also help you to debug your app like Fabric (http://www.fabric.io) that sends reports on user crashes to the developer.
- Xcode 7 Essentials(Second Edition)
- 匯編語言程序設(shè)計(第3版)
- Mastering Predictive Analytics with Python
- Python機器學習算法與實戰(zhàn)
- Java編程的邏輯
- Lift Application Development Cookbook
- Elasticsearch Essentials
- Fastdata Processing with Spark
- Oracle 12c從入門到精通(視頻教學超值版)
- 官方 Scratch 3.0 編程趣味卡:讓孩子們愛上編程(全彩)
- Java EE項目應(yīng)用開發(fā)
- Mobile Test Automation with Appium
- 情境微課開發(fā)(第2版)
- C#編程魔法書
- Comprehensive Ruby Programming