Book Image

Swift 2 Blueprints

By : Cecil Costa
Book Image

Swift 2 Blueprints

By: Cecil Costa

Overview of this book

In this book, you will work through seven different projects to get you hands-on with developing amazing applications for iOS devices. We start off with a project that teaches you how to build a utility app using Swift. Moving on, we cover the concepts behind developing an entertainment or social networking related application, for example, a small application that helps you to share images, audio, and video files from one device to another. You’ll also be guided through create a city information app with customized table views, a reminder app for the Apple Watch, and a game app using SpriteKit. By the end of this book, you will have the required skillset to develop various types of iOS applications with Swift that can run on different iOS devices. You will also be well versed with complex techniques that can be used to enhance the performance of your applications.
Table of Contents (15 chapters)
Swift 2 Blueprints
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

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:

Note

In Swift 2, many functions have changed their input or output header from AnyObject to a specific type, making life easier for developers.

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.