08
swift_down_595x126

I am using Swift for several months now, and really like the language. While Xcode support is not so great, the language significantly improves my daily coding sessions. However, there are aspects of Swift that are not really clear to me. One of them is objects initialization issue which quietly causing memory leaks.

What’s wrong with init?

Let’s assume that we have MyObject class, which objects does nothing except logging to the console whenever they are initialized or de-initialized:

We also have custom view controller, that extends UIViewController, and holds MyObject instance using constant reference (let):

Nothing complicated so far, everything is clear. So, imagine you want to initialize a ViewController object:

Looks good? Well, it’s not. You just created a memory leak, which can be confirmed by profiling the app using Xcode’s Instruments. To better understand what is going on, you can change your code, so ViewController object will be initialized and immediately deallocated:

Now, check out the console output:

Yes, that’s right. Calling ViewController() is causing MyObject instance to be initialized twice, in fact there are two instances of MyObject. One of them is hold by object property in ViewController, another one – just leaked and probably will never be deallocated.

How is that even possible?

My guess is that UIViewController init method could be implemented like this:

While this should work in Objective-C world, it’s problematic in Swift. There is no such thing like automatic property initialization in Objective-C, or default property values. However, in Swift properties are initialized before the object that defines them is initialized, automatically.

That’s only my guess, we can’t be sure if that’s really a reason of the issue. For sure, every Swift developer should pay extra attention when initializing Foundation, UIKit, AppKit or other pre-Swift frameworks. I can confirm that this issue can be reproduced not only with UIViewController, but also UIButton and many other UIKit classes.

Avoiding such nonsense

Thankfully, there is very easy way no avoid such memory leaks. You should always choose the correct initializer for given class.

You can call init without parameters on UIViewController because (like many others) it extends from NSObject. But when you look inside documentation, you will see that the UIViewController initializer is initWithNibName:bundle:.

It’s a pity Swift can’t warn us when we are trying to init UIViewController with init(), as it looks obviously wrong and you should never do that. Perhaps it will be improved in future releases.

Tested under Xcode 6.1.1 and Xcode 6.2 beta

Leave a comment