When I first started iOS development (think it was iPhone OS development) Interface Builder (IB) was pretty clunky and since I was used to creating Java Swing applications, it was no big deal to create the UI in code. It was also simple because there was only one screen size so you could hardcode coordinates and sizes with impunity. As IB has become more robust and has incorporated Auto Layout I do most UI layout in IB.
Now with this mixing of SpriteKit and UIKit I needed to once again place elements programmatically. The things is that SpriteKit and UIKit have their own coordinate system orientations (which I knew) and their own coordinate bounds as well (which I didn’t know). In my initial UIViewController I was centering a UIButton based on half the view’s width. And in my SpriteKit SKScene I was setting a UITextView based on half the view’s width. However, in the UIViewController the UIButton was centered as expected, but the UITextView would never line up right.
After playing with various iPhone Simulator hardware and experimenting with the code, I found that the SKScene bounding box was always 1024x768 and that the bounding box of the UIViewController was the device screen size (e.g. 1136x640 on an iPhone 5s). To get things to work as I expected, I had to get the SKScene as a UIView and then the bounds would be the device bounds. I could now manipulated UIViews in my SKScene but I would have to be aware of the specific device size.
This didn’t seem like a great path to follow. Apple’s whole trajectory is to move away from coding to specific device sizes. I vaguely remembered overhearing that there was a way to do Auto Layout programmatically. After a Google search or two I found some Swift examples of programatic Auto Layout. I was able to put together this code to get the effect I wanted in a non-device specific way:
let viewDictionary = ["textView": textView] let textViewConstraintV = NSLayoutConstraint.constraintsWithVisualFormat("V:|-2 0-[textView(100)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewDictionary) let textViewConstraintH = NSLayoutConstraint.constraintsWithVisualFormat("H:|-50-[textView]-50-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewDictionary) view.addConstraints(textViewConstraintV) view.addConstraints(textViewConstraintH)
I chose to use the “Visual Format Language” in this case. I’m not sure if I’ll stick with this or move to the object-based way of creating constraints. Either way, I’m glad I learned a couple of things even though I found a better way to accomplish the desired effect.