Wrapping up boilerplate code — part 1: Interface builder

Chandan Karmakar
3 min readMay 1, 2020

--

Working as full time iOS app developer, I would like to share few tips on ‘How to wrap boilerplate code for interface builder in swift’.

Most of us have time constraints and have to deliver projects ASAP. This led us to copy-paste code and develop redundant codebase. Copy-pasting seems easy solution first, but as project grows, it becomes less readable and hard to maintain. So let’s take a quick look here.

Using Storyboards

We’re familiar with instantiating view controllers from storyboard, i.e

let storyboard = UIStoryboard(name: “Main”, bundle: nil)
let
viewController = storyboard.instantiateViewController(withIdentifier: “ProfileViewController”) as! ProfileViewController

Now let’s simplify the above code:-

  • Our view controller will tell which storyboard they are defined,
  • and also its storyboardId.

So goal is to write ProfileViewController.instantiate().

We need extension: UIViewControlle for this. And we’ll use class func, similar to static func. But class func comes with override facility, and that is going to help us to achieve our goal. @objc is required for overriding the variable.

extension UIViewController { 
@objc class var fromStoryboard: UIStoryboard? {
return nil
}
@objc class var storyboardId: String {
return String(describing: self)
}
}

Now we just need to provide the fromStoryboard to find it where. storyboardId is optional, it’s default implementation assumes that we have class name as storyboardId. String(describing: self) by default gives the exact class name in String. self in class function is class type itself.

Finally let’s implement instantiate().

Self is Generic class type and it denotes from which class is used to call the method. Here comes the time to utilise instantiate() method. We should create UIStoryboard objects somewhere else to easily access them.

class MyStorybaords {
static var main = UIStoryboard(name: “Main”, bundle: nil)
static var profile = UIStoryboard(name: “Profile”, bundle: nil)
....
}
class ProfileViewController: UIViewController {
override class var fromStoryboard: UIStoryboard? {
return MyStorybaords.profile
}
}

Voila, Thats all! Now we can instantiate view controllers by writing simply

let viewController = ProfileViewController.instantiate()

Using xib to load UIViews

With a little modification, the same can be used for instantiating UIView from xib files. Again method initViewFromNib() assumes same filename is same to class name. Leaving you to add flexibility.

Another example of UITableView reusable cell dequeue and register

Here we don’t need static or class function, since we would have UITableView object. Parameter type takes the cell type and we can get the cell by its class name. Same can be applied to UICollectionView.

let cell = tableView.dequeueReusableCell(type: MyCustomCell.self)

Using IBDesignable UIView from Xib

Let’s see another instance when we use @IBDesignable to instantiate views from xib files, we can use inheritance to wrap those codes.

Now we can inherit from UIViewXib and design view in xib file with no extra code for loading views from xib.

class DayView: UIViewXib {   
// other things...
}

Use this DayView to another view in interface builder. UIStackView is used to add 7 DayView objects.

More optimised version of UIViewXib is here.(Assuming Autolayout is used to create xib files.)

Thats all for today flocks.

Keep improving yourself until you reach your goal. Even a small change can make huge difference.

Thanks for reading, feedback are always welcome.

--

--