Day 44 - 100 Days of Swift

3 minute read

Project 10 (part 3)

Day 44 is the third part of the tenth project. You review the stuff that you’ve learned in this project and then he gives you three challenges. The first challenge is to change it so that when the user taps on a cell they are presented with an alert asking them if they want to delete or rename the person, and then to implement those two pieces of functionality. The second challenge it to use the camera instead of the photo library for the UIImagePickerController. The third is to rewrite the first project to use a collection view instead of a table view.

First I pulled out all the contents of collectionView(_:didSelectRowAt:) into their own function for reuse later:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private func presentRenameAlert(for indexPath: IndexPath) {
    let person = people[indexPath.item]

    let alertController = UIAlertController(title: "Rename Person",
                                            message: nil,
                                            preferredStyle: .alert)
    alertController.addTextField() { textField in
        textField.text = person.name == "Unknown" ? "" : person.name
        textField.placeholder = "Person's Name"
    }

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
    alertController.addAction(cancelAction)

    let saveAction = UIAlertAction(title: "Ok", style: .default)
    { [weak self, weak alertController] _ in
        guard let newName = alertController?.textFields?.first?.text else { return }
        person.name = newName

        self?.collectionView.reloadItems(at: [indexPath])
    }

    alertController.addAction(saveAction)
    present(alertController, animated: true)
}

Then I added a new function that would present an action sheet for the user to choose an option from:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private func presentCellOptionAlert(for indexPath: IndexPath) {
    let alertController = UIAlertController(title: "Edit Person",
                                            message: nil,
                                            preferredStyle: .actionSheet)

    let renameAction = UIAlertAction(title: "Rename",
                                     style: .default) { [weak self] _ in
        self?.presentRenameAlert(for: indexPath)
    }
    alertController.addAction(renameAction)

    let deleteAction = UIAlertAction(title: "Delete",
                                     style: .destructive) { [weak self] _ in
        guard let selfVC = self else { return }
        selfVC.people.remove(at: indexPath.row)
        selfVC.collectionView.deleteItems(at: [indexPath])
    }
    alertController.addAction(deleteAction)

    let cancelAction = UIAlertAction(title: "Cancel",
                                     style: .cancel)
    alertController.addAction(cancelAction)

    present(alertController, animated: true)
}

The rename action presents the alert we built previously. The delete action deletes the Person associated with the passed in IndexPath and then deletes the cell at that IndexPath as well. The cancel action just dismisses the alert.

For the second challenge, I just added these lines to addPerson():

1
2
3
if UIImagePickerController.isSourceTypeAvailable(.camera) {
    picker.sourceType = .camera
}

It just checks that the current device has a camera (the simulator doesn’t), and then sets the picker’s source type to .camera if it does.

You also have to add a description for how your app uses the camera to the Info.plist:

1
2
3
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) uses your camera to let you take pictures of people.</string>
<key>CFBundleDevelopmentRegion</key>

With that, the app looks like this:

Screenshot of working app (with my dog Schmitt).

I decided to skip the third challenge for today because I’m a little short on time and I feel pretty comfortable with the basics of collection views. I might come back to it some time when I have more free time though. You can find my version of this project at the end of day 44 on Github here.