Errata for UIKit Apprentice 2nd Edition

Creating this topic to catch any typos and bugs in the 2nd Edition of UIKit Apprentice.

In page 29 (Chapter 1: Introduction → What you need):

(earlir than Big Sur 11.3 or earlier)

earlir should be earlier, although I suspect you only wanted one of those two.

In page 30 (Chapter 1: Introduction → Xcode):

If you’re look at an article or book that predates Swift, it’s seriously out of date.

look should be looking.

Chapter 29. Maps
There should be mentioned that there’s need for checking of CLLocationManager().authorizationStatus if the user taps on the “Map” tab right after the app loads
/ the authorizationStatus is checked only in getLocation() in CurrentLocationViewController /.
Maybe solution not to be included in the chapter, but still to be considered a possible bug.

Chapter 29. Maps
We should check in func region(for:) if the distance between top left and bottom right is too small (or 0, for example in case of several tags all in one location), or else the span is (0,0) and the map is zoomed-in when showLocaitions is pressed.

if ((topLeft.latitude - bottomRight.latitude) * 111_139 < 100) && ((topLeft.longitude - bottomRight.longitude) * 111_139 < 100) {
        region = MKCoordinateRegion(center: center, latitudinalMeters: 1000, longitudinalMeters: 1000)
      } else {
        let extraSpace = 1.2
        let span = MKCoordinateSpan(latitudeDelta: abs(topLeft.latitude - bottomRight.latitude) * extraSpace,
                                    longitudeDelta: abs(topLeft.longitude - bottomRight.longitude) * extraSpace)
        region = MKCoordinateRegion(center: center, span: span)
      }

chapter 5, section 1 “getting the difference” - under Algorithms:
However, in the programs that you write, you’ll probably have to come up with a few algorithms of your own at some time or other.

I would write; “at some time or another”, or “some time or other”. But, to me at some time or another sound the most right.

Chapter 32:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 
let cellIdentifier = "SearchResultCell"
  var cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) 
 
 if cell == nil {
    cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier)
  }

  cell.textLabel!.text = searchResults[indexPath.row]
  return cell
}

While ‘dequeueReusableCell(:withIdentifier:)’ returns a UITableViewCell?, in case cell is nil, the cell allocated from within the if statement is a non optional UITableViewCell.

if Im understanding correctly, after the ‘if’ statement the cell object might be an optional or not depending on the way it was allocated.

The compiler treats the cell object as an optional, as a result these lines will not compile:
‘cell.textLabel!.text = searchResults[indexPath.row]’
‘return cell’

We cant unwrap the cell object safely because at running time theres a possibility that it might not be an optional.

After following the tutorial further more, it would seem that in chapter 33 this very bit of code was introduced as it were supposed to be:

let cellIdentifier = "SearchResultCell"

var cell: UITableViewCell! = tableView.dequeueReusableCell( withIdentifier: cellIdentifier)
if cell == nil {
  cell = UITableViewCell(
    style: .subtitle, reuseIdentifier: cellIdentifier)
}

Here the cell is not type inferred and is unwrapped at creation.
Chapter 32’s version of the code should be updated to this version.