Sans Pareil Technologies, Inc.

Key To Your Business

Lab 12: Alert View


In this lab session, we will modify the table view application developed in lab11 and add an alert view before the Person entity is saved in PersonSaveViewController.
Controllers 
Edit the prepareForSegue functions in PersonCreateViewController and PersonEditViewController to set the segue identifier in PersonSaveViewController. Make sure that the segue identifiers specified match the values specified in the storyboard.
Storyboard 
  • Modify the storyboard and remove the segue action connections from the “Done” button in the confirmation screen to the “Exit” button.
  • Control-drag a connection from the View Controller to the Exit button instead, and select the same segue action functions as before. Specify identifiers for these segues.
  • Add a save action function to PersonSaveViewController and connect the Done button to the action.
Save 
Modify the PersonSaveViewController to add an action function for the Done button. To unwind the application back to the appropriate segue action function in the table view controller, we will use the segue identifier that was specified in the prepareForSegue function.

In the button action function, we will display an action sheet that will confirm that the user wishes to save the Person.

We will also add a function that will display an alert if the segue identifier was not set. This will display the message and then exit the application with an error.
class PersonSaveViewController: UIViewController {
  
  override func viewDidLoad() {
    super.viewDidLoad()
    check()
    display()
  }
  
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  //MARK: Actions
  @IBAction func save() {
    func title() -> String {
      switch segueIdentifier ?? "" {
      case "AddPerson":
        return "Create Person?"
      case "UpdatePerson":
        return "Save Person?"
      default:
        fatalError("Segue Identifier not set for \(self)")
      }
    }

    func message() -> String {
      switch segueIdentifier ?? "" {
      case "AddPerson":
        return "Do you wish to create new person with email: \(person!.email ?? "")"
      case "UpdatePerson":
        return "Do you wish to update person with email: \(person!.email ?? "")"
      default:
        fatalError("Segue Identifier not set for \(self)")
      }
    }

    //let alertController = UIAlertController(title: title(), message: message(), preferredStyle: .alert)
    let alertController = UIAlertController(title: title(), message: message(), preferredStyle: .actionSheet)
    let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in })
    let ok = UIAlertAction(title: "OK", style: .default, handler: { _ in
      self.performSegue(withIdentifier: self.segueIdentifier!, sender: self)
    })
    alertController.addAction(cancel)
    alertController.addAction(ok)
    alertController.preferredAction = ok
    present(alertController, animated: true, completion: nil)
  }
  
  //MARK: Outlets
  @IBOutlet weak var textView: UITextView!
  var person : Person? = nil
  var segueIdentifier : String? = nil
  
  //MARK: Internals
  private func display() {
    if let p = person {
      let middleName = p.middleName != nil ? p.middleName! : ""
      let email = p.email != nil ? p.email! : ""
      
      let html =
      """
      <div>
      <label>First Name:</label> <label>\(p.firstName)</label><br/>
      <label>Middle Name:</label> <label>\(middleName)</label><br/>
      <label>Last Name:</label> <label>\(p.lastName)</label><br/>
      <label>Email:</label> <label>\(email)</label><br/>
      <label>Age:</label> <label>\(p.age)</label>
      </div>
      <br/><br/>
      <div>Click <b>Save</b> button to save this information, or the <b>Edit</b>
      button to go back and re-edit the information.</div>
      """
      
      let attrStr = NSAttributedString(html: html)
      textView.attributedText = attrStr
    }
  }

  private func check() {
    guard let _ = segueIdentifier else {
      let alertController = UIAlertController(title:"Error", message: "Segue Identifier not set", preferredStyle: .alert)
      alertController.addAction(UIAlertAction(title: "OK", style: .destructive, handler: { _ in fatalError( "Segue identifier not set for \(self)" )}))
      present(alertController, animated: true, completion: nil)
      return
    }
  }
}
Try commenting out (or removing) the line of code that sets the segue identifier in PersonSaveViewController and to ensure that our check function does indeed show the error alert and halts the application.

Modify the table view controller to add a confirmation alert before deleting person entities displayed in the table.