In part 5 we have seen how we can add birthdays to the app. But the data was just printed to the debug console.

In this post we want to implement that the birthdays we add are actually shown in the birthday list.

Open BirthdaysListDataProvider and add the following property:

private var birthdays = [Birthday]()

Add the following code outside of the BirthdaysListDataProvider class:

extension BirthdaysListDataProvider {
  func addBirthday(birthday: Birthday) {
    birthdays.append(birthday)
  }
}

Replace the code inside of

tableView(_:numberOfRowsInSection:)

with this:

return birthdays.count

Replace the line cell.textLabel?.text = "Row: (indexPath.row)" with the following code:

let birthday = birthdays[indexPath.row]
cell.textLabel?.text = birthday.firstName

Now open BirthdaysListViewController and add the following code in the body of the if clause of contactPicker(_:didSelectContact:):

dataProvider?.addBirthday(person)
tableView.reloadData()

Build and run. Tap the plus button and select John Appleseed. You should see something like this:
Simulator Screen Shot 30.08.2015 21.43.50

Great! Now we need a cell that actually can show the name of the person and his/her birthday. Let's add a first version of a custom table view cell. Remember, later we want to have a nice progress show in the cell behind the name. But for now it is enough to show the name and the birthday.

Select File / New / File..., chose iOS / Source / Cocoa Touch Class, click Next. Put in the name BirthdayCell, make it a subclass of UITableViewCell and click Next. Select the BirthdaysList folder and click Create. Open the new created class and remove the two methods from the Xcode template.

Add these two properties:

let nameLabel: UILabel
let birthdayLabel: UILabel

Xcode will complain that

Class 'BirthdayCell' has no initializers

True. But we are going to change that. Add these two initializers:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    
    nameLabel = UILabel()
    nameLabel.translatesAutoresizingMaskIntoConstraints = false
    
    birthdayLabel = UILabel()
    birthdayLabel.translatesAutoresizingMaskIntoConstraints = false
    
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    addSubview(nameLabel)
    addSubview(birthdayLabel)
    
    let views = ["name": nameLabel, "birthday": birthdayLabel]
    var layoutConstraints = [NSLayoutConstraint]()
    
    layoutConstraints.append(nameLabel.centerXAnchor.constraintEqualToAnchor(centerXAnchor))
    layoutConstraints.append(nameLabel.centerYAnchor.constraintEqualToAnchor(centerYAnchor))
    layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("[birthday]-|", options: [], metrics: nil, views: views)
    layoutConstraints += NSLayoutConstraint.constraintsWithVisualFormat("V:[birthday]|", options: [], metrics: nil, views: views)
    
    NSLayoutConstraint.activateConstraints(layoutConstraints)
  }

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

The constrains in the initializer center the nameLabel and put the birthdayLabel at the bottom right corner. The second initializer is needed because it is a required initializer of UIView and in Swift we need to implement all required initializer as soon as we implement one initializer ourselves.

No let's use our new shiny table view cell. Open BirthdaysListDataProvider.swift and replace in registerCellsForTableView(_:) UITableViewCell.self with BirthdayCell.self.

Replace the code in tableView(_:cellForRowAtIndexPath:) with this:

let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifer, forIndexPath: indexPath) as! BirthdayCell

let birthday = birthdays[indexPath.row]
cell.nameLabel.text = birthday.firstName
cell.birthdayLabel.text = "\(birthday.birthday.day) \(birthday.birthday.month)"

return cell

Build and run. Add a person to the list. The result should look like this:

Simulator Screen Shot 31.08.2015 20.50.19

That's it for today. Next time we will make the table view cell nicer.