Welcome to part two of Creating UI Elements Programmatically Using PureLayout. In the first part, we built a simple mobile application’s UI completely in code without the use of Storyboards or NIBs. In this tutorial, we will cover some of the most used UI elements in all applications:
3. Self-sizing UITableViewCell
All of this is handled, out of the box, by the navigation controller. And adding one to your application would only take one extra line of code (if you don’t want customizations to the navbar).
Now run your application. The result should look like this:
- Increase the size of our upperView to accommodate the navigation bar’s height.
- Set the navigation bar’s isTranslucent property to false. Doing this will make the navigation bar opaque (in case you didn’t notice, it is a little bit transparent) and now the superview’s top edge will be the bottom of the navigation bar.
Refactoring Our View Controller
Now right click on the ContactCard folder in the Project Navigator and choose New File:
And now we’re ready for refactoring.
An error will come up saying `'required' initializer 'init(coder:)' must be provided by subclass of 'UIView':
You can fix this by clicking on the red circle and then Fix.
Then call this method from the initializer:
When overriding any method, its always good to check its documentation, either by visiting the Apple docs, or more easily, by holding down the Option (or Alt) key and clicking on the function’s name
Cut and paste the constraints code from the view controller to our new method:
Now our view controller has slimmed down to just a few lines of code after being 100 lines long!
To make sure everything’s working as intended, run your app and check how it looks. Now everything doesn’t just look good, but also its code belongs where it should be.
Having a slim, neat view controller should always be your goal. It might take a little bit more time to do so, but it will save you so much hassle later on during maintenance.
Here we have two methods that we need to implement:
- public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int -- This method tells the table view how many rows we want to show.
- public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell -- This method asks for the cell at each row. This is where we will initialize (or reuse) a cell and insert the information that we want to show to the user. For example, the first cell will display the phone number, the second cell will display the address and so on.
Head to ProfileView.swift and add an attribute for the table view right above the initializer:
The first line adds three constraints between the table view and its superview: The right, left and bottom sides of the table view are pinned to the right, left and bottom sides of the profile view.
The second line pins the top of the table view to the bottom of the segmented control with a spacing of eight points between them. Run the application and the result should look like this:
Great, now everything is in place and we can start implementing our cells.
Type "UITableViewCell" in the "Subclass of:" field and Xcode will autofill the class’s name with "TableViewCell". Type "ProfileView" before the autofill so the final name would be "ProfileInfoTableViewCell" then click Next and Create. Go ahead and delete the created methods as we will not need them. If you want, you can read their descriptions first to get an idea of why we wouldn’t need them right now.
As we said earlier, our cell will contain basic information, which is the title of the field and its description, and so we will need labels for these.
And now we will override the initializer so we can set up the cell:
And as for the constraints, we’re going to do something a little bit different but very useful nonetheless:
Fantastic, we can now start rendering cells in our table view. Let’s head to ViewController.swift and modify the lazy initialization of our table view in order to register this cell class with the table view and set a height for each cell.
There might, and most probably, will be a case where you want your different cells to have different heights according to the information inside of them, which you might not know beforehand. For this you will need your table view to accommodate their sizes automatically, and there is actually a very simple way to do so.
Here, we tell the table view that the row height should have an automatically calculated value based on its content.
As for the estimated row height:
"Providing a nonnegative estimate of the height of rows can improve the performance of loading the table view." -- Apple Docs
Now run the application and it should look something like this:
Amazing, huh? And as a reminder of why we're actually coding our UI, here's a whole blog post written by our mobile team lead on why we don't use storyboards at Instabug.
What you accomplished during the two parts of this PureLayout tutorial:
- Removed the main.storyboard file from your project.
- Created a `UIWindow` programmatically and assigned it a `rootViewController`.
- Creating UI elements programmatically in code, such as labels, image views, segmented controls, and table views with their cells.
- Embedded a `UINavigationBar` in your application.
- Created a dynamically-sized `UITableViewCell`.
Give yourself a round of applause for that! If you have any questions or comments please don’t hesitate to contact me @alyakan.
- Create UIViews Constraints Programmatically Using PureLayout
- The Ultimate Guide to Beta Testing Your Mobile App
- How Much Your Mobile App Performance Costs Your Business
- Performance Monitoring and User Experience for Mobile App Growth
Instabug empowers mobile teams to maintain industry-leading apps with mobile-focused, user-centric stability and performance monitoring.