My 100 Days of Swift
Here is my brief summary of every little project included in 100 Days of Swift by Paul Hudson, mainly for my own future references.
PROJECT 25 — Selfie Share
MILESTONE PROJECT 8 (projects 22–24)
- Milestone project 8 was a bit different, the goal was not to create a new app from scratch but only to implement 3 swift extensions
Challenge:
- Extend
UIView
so that it has abounceOut(duration:)
method that uses animation to scale its size down to 0.0001 over a specified number of seconds. ✅ - Extend
Int
with atimes()
method that runs a closure as many times as the number is high. For example,5.times { print("Hello!") }
will print “Hello” five times. ✅ - Extend
Array
so that it has a mutatingremove(item:)
method. If the item exists more than once, it should remove only the first instance it finds. Tip: you will need to add theComparable
constraint to make this work! ✅
PROJECT 24 — Teqchnique project — Strings
Day 81–81, 27th of May
I learned about:
- Create String Extension in order to create custom properties and methods of the String struct for example extension allowing to access i-th character in the string like you would with array : string[i]
- more practice with String methods like: hasSuffix(), hasPrefix(), contains(where:), dropFirst(), uppercased(), capitalized(),etc
- Formating strings with NSAttributedString, example:
- There is also a chance to format just specific parts of the string
Challenge:
- Create a
String
extension that adds awithPrefix()
method. If the string already contains the prefix it should return itself; if it doesn’t contain the prefix, it should return itself with the prefix added. For example:"pet".withPrefix("car")
should return “carpet”. ✅ - Create a
String
extension that adds anisNumeric
property that returns true if the string holds any sort of number. Tip: creating aDouble
from aString
is a failable initializer. ✅ - Create a
String
extension that adds alines
property that returns an array of all the lines in a string. So, “this\nis\na\ntest” should return an array with four elements.
PROJECT 23 — Swift Ninja
Day 77–80, 26th of May
I decided to skip this SpriteKit project because I am not expecting to use SpriteKit in the future.
PROJECT 22 — Detect-a-Beacon
Day 74–76, 25th of May
I learned about:
- Requesting location
- CoreLocation framework
- CLLocationManager
Description:
Simple app showing distance to random iBeacon which is measured by Apple beacon technology using Bluetooth.
Today I learned about:
- Core Location
- CLBeaconRegion
- What is iBeacon
- Asking the user for permission about location — All the time (even when the app is not running ) or when the app is active.
- Using location when the app isn’t running is of course highly sensitive information, so Apple flags it up in four ways:
- If you request Always access, users will still get the chance to choose When In Use.
- If they choose Always, iOS will automatically ask them again after a few days to confirm they still want to grant Always access.
- When your app is using location data in the background the iOS UI will update to reflect that — users will know it’s happening.
- Users can, at any point, go into the settings app and change from Always down to When In Use.
MILESTONE PROJECT 7 (projects 19–21)
Day 73, 23rd of May
PROJECT 21 — technique project — local notifications
Description:
Another technique project, this time focused on notifications. There are two types of notifications local and push. They are not the same. Local notification can be scheduled only in the app but the push notifications require a dedicated server (or service, if you outsource) to send from.
I learned about:
- You can’t post messages to the user’s lock screen unless you have their permission so in order to send local notifications in our app, we first need to request permission
- How to register and schedule a local notification
- Request permission: In the requestPermision() of UNUserNotificationCenter we have to specify what kind of notification we want to request for, for example options: [.alert, .badge, .sound]
- Schedule Notification: in order to schedule local notification we need to configure 3 things: content (what to show), a trigger (when to show it), and a request (the combination of content and trigger.)
- Notification trigger, when to show the notification — can be a calendar trigger that shows the notification at an exact time, it can be an interval trigger that shows the notification after a certain time interval has lapsed, or it can be a geofence that shows the notification based on the user’s location.
- Content of the notification: UNMutableNotificationContent has lots of properties that customize the way the alert looks and works
- To attach custom data to the notification, e.g. an internal ID, use the
userInfo
dictionary property (in the content) - You can also attach custom actions by specifying the
categoryIdentifier
property (also in the content of the notification) - new data type called
DateComponents
Challenge:
- Update the code in
didReceive
so that it shows different instances ofUIAlertController
depending on which action identifier was passed in. - For a harder challenge, add a second
UNNotificationAction
to thealarm
category of project 21. Give it the title “Remind me later”, and make it callscheduleLocal()
so that the same alert is shown in 24 hours. (For the purpose of these challenges, a time interval notification with 86400 seconds is good enough – that’s roughly how many seconds there are in a day, excluding summer time changes and leap seconds.) - And for an even harder challenge, update project 2 so that it reminds players to come back and play every day. This means scheduling a week of notifications ahead of time, each of which launch the app. When the app is finally launched, make sure you call
removeAllPendingNotificationRequests()
to clear any un-shown alerts, then make new alerts for future days.
PROJECT 20 — Fireworks game
Days 70–72, 18th of May
Description:
Another SpriteKit project. This time a little firework game where the goal is to tap rockets of the same colour and make them explode by shaking of the tablet.
I learned about:
- UIBezierPath
- New SKAction follow(), which takes in CGPath as a parameter and makes the node move along that path.
- new syntax for case let — in the case of this project it is used to loop over an array of SKNode but because we need to execute some code only when the node is SKSpriteNode. We create a new constant with let and typecast it to SKSpiriteNode
Challenge:
- For an easy challenge try adding a score label that updates as the player’s score changes. ✅
- Make the game end after a certain number of launches. You will need to use the
invalidate()
method ofTimer
to stop it from repeating. ✅ - Use the
waitForDuration
andremoveFromParent
actions in a sequence to make sure explosion particle emitters are removed from the game scene when they are finished.
PROJECT 19 — Safari extension — JavaScript Injection
Days 67–69, 17th of May
Description:
The goal of this project is not an application or game as before but rather a Safari extension. This extension allows running JavaScript code that we provide to the text TextView. So for example we can enter and display an alert with the title of the page that we previously fetched from the Safari itself. Also, we have fixed a keyboard issue, where text inputted into TextView was hiding under the keyboard if it was too long. It was fixed with Pauls own method — observing values from NotificationCenter. In the observer, we react to any change by adjusting the contentInset
and scrollIndicatorInsets
of our text view.
I learned about:
- When our Swift extension finishes we can send values back to JavaScript. Anything we send back is then made available to our action file.
- The
addObserver()
method ofNotificationCenter
lets us watch for a particular notification. This lets us attach some code to run when a notification comes in. - Scroll indicator insets control how big the scroll bars are relative to their view.
- You must ship an app if you want to ship an extension. Extensions are shipped inside the parent app.
- The
contentInset
property of aUITextView
determines how text is placed inside the view. - We usually rely on the capture list from the outer closure.
Challenge
- Add a bar button item that lets users select from a handful of prewritten example scripts, shown using a
UIAlertController
– at the very least your list should include the example we used in this project. ✅ - You’re already receiving the URL of the site the user is on, so use
UserDefaults
to save the user's JavaScript for each site. You should convert the URL to aURL
object in order to use itshost
property. - For something bigger, let users name their scripts, then select one to load using a
UITableView
.
PROJECT 18 — technique project — debugging
Days 65–67, 11th of May
Description:
- Another technique project. Project with no real app as an outcome Only allows to practices some technique in the playground.
- This time — debugging
I learned about:
- different approaches to debugging
- print() — the lamest approach to debugging. Used with Swift’s string interpolation to see the contents of your variables when your app is running.
- assert() — lets us ensure the app’s state is exactly what you thought it was, for example, assert(array.isEmpty)
- breakpoints — allows us to stop the program on the line, where the breakpoint is placed when the program execution comes to that line. It then allows to see the current values of all variables.
- conditional breakpoints — create a condition for when breakpoint should be applied, for example, every 10th iteration of the loop
- exceptions breakpoints — can be automatically triggered when an exception is thrown
- backtrace —way how to track functions and from where they were called. So if a bug is found somewhere in the method
d()
, this back trace will show you thatd()
was called byc()
, which was called byb()
, which in turn was called bya()
– it effectively shows you the events leading up to the problem, which is invaluable when trying to spot bugs. - view debugging — Capture View Hierarchy, great function of xCode. This debug mode is perfect for times when you know you’ve placed your view but for some reason can’t see it.
Challenges:
- Temporarily try adding an exception breakpoint to project 1, then changing the call to
instantiateViewController()
so that it uses the storyboard identifier “Bad” – this will fail, but your exception breakpoint should catch it. ✅ - In project 1, add a call to
assert()
in theviewDidLoad()
method of DetailViewController.swift, checking thatselectedImage
always has a value. ✅ - Go back to project 5, and try adding a conditional breakpoint to the start of the
submit()
method that pauses only if the user submits a word with six or more letters. ✅
PROJECT 17 — Space Race
Days 64–65, 10th of May
Description:
Another mini-game. This time small rocket flying thru space and trying to avoid collision with randomly generated objects.
I learned about:
- How to use
Timer
to trigger a repeating method every few seconds - Postpone the initial state of the particles animation so it looks good right from the start (used for moving stars) with
advanceSimulationTime()
linearDamping
andangularDamping
properties ofSKPhysicsBody
to force sprites to retain their speed and spin, rather than slowing down over time (enemy objects)
Challenges:
- Stop the player from cheating by lifting their finger and tapping elsewhere — try implementing
touchesEnded()
to make it work. - Make the timer start at one second, but then after 20 enemies have been made subtract 0.1 seconds from it so it’s triggered every 0.9 seconds. After making 20 more, subtract another 0.1, and so on. Note: you should call
invalidate()
ongameTimer
before giving it a new value, otherwise you end up with multiple timers. - Stop creating space debris after the player has died.
PROJECT 16 — MapKit
Days 60–63, 7th of May
Description:
Simple one screen app displaying a map with pins representing “interesting” places. Every pin has its name and link to Wikipedia which is displayed as webView inside of the app on the next screen.
I learned about:
MKMapView
MKAnnotation
MKPinAnnotationView
CLLocationCoordinate2D
- Different
MapView.mapType
, for example,.satellite
Challenges:
- Try typecasting the return value from
dequeueReusableAnnotationView()
so that it's anMKPinAnnotationView
. Once that’s done, change thepinTintColor
property to your favouriteUIColor
. ✅ - Add a
UIAlertController
that lets users specify how they want to view the map. There's amapType
property that draws the maps in different ways. For example,.satellite
gives a satellite view of the terrain. ✅ - 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. ✅
MILESTONE PROJECT 6 (projects 13–15)
Day 59, 6th of May
Challenge:
Your challenge is to make an app that contains facts about countries: show a list of country names in a table view, then when one is tapped bring in a new screen that contains its capital city, size, population, currency, and any other facts that interest you.
My approach:
- getting data from open API https://restcountries.eu/
- created one central class APIManager which is calling this API with customized calls
- fetching all countries and displaying them in the initial tableView
- then I fetch single country data based on what cell was tapped and display info on the new screen
- so far not able to fetch flag picture
PROJECT 15 — technique project — Animations
Days 57–58, 4nd of May
Description:
- Another technique project.
- Project with no real app as an outcome
- Only allows to practices some technique in the playground.
- This time — Animations.
I learned about:
UIView.Animate()
- How to use Alpha to make object invisible
- How to move, rotate, and scale views using
CGAffineTransform
. - Scale — CGAffineTransform(scaleX: 2, y: 2)
- Move — CGAffineTransform(translationX: -256, y: -256)
- Rotate — CGAffineTransform(rotationAngle: CGFloat.pi)
- Make invisible — self.imageView.alpha = 0
- Return to original appearence —self.imageView.transform = .identity
Challenges
- Go back to project 8 and make the letter group buttons fade out when they are tapped. We were using the
isHidden
property, but you'll need to switch toalpha
becauseisHidden
is either true or false, it has no animatable values between. ✅ - Go back to project 13 and make the image view fade in when a new picture is chosen. To make this work, set the
alpha
to 0 first. ✅ - Go back to project 2 and make the flags scale down with a little bounce when pressed. ❌
PROJECT 14 — Whack-A-Pinguine
Days 54–56, 2nd of May
https://github.com/lukassmetana/project14
Description:
- Simple Whack-a-mole type game. Instead of moles, there are good and bad pinguins.
I learned about:
- SKTexture — Changing sprite images without moving the sprite, using
SKTexture
- SKCRopNode — Cropping a sprite so that only part of it is visible, using
SKCropNode
- More
SKActions
, includingmoveBy(x:y:)
,wait(forDuration:)
,sequence()
, and even how to run custom closures usingrun(block:)
- The
asyncAfter()
method of GCD, which causes code to be run after a delay — used for delaying start of the round
Challanges:
- Record your own voice saying “Game over!” and have it play when the game ends. ✅
- When showing “Game Over” add an
SKLabelNode
showing their final score. ✅ - Use
SKEmitterNode
to create a smoke-like effect when penguins are hit, and a separate mud-like effect when they go into or come out of a hole. ✅ (only effect when they are hit)
PROJECT 13 — PhotoFilters
Days 51–53, 29th of April
https://github.com/lukassmetana/project13
Description:
- App that allows you to apply a filter on pictures from your photo library and save them
I learned about:
- UISlider — How to let the user select from a range of values using
UISlider
- Using Core Image (CIContext and CIFilter) — Create Core Image contexts using
CIContext
, and creating then applying Core Image filters usingCIFilter
. - UIImageWriteToSavedPhotosAlbum() — Saving images back to the user’s photo library by calling the
UIImageWriteToSavedPhotosAlbum()
function - More practice using
UIImagePickerController
, to select pictures from the user’s photo library.
Challenges:
- Try making the Save button show an error if there was no image in the image view. ✅
- Make the Change Filter button change its title to show the name of the currently selected filter. ✅
- Experiment with having more than one slider, to control each of the input keys you care about. For example, you might have one for radius and one for intensity. ❌
MILESTONE PROJECT 5 (projects 10–12)
Day 50
Challenge:
- Your challenge is to put two different projects into one: I’d like you to let users take photos of things that interest them, add captions to them, then show those photos in a table view. Tapping the caption should show the picture in a new view controller
PROJECT 12 — technique project — UserDefaults
Days 48–49
PROJECT 11 — Pachinko
Days 45–47, 21st of April
https://github.com/lukassmetana/project11
Description:
- First game-project using SpriteKit — Apple’s high-performance 2D games framework.
- I would not even call it a game because there is no clear goal. User can just drop balls and if they end up in the green slot score increases and if they end up in the red one, score decreases.
- Also, it's possible to add obstacles. When the ball hits an obstacle they are both “destroyed” and disappear.
I learned about:
- A lot of stuff from SpriteKite 😀.
- The
SKSpriteNode
class is responsible for loading and drawing images on the screen. - Draw sprites using a selection of blend modes. We used
.replace
for drawing the background image, which causes SpriteKit to ignore transparency. This is faster, and perfect for our solid background image. - Add physics to sprite nodes using
SKPhysicsBody
, which hasrectangleOf
andcircleWithRadius
initializers that create different shapes of physics bodies. - Adding actions to things, such as spinning around or removing from the game, is done using
SKAction
. - Measure angles in radians using
CGFloat.
- Detecting user interaction with the screen (game) with touchesBegan(_:with:)
Project 10 — Names to Faces
Days 42–44, 17th April
https://github.com/lukassmetana/project10
I learned about:
- UICollectionView
- Designed a custom
UICollectionViewCell
, first in the storyboard and then in code. No like with UITableViewCell, CollectionViewCell always must be customized. - UUID — easy way how to create unique identifiers, which is the easiest way to generate filenames that are guaranteed to be unique
- Saving Data to disk — converting each
UIImage
to aData
that could be written to disk, usingjpegData()
appendingPathComponent()
method, as well as Paul Hudson'sgetDocumentsDirectory()
helper method. Combined, these two let create filenames that are saved to the user’s documents directory.
The thing I should have probably already known but realized just now:
- UiCollectionView
Review quiz score: 11/12
Challenges:
- ✅
- ✅
MILESTONE PROJECT 4 (projects 7–9)
Day 41
Challenge:
- The challenge is this: make a hangman game using UIKit.
PROJECT 9 — technique project — Grand Centra Dispatch
Days 39–40, 11th of April
https://github.com/lukassmetana/project9
Review quiz score: 11/12
Challenges:
PROJECT 8 — Swifty Words
Days 36–38, 8th — 10th of April
https://github.com/lukassmetana/project8
I learned about:
- Building UI programmatically
- Content hugging and content compression resistance priority
- Property observer: didSet
- Working with strings: contentsOf, components(separatedBy: ), enumerated(), replacingOccurrences()
- Add action to UIButton with addTarget()
- Difference between shuffle() and shuffled() array
The thing I should have probably already known but realized just now:
- UIView is a parent class of all UIKit’s types like UIButton, UILabel, etc.
The thing I should probably remember: nil
Review quiz score: 11/12
Challenges:
- ✅
- ✅
- ✅
PROJECT 7 — Petitions
Days 33–35
https://github.com/lukassmetana/project7
I learned about:
- UITabBarController
- Getting data from the internet with Codable protocol
- Data data type
- Create custom HTML inside of WebView
The thing I should have probably already known but realized just now: nil
The thing I should probably remember: nil
Review quiz score: 11/12
Challenges:
- ✅
- ✅
- ✅
MILESTONE PROJECT 3 (projects 4–6)
Day 32
Challenge:
- This time your job is to create an app that lets people create a shopping list by adding items to a table view.
PROJECT 6 — technique project — Auto Layout
Days 30–31
PROJECT 5 — World Scramble
Days 27 — 29
I learned about:
- weak, strong, unowned references
PROJECT 4 — Easy browser
Days 24–26
I learned about:
WKWebView
- UIAlertController action sheets
- UIToolbar, toolBarItems, rightBarButtonItem
- UIProgressView
MILESTONE PROJECT 2 (projects 1–3)
Day 23
Challenge:
Your challenge is to create an app that lists various world flags in a table view. When one of them is tapped, slide in a detail view controller that contains an image view, showing the same flag full size. On the detail view controller, add an action button that lets the user share the flag picture and country name using UIActivityViewController
.
PROJECT 3 — technique project — UIActivityViewController
Day 22
I learned about:
UIBarButtonItem
UIActivityViewController
PROJECT 2 — Guess the flag
Days 19–21
I learned about:
- UIButton
- Assets — iOS assets come in three sizes — 1x , 2x , 3x, if you’re supporting only iOS 10 or later devices you only need to include the @2x and @3x images
- CALayer (CA = Core Animation)— every iOS view is backed by CALayer, which is a Core Animation data type responsible for managing the way views looks. Conceptually,
CALayer
sits beneath allUIView
s (that's the parent ofUIButton
,UITableView
, and so on), so it's like an exposed underbelly giving lots of options for modifying the appearance of views, as long as you don't mind dealing with a little more complexity. Example of CALayer property for UIButton isborderWidth
. - CGColor is is type by which we can set colour to borderColor of our layer. (CG = CoreGraphics)
- UIAlertController
Challenges:
- Try showing the player’s score in the navigation bar, alongside the flag to guess.
- Keep track of how many questions have been asked, and show one final alert controller after they have answered 10. This should show their final score.
- When someone chooses the wrong flag, tell them their mistake in your alert message — something like “Wrong! That’s the flag of France,” for example.
PROJECT 1 — Storm Viewer
Days 15–18
https://github.com/lukassmetana/project1
Description:
- Very simple TableView app displaying pre-loaded pictures (part of the repository), counting the number of views of every picture.
- Added as part of a challenge from different weak: the number of views is saved in UserDefaults.
I learned about:
- UITableView
- UIImageView
- FileManager
- Outlets
- StoryBoard
- AutoLayout
- UIImage
- instantiateViewController from Storyboard
- pushViewController with navigationController
—