Sharing passion in Swift

#1 Meaningful print debugging

Print debugging problems

Print debugging is simple and yet a powerful method. It is usually enough to toss a print() in a couple of places and a problem is recognised. As it works well for values and simple objects, when we print a more complex instance, the result is less informing.

To illustrate this, let’s take this simple Wheel class:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

classWheel{

varspokes:Int=0

vardiameter:Double=0.0

init(spokes:Int=32,diameter:Double=26.0){

self.spokes=spokes

self.diameter=diameter

}

funcremoveSpoke(){

spokes=spokes>0?spokes--:spokes

}

}

varwheel=Wheel(spokes:36,diameter:29)

print(wheel)// Wheel

debugPrint(wheel)//Wheel

Struct benefits

Note that if Wheel was a struct and not a class we would already get a better print output:

So now, if we print our wheel object after confoming to CustomStringConvertible and CustomDebugStringConvertible protocols then we get:

1

2

3

4

5

print(wheel)//Wheel has 36 spokes

debugPrint(wheel)//Wheel has 36 spokes and 29.0 inches

Neat!

UIViewControllers and NSObject inheritance

One of the least verbose print outputs belongs to UIViewController:

1

2

3

4

5

6

7

8

classWheelsViewController:UIViewController{

varwheels=[Wheel]()

}

varwheelsViewController=WheelsViewController()

print(wheelsViewController)//<WheelsViewController: 0x7f8e0861b590>

To make it simple, let’s just focus on CustomStringConvertible protocol and print() function. However, now if we try to conform to CustomStringConvertible protocol:

1

2

3

4

5

6

7

8

extensionWheelsViewController:CustomStringConvertible{

vardescription:String{

return"WheelsViewController has \(wheels)"

}

}

we receive an error "Redundant conformance of ‘WheelsViewController’ to protocol ‘CustomStringConvertible’"

That is because UIViewController inherits from NSObject that in turn conforms to NSObjectProtocol. We can see that all NSObject subclasses already implement description and optionally debugDescription properties:

1

2

3

4

5

6

7

8

9

publicprotocolNSObjectProtocol{

...

public vardescription: String{get}

optional public vardebugDescription: String{get}

...

}

To fix that issue we will override inherited properties.

Overriding inherited properties

As we are not satisfied with the default implementation of description property inherited from UIViewController, we can override it within the body of our WheelsViewController class or as an extension:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

extensionWheelsViewController{

overridevardescription:String{

return"WheelsViewController has \(wheels.count) wheels"

}

}

varwheelsViewController=WheelsViewController()

print(wheelsViewController)//WheelsViewController has 0 wheels

wheelsViewController.wheels=[wheel1,wheel2]

print(wheelsViewController)//WheelsViewController has 2 wheels

That’s it!

This post is inspired by Udacity course Xcode Debugging. It’s a great starting point in mastering your debugging skills. More advanced developers will also find it useful. Playground with the code from this post is available here.