Day 23 - 100 Days of Swift
Consolidation II (Projects 1-3)
Day 23 is a consolidation day where you review the first three projects. You go back over a bunch of stuff covered in the few days, but I won’t reiterate it here. He also gives you a challenge to build an app that displays all the flags from the flag game on a table view, lets you view them in a detail view, and lets you share the image and country name. It is very similar to the other projects, so I’ll move pretty quickly.
First, I added a countries
variable to hold an array of country names and filled it up in viewDidLoad
:
1
2
3
4
5
6
7
8
9
10
11
12
13
var countries: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
let fm = FileManager.default
let path = Bundle.main.resourcePath!
let items = try! fm.contentsOfDirectory(atPath: path)
countries = items.filter({ $0.hasSuffix("png")})
.map({ $0.components(separatedBy: ".")[0] })
}
I filtered to only the items with a png
suffix and then chopped off everything from the .
and after with a chain of higher order functions. This leaves an array with all the country names as they appear in the image names.
Next, I edited ViewController
to inherit from UITableViewController
, added a table view controller as the main view in the storyboard, and set its class to be ViewController
. This allowed me to override the UITableViewControllerDataSource
methods:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return countries.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FlagCell",
for: indexPath)
let country = countries[indexPath.row]
// Uppercase abbreviated names and capitalize full names
cell.textLabel?.text = country.count < 3 ?
country.uppercased() :
country.capitalized
cell.imageView?.image = UIImage(named: country)
return cell
}
Next, I added a new view controller to the storyboard, gave it an image view, and constrained to be big enough to display a flag:

Then I made a new DetailViewController
class that inherits from UIViewController
, set the new view controller’s class to it, and connected an outlet from the image view. Then I added a setupViews()
method to set the views up:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private func setupViews() {
guard let countryName = countryName else { return }
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .action,
target: self,
action: #selector(shareFlag))
title = countryName.count < 3 ?
countryName.uppercased() :
countryName.capitalized
flagImageView.image = UIImage(named: countryName)
flagImageView.addBorder()
}
You can see that the image view uses an addBorder()
method, which is similar to the one I made the other day. I just configured it to round the corners a little bit as well:
1
2
3
4
5
6
7
8
9
10
extension UIView {
func addBorder(width: CGFloat = 1, color: UIColor = .gray) {
self.layer.borderWidth = width
self.layer.borderColor = color.cgColor
self.layer.cornerRadius =
min(self.frame.height, self.frame.width) / 24
self.layer.masksToBounds = true
}
}
You can also see that the bar button item’s action is a method called shareFlag
so the last thing I did was add that and give a Photo Library Addition Usage to Info.plist
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@objc private func shareFlag(action: UIAlertAction! = nil) {
guard let imageName = countryName,
let image = UIImage(named: imageName),
let imageData = image.jpegData(compressionQuality: 0.8) else {
return
}
let items: [Any] = [imageData, imageName]
let activityVC =
UIActivityViewController(activityItems: items,
applicationActivities: [])
activityVC.popoverPresentationController?.barButtonItem =
navigationItem.rightBarButtonItem
present(activityVC, animated: true)
}
At the end of the day, it looks like this:

You can find my version of this project at the end of day 23 on Github here.
Reflections
Today was definitely a good review. Most of these things are things I’m familiar with, and have done many times. But I did have to look up how to get the filenames from from the main bundle. So I can’t say I knew it all by heart.
Slowly but surely, these project apps are getting more complicated and more interesting. I’m excited to see where things go next!