Welcome to my Day 48 report for the 100 Days of Swift initiative!
I will be tackling Day 44’s program in my ongoing attempt to catch up on the last days. Here is what we learned in Day 43:
- Collection Views, an alternative to Table Views when we want to display data in grids instead of in rows
- Image Pickers, a safe way to access, browse and choose a picture from the photo library
- Universally Unique Identifiers, or
UUID
, to create unique names for our files. - Custom classes and more…
Review
- We can force a
UICollectionView
to reload all its data by calling itsreloadData()
method, exactly as we did forUITableViews
. - When dequeueing a custom collection view cell we need to typecast it to our specific type. We have not done this yet but it would work the same if we had done this with a table view cell.
- This time I made a mistake and I chose the “Classes must always have a custom initializer” option which was explained in this way:
They don’t need a custom initializer if their properties are given initial values somewhere, for example if we give them default values.
The correct answer was CALayer
can add borders and round corners to views.
- Each app has its own documents directory.
- The
path
property of aURL
gives us the location as a string. UIKit
re-uses collection view cells for performance reasons.- When the user selects a picture using
UIImagePickerController
we’ll be sent a dictionary of data. - Collection view items are referenced using section and item rather than section and row.
Data
can hold any kind of binary dataUIColor
can be created as a grayscale color, using thewhite
property and thealpha
property of its initialiser.UIImagePickerController
lets us read photos from the user’s photo library.- We can create custom classes for our collection view cells.
I wonder if Paul is really reading my learning reports because right now it seems that the difficulty for the choice in the questions has ramped up a considerably bit. This time one really needs to think about it. Good job, Paul!
Challenges
Challenge 1: add a second UIAlertController
that gets shown when the user taps a picture, asking them whether they want to rename the person or delete them.
I have seen some people on the Slack channel dedicated to this initiative asking whether the correct approach would have been to add a UIAlertAction
but Paul promptly answered « No, it should be a UIAlertController
».
The way I solved it is via control flow, that is: IF the person’s name is “Unknown”—which is the state we have a picture in when we first import it—clicking on it will invoke the already programmed alert controller. ELSE we will create another alert controller with two alert actions: the first will actually be very similar to the one we have already programmed—I have just changed the name of the variables for my endless need for clarity—while the second will remove the item from the people’s array and reload the data!
BUM! It works!
Easy? Now I say yes, but I know Paul will smile as we both know that even a week or so ago this would have been very, very hard to do!
Challenge 2: try using picker.sourceType = .camera
when creating your image picker, which will tell it to create a new image by taking a photo.
This will only be available for testing on real devices, not on the simulator, so we get an extra hint, that is to check the return value of UIImagePickerController.isSourceTypeAvailable()
before trying to use this feature…!
I was actually quite afraid of this challenge but I think I solved it with as little as 6 lines of code (+ an edit in the Info.plist file). As I had no real idea where to start from I opened the Documentation at the voice UIImagePickerController
and started to read it, finding so many interesting things and… clear instructions!
Some part of it was indeed misleading but I think it was simply because I had not enough experience with the terminology. In any case, inside the addNewPerson
method I added a control flow statement after the the picker.allowsEditing = true
line.
if UIImagePickerController.isSourceTypeAvailable(.camera) {
picker.sourceType = .camera
} else {
picker.sourceType = .photoLibrary
}
The nice thing is that I even tried to launch it without modifying the .plist file for the permission! The crash was so nice because… it actually didn’t do anything on the device, it didn’t go back to the home screen. Anyway…
I added the required line to the Info.plist file (the Camera Usage one) and the app magically worked.
What I would still improve here is that when I launch the app on my iPhone XS I can only take a photo, nothing else so I would like to allow also videos and all the other options as if it were a full-fledged camera. Furthermore I would like to retain the chance to access the photo library even when I have the camera running.
The first part was (partially) solved like this:
@objc func addNewPerson() {
let picker = UIImagePickerController()
picker.allowsEditing = true
if UIImagePickerController.isSourceTypeAvailable(.camera) {
if let availableMediaTypes = UIImagePickerController.availableMediaTypes(for: .camera) {
picker.mediaTypes = availableMediaTypes
picker.sourceType = .camera
}
} else {
picker.sourceType = .photoLibrary
}
picker.delegate = self
present(picker, animated: true)
}
… and adding the microphone usage privacy description in the .plist.
I now get also the chance to record a video… but what about the rest?
Anyway, I will probably find a way later. In the meantime you can find the repository here.
Challenge 3: modify project 1 so that it uses a collection view controller rather than a table view controller.
This time I really think I will be making a copy of it!
I did it, it works. It started up quite easy and then it ramped up because of the level of attention needed while performing each step.
I will not go through each step in great detail because it was simply trying to remember what we did in Project 10 and repeat it adapting it to our needs.
After the basic edits in the storyboard I changed the view-controller’s class conformance to a collection-view and then went down step by step fixing the mistakes.
Once I got to the cellForItemAt
method I created a new ImageCell
cocoa-touch class, created the outlets and performed the necessary changes.
That’s it! You can find the repository here.
So! Another challenge is behind! Motivation is ramping up, especially when you see the apps you create running on the device! That’s so awesome!
Please 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.
Thank you!
Until 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!