Your First iOS App: 100% Programmatically (Swift)

Part 2

Austin Louden
4 min readMar 27, 2016

This is Part 2 of a tutorial that follows Apple’s “Build a Basic UI”, but implements all of the user interface elements programmatically. View the full project on GitHub. View Part 1 or Part 3.

The next step is to add elements to the user interface — a text field, a button, and a label.

The label

First, we’ll need an init method, which is called when the view controller is created.

Above the viewDidLoad method, we can create our own init method. Right now, we’ll just call the superclass’s init method (UIViewController).

init() {
super.init(nibName: nil, bundle: nil)
}

After we make this, Xcode will complain that we’re not implementing the other initializer of UIViewController:

Clicking on the warning will auto-generate the following code:

required init?(coder aDecoder: NSCoder) {
fatalError(“init(coder:) has not been implemented”)
}

Where do these required initializer’s come from? If you ⌘+Click on “UIViewController” at the top of the file, you can see the public parts of Apple’s UIViewController class. There’s a comment above the first initializer which explains why we can’t just call super.init() with no arguments.

Back to creating the label. Above your init method, write the line:

let label = UILabel()

Because we used “let” instead of “var”, the label can be set once and only once. You can set the label and it’s text property in the init method like so:

init() {
super.init(nibName: nil, bundle: nil)

label.text = “hello!”
}

Then, in viewDidLoad, set its frame and add it to the view hierarchy.

override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
label.frame = CGRectMake(20, 40, CGRectGetWidth(self.view.frame), 20)
self.view.addSubview(label)
}

We do this inside viewDidLoad because it’s best practice to not access the view controller’s view property (i.e. self.view) until this method is called.

Build and run the app. You should your label in the upper left of the screen.

The text field

Create the text field constant below your label.

let textField = UITextField()

We should also set the border style so the text field shows up on the screen (the default text field does not have a background). You can do this below where you set label.text in the init method.

textField.borderStyle = .RoundedRect

Finally, in viewDidLoad, set the text view’s frame and it to the subview. Make sure this is below your label code.

textField.frame = CGRectMake(20, CGRectGetMaxY(label.frame) + 10, CGRectGetWidth(self.view.frame) — 40, 30)
self.view.addSubview(textField)

I’m using a lot of different numbers in the CGRectMake method. It’s best practice to put these numbers into constants so they can be reused and easily modified, but I’ll leave these as is for the sake of this tutorial.

Build and run the app — you should now see the text field box below your label. Clicking on the text field allows you to type using your keyboard, however the simulator hides the phone’s keyboard by default. You can show it by pressing ⌘+K.

The button

Create the button constant as you’ve done before. This time, we’ll use a UIButton initializer which lets us set a type property.

let button = UIButton(type: .RoundedRect)

UIButton also has a method - setTitle:forState:, which lets us change the button title depending on whether it’s pressed or not. “.Normal”, which is short for UIControlState.Normal, corresponds to the regular, unpressed state. You can set this below the textField.borderStyle line in init.

button.setTitle(“Set Default Label Text”, forState: .Normal)

In viewDidLoad, below your text field code, set the frame of the button and add it to the view.

button.frame = CGRectMake(20, CGRectGetMaxY(textField.frame) + 10, CGRectGetWidth(self.view.frame) — 40, 30)
self.view.addSubview(button)

Build and run the app. At this point, you should have all the user interface components ready to go.

You can tap on the button, but it won’t do anything (yet!). We’ll hook everything up the final post, Part 3.

--

--