Home iOS & Swift Books Auto Layout by Tutorials

2
Construct Auto Layout with the Interface Builder Written by Jayven Nhan & Libranner Santos

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Interface Builder is a graphical user interface (GUI) for developers to create an app’s user interface (UI). With Interface Builder, developers can drag and drop UI objects onto a design canvas, and then use Auto Layout to create adaptive user interfaces for different screen sizes.

With Interface Builder, you can build most of your app’s UI without writing a single line of code. In the end, you’ll end up with an Interface Builder file, saved as either a storyboard or a .nib/.xib file.

In this chapter, you’ll learn:

  • To use a storyboard to layout your app’s UI.
  • The benefits and drawbacks of using storyboards.
  • To use .nib/.xib to layout your app’s UI.
  • The benefits and drawbacks of using .nib/.xib files.

Setting up the launch screen layout using a storyboard

Open MessagingApp.xcodeproj in the starter folder. Under the Storyboards group, open LaunchScreen.storyboard. You’ll see the following:

You want the background image view to fill the edges of the view controller’s view. The current storyboard preview device is the iPhone 8. On this device, the UI looks fine. But it’s time to scrutinize how the launch screen looks on other devices and screen sizes.

Previewing layouts on multiple screen sizes

Interface Builder’s Preview mode lets you see your screen layout on various devices without running the project on a simulator or device. Preview is useful, but you still have to keep in mind its limitations.

Adding constraints

The first thing you’ll learn is how to add constraints to a view in Interface Builder.

Editing constraints

The Safe Area layout guide helps prevent obscured content. However, with this background image view, you want to have it fill the screen edges on every device.

Constraint inequalities

The background image view uses equality constraints. In addition to equality constraints, you can also create inequality constraints using Auto Layout.

Implementation

Are you ready to spice up the launch screen? Fantastic!

Pros/cons and who is it for?

Apple has taken something complex and turned it into something comparatively elegant. However, as with any solution, there are benefits and drawbacks.

Using Xibs

Have you ever heard about .xib files? Even if you say no, I bet you’ve probably used them. Those screens that are part of a scene in your storyboard are .xib files. The only difference is that, thanks to the storyboard, you have some benefits, like segues and a nice look at the workflow of your app. Before carrying on and to avoid ambiguity, it’s important to understand the differences between .xib and .nib files.

How to achieve modularity with .xib

If you’re working on a team, it can be pretty rough to deal with merge conflicts when everybody is using a single storyboard. That’s why you need a way to work on screens in a more decoupled way.

The .xib object life cycle

It’s important to understand how .nibs files are loaded, so you can create better interfaces that behave as expected and have good performance. The following diagram shows the chain of steps executed to display a view using a nib:

Practical use case

Open MessagingApp.xcodeproj in the starter folder. Build and run. You can see a contact list; it’s a simple table view that shows the name of the contact and has an accessory info button on the right. But if you press the info button, nothing happens. Well, it’s time to do something about that!

// 1
override init(frame: CGRect) {
  super.init(frame: frame)
  loadView()
}
// 2
required init?(coder aDecoder: NSCoder) {
  super.init(coder: aDecoder)
  loadView()
}

func loadView() {
  // 3
  let bundle = Bundle(for: ContactPreviewView.self)
  // 4
  let nib =
    UINib(nibName: "ContactPreviewView", bundle: bundle)
  // 5
  let view = nib.instantiate(withOwner: self).first as! UIView
  // 6
  view.frame = bounds
  // 7
  addSubview(view)
}
@IBOutlet var contactPreviewView: ContactPreviewView!

// MARK: - Setup Contact Preview
override func tableView(_ tableView: UITableView, 
    accessoryButtonTappedForRowWith indexPath: IndexPath) {
  // 1
  let contact = contacts[indexPath.row]
  // 2
  view.addSubview(contactPreviewView)
  // 3
  contactPreviewView
    .translatesAutoresizingMaskIntoConstraints = false
  // 4
  NSLayoutConstraint.activate([
    contactPreviewView.widthAnchor.constraint(
      equalToConstant: 150),
    contactPreviewView.heightAnchor.constraint(
      equalToConstant: 150),
    contactPreviewView.centerXAnchor.constraint(
      equalTo: view.centerXAnchor),
    contactPreviewView.centerYAnchor.constraint(
      equalTo: view.centerYAnchor)
  ])
  // 5
  contactPreviewView.transform =
    CGAffineTransform(scaleX: 1.25, y: 1.25)
  contactPreviewView.alpha = 0
  // 6
  UIView.animate(withDuration: 0.3) { [weak self] in
    guard let self = self else { return }
    self.contactPreviewView.alpha = 1
    self.contactPreviewView.transform =
      CGAffineTransform.identity
  }
}

@IBOutlet var photoImageView: UIImageView!
@IBOutlet var nameLabel: UILabel!
@IBOutlet var contentView: UIView!

contactPreviewView.nameLabel.text = contact.name
contactPreviewView.photoImageView.image =
  UIImage(named: contact.photo)
@objc private func hideContactPreview() {
  // 1
  UIView.animate(withDuration: 0.3, animations: { [weak self] in
    guard let self = self else { return }
    self.contactPreviewView.transform =
      CGAffineTransform(scaleX: 1.25, y: 1.25)
    self.contactPreviewView.alpha = 0
  }) { (success) in
    // 2
    self.contactPreviewView.removeFromSuperview()
  }
}
private func configureGestures() {
  // 1
  let tapGesture = UITapGestureRecognizer(
    target: self, 
    action: #selector(hideContactPreview))
  // 2
  contactPreviewView.addGestureRecognizer(tapGesture)
  view.addGestureRecognizer(tapGesture)
}
configureGestures()

Editing constraints using Interface Builder

Open ContactPreviewView.xib. Select the Photo Image View, and on the right side of the Interface Builder, select the Size inspector.

Pros/cons and who is it for?

.xib files can offer many advantages, especially when compared to storyboards. But remember, you can use both tools in your project.

Pros

Cons

  • You can’t have relationships between screens, something that’s simple and useful while using storyboards.
  • No visualization of the workflow of your app. That’s something you can only have with storyboards.
  • If the view is dynamic, it can be difficult to create using .xibs.

Challenges

Great job making it this far. Here are a few challenges to help solidify what you learned.

Key points

  • The preview feature helps you see your UI on different screen sizes without running the project on a simulator or device.
  • You can use the Add New Constraints button to apply Auto Layout constraints in Interface Builder.
  • You can use the Attributes inspector to set the object’s properties.
  • Remember to account for the Safe Area layout guide to ensure devices with a notch display as intended at runtime.
  • You can set equality and inequality constraint relations between items.
  • The Issue navigator can show you the conflicting constraints in a storyboard.
  • Using .xib files is a great way to achieve modularity.
  • There are benefits and drawbacks to every tool. Building Auto Layout constraints in storyboards or .xib files with Interface builder is no exception. Consider the pros and cons of each to conclude an optimized solution for what you need.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2021 Razeware LLC

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.