Segmentation of Initialization Method in Swift

| | August 10, 2015

Since being an OS X/iOS Developer for years I have a strong interest in Apples Swift language. In order to keep my initialization methods clean and simple I am isolating individual parts of the initialization into individual methods. Especially when dealing with long initializations – like often found in a SpriteKit SKScene subclass this helps me keeping a clean and simple structure. This is how it looks like:

Typical Objective-C Class:

@interface SomeScene ()

@property (strong, nonatomic) SKSpriteNode* backgroundNode;
@property (strong, nonatomic) SKNode* hudNode;
@property (strong, nonatomic) SKSpriteNode* playerNode;

@end

@implementation SomeScene

-(id)init {

    if (self = [super init]) {

        [self setupBackgroundNode];
        [self setupHUD];
        [self setupPlayer];
    }

    return self;
}

-(void)setupBackgroundNode {

    self.backgroundNode = [SKSpriteNode new];
    self.backgroundNode.position = CGPointMake(0., 0.);
    /* Some More Options */
    [self addChild:self.backgroundNode];
}

-(void)setupHUD {

    self.hudNode = [SKSpriteNode new];
    self.hudNode.position = CGPointMake(0., 0.);
    /* Some More Options */
    [self addChild:self.hudNode];
}

-(void)setupPlayer {

    self.playerNode = [SKSpriteNode new];
    self.playerNode.position = CGPointMake(0., 0.);
    /* Some More Options */
    [self addChild:self.playerNode];
}

@end

This is just a demonstration to show you how I encapsulate different parts of the initialization into individual methods which are then all being called at the time the -(id)init is being called. I am using this kind of pattern in any of my projects.

Now with learning Swift I read about the basic concepts, about optionals and tried to get used to the slightly different type of initialization. And in order to keep my own Objective-C pattern shown above the Swift code will look like this:

Same class in Swift:

class SomeScene: SKScene {

    var backgroundNode: SKSpriteNode?
    var playerNode: SKSpriteNode?
    var hudNode: SKSpriteNode?

    override convenience init() {

        self.init()

        self.setupBackground()
        self.setupPlayer()
        self.setupHUD()
    }

    func setupBackground() {

        backgroundNode = SKSpriteNode(/*Some Initialisation Parameters*/)
        backgroundNode?.position = CGPointMake(0.0, 0.0)
        /* even more lines */
        self.addChild(backgroundNode!);
    }

    func setupPlayer() {

        playerNode = SKSpriteNode(/*Some Initialisation Parameters*/)
        playerNode?.position = CGPointMake(0.0, 0.0)
        /* even more lines */
        self.addChild(playerNode!);
    }

    func setupHUD() {

        hudNode = SKSpriteNode(/*Some Initialisation Parameters*/)
        hudNode?.position = CGPointMake(0.0, 0.0)
        /* even more lines */
        self.addChild(hudNode!);
    }

}

This does work like expected but I was asking myself if this is the correct way of using optionals. I am afraid that I am misusing them just to convert an Objective-C style to Swift. Do I really have to write all that question marks after every property? Does that something or is it more of a way to switch of a compiler-error that this property “might be nil” – which is what Apples Documentation says about the ?-suffix.

I came up to this question because using swift that way feels a bit strange. Is there a better way to encapsulate code-parts / blocks from an init method in order to prevent it from growing and growing and loosing focus ?

One Response to “Segmentation of Initialization Method in Swift”

  1. Do I really have to write all that question marks after every property?

    Basically, yes. Swift has strong rules about initializers. You must initialize all instance properties by the end of initialization. If you are going to move initialization of instance properties out of the initializer, then you must provide a default initial value for those instance properties in some other way. You can do that with an equal sign and an explicit value, or you can do it with an Optional because it automatically assigns nil.

    That is why outlets (@IBOutlet) are usually Optionals. We know they won’t be initialized during initialization, so we need a temporary value until they are initialized when the nib loads.

    Also it is common practice to use Optionals for any instance property that simply cannot be initialized until after the instance itself has been fully initialized. For example, you might have some time-consuming operation to perform, and you don’t want to do that in the initializer.

    However, there is another approach that might be appropriate for some of your instance properties: mark them as lazy and provide a default initializer that is a define-and-call function. For example:

    lazy var prog : UIProgressView = {
        let p = UIProgressView(progressViewStyle: .Default)
        p.alpha = 0.7
        p.trackTintColor = UIColor.clearColor()
        p.progressTintColor = UIColor.blackColor()
        p.frame = CGRectMake(0, 0, self.view.bounds.size.width, 20)
        p.progress = 1.0
        return p
    }()
    

    That has the advantage of encapsulation. We have provided a default value, namely the thing returned from the define-and-call function, so we don’t have to initialize in an initializer. But the compiler allows us to postpone running the define-and-call function until the first time some other code actually accesses this instance property. That pattern might make more sense for you.

    Also I find myself using computer properties a lot. That’s another good alternative pattern in many cases.

    So basically yes, what you are doing is right, but Swift has some other patterns that can often make it unnecessary, and when you’re coming from Objective-C you’ll want to get comfortable with those patterns too.

Leave a Reply