My 100 Days of Swift

Lukas Smetana
17 min readApr 10, 2021

--

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:

  1. Extend UIView so that it has a bounceOut(duration:) method that uses animation to scale its size down to 0.0001 over a specified number of seconds. ✅
  2. Extend Int with a times() method that runs a closure as many times as the number is high. For example, 5.times { print("Hello!") } will print “Hello” five times. ✅
  3. Extend Array so that it has a mutating remove(item:) method. If the item exists more than once, it should remove only the first instance it finds. Tip: you will need to add the Comparable 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:

  1. Create a String extension that adds a withPrefix() 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”. ✅
  2. Create a String extension that adds an isNumeric property that returns true if the string holds any sort of number. Tip: creating a Double from a String is a failable initializer. ✅
  3. Create a String extension that adds a lines 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:
  1. If you request Always access, users will still get the chance to choose When In Use.
  2. If they choose Always, iOS will automatically ask them again after a few days to confirm they still want to grant Always access.
  3. When your app is using location data in the background the iOS UI will update to reflect that — users will know it’s happening.
  4. 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:

  1. Update the code in didReceive so that it shows different instances of UIAlertController depending on which action identifier was passed in.
  2. For a harder challenge, add a second UNNotificationAction to the alarm category of project 21. Give it the title “Remind me later”, and make it call scheduleLocal() 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.)
  3. 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:

  1. For an easy challenge try adding a score label that updates as the player’s score changes. ✅
  2. Make the game end after a certain number of launches. You will need to use the invalidate() method of Timer to stop it from repeating. ✅
  3. Use the waitForDuration and removeFromParent 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 of NotificationCenter 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 a UITextView determines how text is placed inside the view.
  • We usually rely on the capture list from the outer closure.

Challenge

  1. 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. ✅
  2. 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 a URL object in order to use its host property.
  3. 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 that d() was called by c(), which was called by b(), which in turn was called by a() – 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:

  1. 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. ✅
  2. In project 1, add a call to assert() in the viewDidLoad() method of DetailViewController.swift, checking that selectedImage always has a value. ✅
  3. 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 and angularDamping properties of SKPhysicsBody to force sprites to retain their speed and spin, rather than slowing down over time (enemy objects)

Challenges:

  1. Stop the player from cheating by lifting their finger and tapping elsewhere — try implementing touchesEnded() to make it work.
  2. 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() on gameTimer before giving it a new value, otherwise you end up with multiple timers.
  3. 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:

  1. Try typecasting the return value from dequeueReusableAnnotationView() so that it's an MKPinAnnotationView. Once that’s done, change the pinTintColor property to your favourite UIColor. ✅
  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. ✅
  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. ✅

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

  1. 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 to alpha because isHidden is either true or false, it has no animatable values between. ✅
  2. 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. ✅
  3. 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, including moveBy(x:y:), wait(forDuration:), sequence(), and even how to run custom closures using run(block:)
  • The asyncAfter() method of GCD, which causes code to be run after a delay — used for delaying start of the round

Challanges:

  1. Record your own voice saying “Game over!” and have it play when the game ends. ✅
  2. When showing “Game Over” add an SKLabelNode showing their final score. ✅
  3. 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 using CIFilter.
  • 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:

  1. Try making the Save button show an error if there was no image in the image view. ✅
  2. Make the Change Filter button change its title to show the name of the currently selected filter. ✅
  3. 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 has rectangleOf and circleWithRadius 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 a Data that could be written to disk, using jpegData()
  • 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 all UIViews (that's the parent of UIButton, 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:

  1. Try showing the player’s score in the navigation bar, alongside the flag to guess.
  2. 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.
  3. 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

--

--

Lukas Smetana
Lukas Smetana

No responses yet