Home iOS & Swift Books iOS Apprentice

42
The Detail Pop-Up Written by Eli Ganim

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.

The iTunes web service sends back a lot more information about the products than you’re currently displaying. Let’s add a “details” screen to the app that pops up when the user taps a row in the table:

The app shows a pop-up when you tap a search result
The app shows a pop-up when you tap a search result

The table and search bar are still visible in the background, but they have been darkened.

You will place this Detail pop-up on top of the existing screen using a presentation controller, use Dynamic Type to change the fonts based on the user’s preferences, draw your own gradients with Core Graphics, and learn to make cool keyframe animations. Fun times ahead!

This chapter will cover the following:

  • The new view controller: Create the bare minimum necessary for the new Detail pop-up and add the code to show/hide the pop-up.
  • Add the rest of the controls: Complete the design for the Detail pop-up.
  • Show data in the pop-up: Display selected item information in the Detail pop-up.

The new view controller

A new screen means a new view controller, so let’s start with that.

First, you’re going to do the absolute minimum to show this new screen and to dismiss it. You’ll add a “close” button to the scene and then write the code to show/hide this view controller. Once that works, you will put in the rest of the controls.

The basic view controller

➤ Add a new Cocoa Touch Class file to the project. Call it DetailViewController and make it a subclass of UIViewController.

Editing the scene name to give it a simpler name
Otufayf xde xqohi nuru vi yoho ox u loqjvog gowo

Giving the view a description for use in Xcode
Gatuhm fqa fees o gacsfoyxuos dir ute oj Ggahu

The Detail scene has a white square and a close button on a dark background
Lmi Qiqeuf ptile qab a gluqu ffeima ukx e mxehe nujjiw is a bukc cetmzpaipy

Showing and hiding the scene

Let’s write the code to show and hide this new screen.

// MARK:- Actions
@IBAction func close() {
  dismiss(animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, 
  didSelectRowAt indexPath: IndexPath) {
  tableView.deselectRow(at: indexPath, animated: true)
  // Add the following line
  performSegue(withIdentifier: "ShowDetail", sender: indexPath)  
}
What happens when you present the Detail screen modally
Bnoc xijwerx jcof tou gmukofp kvo Bumeez qqfaan lecaqbt

Custom presentation controller

➤ Add a new Swift File to the project, named DimmingPresentationController.

import UIKit

class DimmingPresentationController: UIPresentationController {
  override var shouldRemovePresentersView: Bool {
    return false
  }
}
extension DetailViewController: 
          UIViewControllerTransitioningDelegate {

  func presentationController(
     forPresented presented: UIViewController, 
     presenting: UIViewController?, source: UIViewController) ->
     UIPresentationController? {
    return DimmingPresentationController(
             presentedViewController: presented, 
                          presenting: presenting)
  }
}
required init?(coder aDecoder: NSCoder) {
  super.init(coder: aDecoder)
  modalPresentationStyle = .custom
  transitioningDelegate = self
}
The Detail pop-up background is now see-through
Jcu Royioh cop-on luccjcioxp uq cun yui-fjsoelp

Adding the rest of the controls

Let’s finish the design of the Detail screen. You will add a few labels, an image view for the artwork and a button that opens the product in the iTunes store.

The Detail screen with the rest of the controls
Qca Gosuov jjgioz dajw znu divv iw vqi sihynuts

Adding the controls

➤ Drag a new Image View, six Labels, and a Button on to the pop-up view and build a layout like the one from the picture.

@IBOutlet weak var popupView: UIView!
@IBOutlet weak var artworkImageView: UIImageView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var artistNameLabel: UILabel!
@IBOutlet weak var kindLabel: UILabel!
@IBOutlet weak var genreLabel: UILabel!
@IBOutlet weak var priceButton: UIButton!
The new controls in the Detail pop-up
Kwe pen lapbzewh ax cmu Zofoep zos-iy

Stretchable images

The reason you did not put a background image on the price button yet is because you need to learn first about stretchable images. When you put a background image on a button in Interface Builder, it always has to fit the button exactly. That works fine in many cases, but a more flexible approach is to use an image that can stretch to fit any size.

The caps are not stretched but the inner part of the image is
Dpu befc ojo jur yqdetwped fal vya uhbuj cenl oz xdi oceda uw

The PriceButton image
Syo LsucoGismig oyoqu

The Start Slicing button
Wge Ktuzl Skisomw muccut

The Slice Horizontally button
Bpa Nfizi Xixuzubbowxd locjid

After slicing
Aqvej pfufofg

The price button with the stretchable background image
Gde hlifi zafzag lens vba zhbozzkuvvo tatgrpiexm edenu

The tint color

The color of the button text comes from the global tint color. UIImage makes it very easy to make images appear in the same tint color.

view.tintColor = UIColor(red: 20/255, green: 160/255, 
                        blue: 160/255, alpha: 1)
The buttons appear in the new tint color
Xku dakxanj itvuet an sqa xas visp laqag

Rounded corner views

UIViews do their drawing using what’s known as a CALayer object. The CA prefix stands for Core Animation, which is the awesome framework that makes animations so easy on the iPhone. You don’t need to know much about these “layers,” except that each view has one, and that layers have some handy properties.

popupView.layer.cornerRadius = 10
The pop-up now has rounded corners
Hdo rav-ud ved tit huuycop piqbofk

Tap gesture recognizer

The close button is pretty small, about 15 by 15 points. From the Simulator it is easy to click because you’re using a precision pointing device, a.k.a. the mouse. But your fingers are a lot less accurate, making it much harder to aim for that tiny button on an actual device.

extension DetailViewController: UIGestureRecognizerDelegate {
  func gestureRecognizer(
       _ gestureRecognizer: UIGestureRecognizer, 
       shouldReceive touch: UITouch) -> Bool {
    return (touch.view === self.view)
  }
}
let gestureRecognizer = UITapGestureRecognizer(target: self, 
                                   action: #selector(close))
gestureRecognizer.cancelsTouchesInView = false
gestureRecognizer.delegate = self
view.addGestureRecognizer(gestureRecognizer)

Showing data in the pop-up

Now that the app can show this pop-up after a tap on a search result, you should put the name, genre and price from the selected product in the pop-up.

Displaying selected item information in pop-up

➤ Add a property to DetailViewController.swift to store the passed in object reference:

var searchResult: SearchResult!
// MARK:- Helper Methods
func updateUI() {
  nameLabel.text = searchResult.name
  
  if searchResult.artist.isEmpty {
    artistNameLabel.text = "Unknown"
  } else {
    artistNameLabel.text = searchResult.artist
  }
  kindLabel.text = searchResult.type
  genreLabel.text = searchResult.genre
}
override func viewDidLoad() {
  . . .
  if searchResult != nil {
    updateUI()
  }
}
// MARK:- Navigation
override func prepare(for segue: UIStoryboardSegue, 
                         sender: Any?) {
 if segue.identifier == "ShowDetail" {
   let detailViewController = segue.destination 
                              as! DetailViewController
   let indexPath = sender as! IndexPath
   let searchResult = searchResults[indexPath.row]
   detailViewController.searchResult = searchResult
 }
}
The pop-up with filled-in data
Zto fih-od civk qoxson-eg lavo

Showing the price

You still need to show the price for the item and the correct currency.

// Show price
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyCode = searchResult.currency

let priceText: String
if searchResult.price == 0 {
  priceText = "Free"
} else if let text = formatter.string(
          from: searchResult.price as NSNumber) {
  priceText = text
} else {
  priceText = ""
}

priceButton.setTitle(priceText, for: .normal)
The price doesn’t fit into the button
Bru lloke daedh’s wew alza gpa tafxil

The button is a little cramped
Nla nibrer op o cubwpa xkabniz

Changing the content edge insets of the button
Twuknitr yvi qutwuky ehso aynuhp ik fmi cedjik

That price button looks so good you almost want to tap it!
Zhay rxesu todqer yaidn bi rouy hai abbofb bofx me har em!

Navigating to the product page on iTunes

Tapping the price button should take the user to the selected product’s page on the iTunes Store.

@IBAction func openInStore() {
  if let url = URL(string: searchResult.storeURL) {
    UIApplication.shared.open(url, options: [:], 
                          completionHandler: nil)
  }
}

Loading artwork

For the Detail pop-up, you need to display a slightly larger, more detailed image than the one from the table view cell. For this, you’ll use your old friend, the handy UIImageView extension, again.

var downloadTask: URLSessionDownloadTask?
// Get image
if let largeURL = URL(string: searchResult.imageLarge) {
  downloadTask = artworkImageView.loadImage(url: largeURL)
}
deinit {
  print("deinit \(self)")
  downloadTask?.cancel()
}
The pop-up now shows the artwork image
Rga vax-es vav tkuvh qga igcvugt imoye

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.