I have just read what the three challenges are about and… I really do not feel like ranting anymore…
I mean… I will go for them but…
Review
Here is what, in theory, I have learned in this lesson… again, learn is a big word, I have just listened to a video, repeated the instructions and read the description of the video once more so… learn… yeah…
I was at my weekly Taiji-Quan lesson this Tuesday and I spoke with the trainer about the repeating thousands of times thing and he said something I really agree with and that makes me clash with the current coding-learning path:
Sure, you can repeat it ten thousand times, but if you repeat it without understand whether you are doing it right or wrong and why and how you can make it better and how you should feel, all those times will be for nothing!
So, yeah, let’s just review, shall we?
- We can choose from multiple map styles, such as satellite maps. Yes, sure, but we have not been told neither how nor where to look for it and I am really sick of people telling me “just Google it”. First of all I do not use Google! Second: it is in my rights not to use it so I need to be given alternative options where to learn onto. Really sick of all this…
- Map views have annotations that weren’t created by us, such as the user’s location. Fine, this was clearly explained.
- Map annotations may or may not have a title. I have answered the other option because I am pretty sure during the explanation it was said that annotations have a title, a subtitle and a set of coordinates but, of course, I am wrong and that’s it, right? Explanations are for the faithless ones!
- Custom annotations can have extra properties of our choosing.. Ooooh, wow! 🙂 …
MKPinAnnotationView
is a built-in class that draws tappable pins on the map. Right, exactly! Can’t wait to use it more…- We can add individual map annotations, or add lots at once. By the time this was explained I was still writing the individual ones but thankfully someone invented the Pause button…
- If we make a class and don’t give all its properties default values, we need to create a custom initialiser. So, the other option was “We need to import
MapKit
in order to add a map view to our app”, which is exactly what we did… oh no, right, you are talking about adding the map kit view to the storyboard, right? Very funny, yes very funny… - The
dequeueReusableAnnotationView(withIdentifier:)
method might return nil. Chose this one only because the other one looked ridiculous… - There’s a specific
UIButton
type calleddetailDisclosure
, which creates an “i” with a ring around it. Yes, I was awake during this part of the course… - The
MKMapViewDelegate
protocol lets us control the way anMKMapView
works. Yeah, it seems so… - Annotation titles are automatically shown by
MapKit
. Thanks goodness, I thought we had to do everything ourselves… - Every map annotation needs a latitude and longitude coordinate. Fine, an easy last one…
That’s it…
Let’s move on to the challenges before I get hungry!
Challenges
Challenge 1: try typecasting the return value from dequeueReusableAnnotationView()
so that it’s an MKPinAnnotationView
. Once that’s done, change the pinTintColor
property to your favorite UIColor
.
First attempt
Added as? MKPinAnnotationView
after the dequeuing call and then wrote annotationView?.pinTintColor = .orange
but all this did absolutely nothing. Why? Who knows?
Second attempt
Moved the annotationView?.pinTintColor = .orange
inside the if-else
statement. Now it works. I would be glad to know why but, sincerely, who cares at this point? I should just mindlessly repeat, right?
Challenge 2: add a UIAlertController
that lets users specify how they want to view the map. There’s a mapType
property that draws the maps in different ways. For example, .satellite
gives a satellite view of the terrain.
First attempt
Inside viewDidLoad
I created a bar button item like this:
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Map Type", style: .plain, target: self, action: #selector(chooseMapType))
At the end of the class I then created my magic function:
@objc func chooseMapType() {
let mapTypeAC = UIAlertController(title: "Map Type", message: "Choose your preferred map type", preferredStyle: .alert)
mapTypeAC.addAction(UIAlertAction(title: "Standard", style: .default, handler: { [weak self] _ in
self?.mapView.mapType = .standard
}))
mapTypeAC.addAction(UIAlertAction(title: "Hybrid", style: .default, handler: { [weak self] _ in
self?.mapView.mapType = .hybrid
}))
mapTypeAC.addAction(UIAlertAction(title: "Satellite", style: .default, handler: { [weak self] _ in
self?.mapView.mapType = .satellite
}))
present(mapTypeAC, animated: true)
}
I know, I could be using trailing closure syntax but I do not feel comfortable enough by now and I would like to have as much readable code as possible.
Build, run… bum… it works!
Also, crazy fast!
Challenge 3: modify the callout button so that pressing it shows a new view controller with a web view, taking users to the Wikipedia entry for that city.
So, this was a though one and it took me almost 2 hours only to figure out all the details.
In short, I created a new view controller in the storyboard and an accompanying class which is very similar to the one in project 4 (I mean, almost the same, just a bit slimmer and with a few less properties and details in the view).
Then I changed the mapView(_:view:control:)
method to this:
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
guard let capital = view.annotation as? Capital else { return }
let capitalTitle = capital.title
if let webViewController = storyboard?.instantiateViewController(withIdentifier: "WebView") as? DetailViewController {
if let title = capitalTitle {
webViewController.title = title
webViewController.websiteToLoad = "en.wikipedia.org/wiki/" + title
navigationController?.pushViewController(webViewController, animated: true)
}
}
}
I don’t want to bore you with the silly mistakes I did, they are not pedagogic at all!
Anyway, it works! And that’s enough!
I think I will go back to the Country Facts app and add a web view for the capitals in there tomorrow! With all this code in place it should not be too complex.
So… here is the finished code. You will find three branches: one for the basic project (master), one for the first two challenges (challenge16-1) and one for the last one (challenge16-2) which is branching from the second branch. I didn’t want to mess up things that were working!
Please don’t forget to drop a hello and a thank you to Paul for all his great work (you can find him on Twitter) and don’t forget to visit the 100 Days Of Swift initiative page.
Thanks for reading!
Till the next one!
If you like what I’m doing here please consider liking this article and sharing it with some of your peers. If you are feeling like being really awesome, please consider making a small donation to support my studies and my writing (please appreciate that I am not using advertisement on my articles).
If you are interested in my music engraving and my publications don’t forget visit my Facebook page and the pages where I publish my scores (Gumroad, SheetMusicPlus, ScoreExchange and on Apple Books).
You can also support me by buying Paul Hudson’s books from this Affiliate Link.
Anyways, thank you so much for reading!
Till the next one!