100 Days of Swift

Final Exam

So … the day has come, I feel ready to try and take the exam!

I am beginning today, Sunday June 23rd at 10.40am.

Questions, answers and comments

We begin with a series of “Which of these statements are true?” … goodness, I’m trembling for the emotion!

  1. The @unknown default case is there to catch cases that get added to an enum after we wrote our code. This stops our app ending up in an unknown state if something changes in the future.
  2. Visual Formatting Language metrics let us share sizes across views more easily. Metrics let us define shared values that many views can use.
  3. We can add a simple shadow to a UIView by using the shadow properties of its layer. While these shadows are easy to create, it’s helpful to also provide a shadow path to avoid performance problems.
  4. We must ask permission to read the user’s location. Location data is highly sensitive, so ask for it only if you need it.
  5. inout parameters must be variables.
  6. JSON is a lightweight way to store and send data. JSON (JavaScript Object Notation) is commonly used across many languages for just this purpose.
  7. Auto Layout constraints must always be complete and non-conflicting. These are Auto Layouts two rules, and you must always obey them if you want your layouts to work.
  8. If we make a class and don’t give all its properties default values, we need to create a custom initialiser. Structs benefit from a default memberwise initialiser. Here I made my first mistake, a bit too early for my expectations, as I confused the MapView with the code needed to use it…
  9. Any part of the mask of an SKCropNode that has color is not cropped.It doesn’t matter what the color is, so make it nice and clear. Second mistake in a row, but the question really was not clear at all and I’m starting to get nervous:

The .replace blend mode replaces all the pixel colours in an SKSpriteNode, but leaves transparency intact. This blend mode ignores transparency, which is what makes it so fast.

There is no mention on transparency on the Documentation… “Enumeration Case SKBlendMode.replace The source color replaces the destination color.” … where the hell is mention on transparency? Ok … I kind of hate SpriteKit but these kind of unclear questions are what drives me nuts (and drove me nuts for all this course)… One thing is not knowing the answer, one thing is being screwed by the question not being laid out clearly…

  1. You can share images, text, and more using activity view controllers. Activity view controllers are capable of handling a variety of data types.
  2. Activity view controllers can send our data using AirDrop. AirDrop is one of several services that connect to activity view controllers.
  3. Using Codable is preferred when you have an app that’s written only in Swift. Codable takes much less work than NSCoding, and is safer too.
  4. The keyboard frame can change many times while our app is running. The user can hide and show the QuickType bar as often as they want.
  5. We can render a UIImage directly to a Core Graphics canvas. They have a draw() method that makes this easy.
  6. Variadic parameters can potentially receive zero values. The array we’re given might be empty.
  7. Scroll indicator insets control how large the scroll bar is relative to its container. These insets let the user see how much content there is in the scroll view, as well as how far through it they are.

The alternative option was quite interesting and worth mentioning here for the sake of knowledge:

To use Touch ID we must provide a user-facing reason string in our property list. For reasons only known to Apple, the Touch ID reason is provided in code, and the Face ID property is provided in the property list.

  1. SKCropNode only crops nodes that are placed inside it. If you want something to be cropped, it must be made a child of a crop node. Every time I see a question on SpriteKit I get a stress shiver in my back… that’s not nice…
  2. SKTexture lets us change the image of an SKSpriteNode without having to delete and recreate it. This makes it helpful for changing how something looks in place – we can just change the property. What did I just say?! The Documentation for this was a bit murky as no mention was given to the deletion and recreation of the SKSpriteNode. Fortunately, the alternative was quite clearly wrong and helped me in the choice.
  3. We can make an SKTexture directly from a UIImage. This allows us to generate textures dynamically. This is done via the init(image:) initialiser.
  4. Lazy properties are a performance optimisation. They are created only when needed, and so might never be created.
  5. Calling sizeToFit() on a view makes it take up the correct amount of space for its content. UIKit will measure the contents of the view, then adjust its size so that all the content is visible.
  6. Nil coalescing lets us provide a default value to use if an optional is nil. As much as I love optionals, I’d much rather have real types to work with, and nil coalescing helps provide just that.

Once more, it is nice to learn from the wrong option:

We need to make custom types conform to NSKeyedUnarchiver if we want to load them from UserDefaults. NSKeyedUnarchiver is a class, not a protocol; it’s used to convert a Data instance into some other sort of data type.

  1. When creating a scaling CGAffineTransform we can provide different X and Y values. This lets us squash our views if needed.
  2. UserDefaults lets us store program settings and user settings in one place. All apps have access to their own UserDefaults.
  3. Multitasking refers to a computer running many pieces of code at the same time. The codes runs in parallel, so any of the tasks can complete at any time.
  4. Enum raw values are underlying values that sit behind each case. These can be strings, integers, or something else.
  5. loadView() is called before viewDidLoad(). loadView() is called first, and it’s where you create your view; viewDidLoad() is called second, and it’s where you configure the view that was loaded.
  6. Core Graphics can render to PDFs or to screens. This is what’s meant by being “device-independent”.
  7. We can create custom subclasses of SKNode. It’s lets us store additional properties and methods.
  8. Pin annotation titles are automatically shown by MapKit. This is the default behaviour of MapKit.
  9. You can add many items to an array by using +=. The += operator adds one array to another, so you can use it to add items quickly.
  10. A lazy property can be an instance of a different struct.
  11. The shuffle() method shuffles an array in place rather than returning a new array. If you want the shuffled array return, use shuffled() instead.
  12. NSValue is an Objective-C wrapper that can hold a CGRect, a CGPoint, or something else. NSValue was needed because Objective-C was not able to store CGRect and other structs in arrays and dictionaries.
  13. Bitmasks can be combined using |. This operator is called “bitwise or” and it combines two numbers together.

The alternative option was quite interesting once more:

All SpriteKit physics bodies must be attached to a node. The node property is optional because the node might have been destroyed after a collision started.

  1. Variadic parameters are converted into arrays inside your function. Third mistake of the day, and this time I was absolutely sure I was going to be correct… but again… questions laid out as traps are just that, nasty traps… my answer was: “You can pass an array in place of a variadic parameter.” To which the explanation was: “You must always pass values individually, separated by commas”. Let’s not express my rage in words, better for the reader …
  2. Using isEmpty on a string is faster than count == 0. isEmpty can return true as soon as it knows at least one item exists, where count == 0 has to count all the letters in a string.
  3. All modern iPhones and iPads support iBeacons. iBeacons were first introduced way back with the iPhone 4S. …fine, my brain is starting to burn when it stretches the memory…
  4. Multiple buttons can call the same method when tapped. You can connect as many actions as you like to a single method.
  5. print() is a variadic function. You can pass in as many values as you want, separated by commas.
  6. NSAttributedString and NSMutableAttributedString both hold strings with formatting. The only difference is that mutable attributed strings can be modified after we create them.

The alternative was most interesting!

Calling the dropFirst() method on a string always removes the first character. FALSE: if the array is empty, dropFirst() does nothing. Also, dropFirst() can be called with a parameter to make it drop several letters.

  1. Multipeer networking can take advantage of Bluetooth and Wi-Fi. We don’t actually care what networking system is used – that’s an implementation detail that iOS takes care of for us.
  2. We can track changes in the value of a UISlider using its valueChanged event. This gets reported back to us every time the slider is moved.
  3. The default GCD background queue has a lower priority than .userInitiated but higher than .utility. It has a higher priority than .utility and lower than .userInitiated. Ouff… finding this in my memory was almost as hard as finding it later in the Documentation…
  4. UIGraphicsImageRenderer automatically adjusts its sizes for the pixel density of the current screen. There are options to change this, but the default works best most of the time.

First hour is over, bathroom break 🙂

Back… let’s move on

  1. To use a UIBezierPath with an SKAction.follow() action we must pass in its cgPath property. SpriteKit is a cross-platform framework, and UIKit types like UIBezierPath aren’t available on macOS. This was the fourth mistake as I rushed it… damn me… of course I could create timers with the repeating option set to false … idiot!
  2. The resignFirstResponder() method stops a selected text control from being active, which in turn makes the keyboard go away. You should call this method when you want the user to stop editing a text field or text view.
  3. The target of an action refers to where that method will be run. The target refers to where the code will be run, and the action refers to what code will be run.
  4. Changing inout parameters inside a function changes them outside too.
  5. You can combine try? with if let. Phew… halfway through… 46/50 by now… not bad but not as good as I hoped it to be. I have only one more mistake for the Distinction pass…
  6. We can create custom classes for our collection view cells. Custom classes let us create outlets for the cells’ subviews.
  7. We can change the delegate of the default UNUserNotificationCenter. This lets us control who gets told when notifications are triggered. This question was just plain scary…
  8. We can use #selector to point to a specific method in a different object. You can use #selector to point to a method in any object, as long as that method is marked @objc.
  9. SpriteKit scenes have a default gravity vector. The default value is Y:-9.8, which matches the gravity on Earth.
  10. Colouring a sprite means setting its color and colorBlendFactor properties. This lets us control the degree of coloration precisely. Please Paul, for my health’s sake… write “colouring a sprite NODE”… not just a sprite… my heart has limited amount of shocks per day available…
  11. Creating a new SKEmitterNode from a filename returns an optional. You can unwrap it safely or unsafely depending on how confident you are.
  12. Interface Builder creates outlets as implicitly unwrapped optionals. This is required because the view won’t exist when the view controller is first created, but it will exist shortly afterwards and then continue to exist for the life of the view controller.
  13. Every map annotation needs a latitude and longitude coordinate. Without this information the annotation wouldn’t make sense – where would it go?
  14. Delegation allows one object to respond on behalf of another. Delegation is what allows us to customise the behaviour of built-in types without having to sub-class them.

The other option was:

App Transport Security means apps are installed safely from the App Store. FALSE: App Transport Security means that we can transfer data over the internet using secure connections only.

  1. We can adjust the stroke color and line width of an SKShapeNode. This lets us draw lines and borders around shapes.

The other option was, quite trickily because of my friend SpriteKit:

When we call removeAllActions() method on a SpriteKit node, it means any actions will be removed once they have completed. FALSE: removeAllActions() removes the actions immediately rather than waiting for them to complete.

  1. Lazy properties can be used inside any kind of structs.
  2. MKPinAnnotationView is a built-in class that draws tappable pins on the map. As its name suggests, this draws a pin on the map.
  3. When the user selects a picture using UIImagePickerController we’ll be sent a dictionary of data. Apple prefers using dictionaries for this purpose because it allows them to expand it to add more things later on if needed.
  4. A SpriteKit physics body with isDynamic set to false will no longer be affected by gravity. Non-dynamic physics bodies take less CPU time to calculate in the physics simulator, and still respond to collisions.

The other one was very mean but … here it is:

All instances of SKSpriteNode have a texture. FALSE: It’s possible to create sprite nodes with just a color, which is why the texture property is optional.

  1. Table view cells with subtitles show two different text labels. The default table view cell has a single label, but the subtitle style has two.
  2. Local notifications can include alerts, sounds, and badges. There are extra settings, but these are the most common.
  3. The p command in LLDB is short for “print”. It’s an easy way to read the value of a particular variable.
  4. Visual Formatting Language can create horizontal or vertical constraints. VFL creates horizontal constraints using H: and vertical constraints using V:.
  5. We can loop over strings like arrays. Both arrays and strings can be treated like sequences, which means we can loop over them.
  6. Background tasks prioritise battery efficiency. Background priority is there for tasks that take a very long time to complete, so the system doesn’t allocate them much CPU resource.
  7. Each multipeer network needs a service type string that identifies it uniquely. Apple recommends you include your company and app name to make sure this string is unique.
  8. A String! does not need to be unwrapped before use. If you access an implicitly unwrapped optional while it contains nil, your code will crash. So yes, it technically doesn’t need to be unwrapped but … it is warmly suggested!
  9. We can control the center of a view using its center property. This is often the easiest way to move a view around the screen.
  10. The safe area layout guide is the space available to our view, excluding rounded corners and notches. All important content should lie inside the safe area, or you risk it being obscured.
  11. Lazy properties are created using the lazy keyword.
  12. Auto Layout lets us position one view relative to another. This makes it a great way to handle different languages, because your layouts will adapt when given longer or shorter text.
  13. UIStoryboard can load storyboards from our bundle and create view controllers from there. Just provide it the storyboard name as its first parameter and it will do the rest.
  14. It’s a good idea to make liberal use of assertions. These can help catch errors in your program state.
  15. We can create an SKSpriteNode from a texture, from an image name, or from a color. All three initialisers are useful. So this was my fifth mistake but, wait, I can also create a sprite node from a file named… which means that this question is wrongly put… ok… I didn’t check the other option before but I was quite sure with this… if because of this I get to the 6th mistake I will complain with Paul because it really should not be put this way… The other option was :

An SKLabelNode always aligns its text to the center. FALSE: It has a horizontalAlignmentMode property that lets us control this.

Sure I could have checked this, but I guessed, this is the default… which it is …

  1. #if targetEnvironment(simulator) is a compiler directive that lets us compile code only for the simulator. Any code inside this directive won’t be compiled for real devices – it’s as if it doesn’t exist.
  2. Drawing a sprite with the blend mode .replace is faster than the default blend mode. The .replace blend more ignores transparency, which makes it faster to draw.
  3. We must request the user’s permission to show notifications. We can only start showing notifications when permission is granted.
  4. SpriteKit texture atlases are more efficient than regular asset catalog images. They allow SpriteKit to load in a single image and share it across many nodes.
  5. CLLocationManager is responsible for telling us when iBeacons are detected. We need to assign an object as its delegate, then wait for callbacks when something happens.
  6. Strong reference cycles can cause view controllers to never be destroyed. If view controllers are kept alive, their contents might be kept alive too – it’s very wasteful.
  7. Storyboard identifiers allow us to create storyboard view controllers in code. These work similarly to table view cell reuse identifiers.

At 12.40pm I took a pause to go for launch and then to visit a couple of exhibitions in my home town. Tomorrow will be the 220th anniversary of the birth of Silvio Pellico (I hope you know who he is) who was born in my town (Saluzzo). Also Bodoni (yeah, the guy who invented the font among other things) was from here!

But now, at 5.30pm, let’s see if I can resume and finish this with a bit of success.

  1. Reading a specific character from a string means starting at the start index and counting forwards until we find the letter we want. This is a slow operation, particularly if you want to read through a very large string.
  2. We can add a delay to animations so they start after a few seconds. This lets you time them as accurately as you need.
  3. The components(separatedBy:) method of strings sends back an array of strings. Some strings might be empty depending on what your source data was.
  4. You can use values higher than 1.0 for red, green, and blue in UIColor. This uses an iOS feature called wide color, which enables extremely deep colours on modern devices.
  5. When using try you must catch all errors that can be thrown.
  6. All user interface code should be run on the main thread. The main thread is the only place it can safely be run.
  7. If you use try! and your call throws an error, your code crashes.
  8. If a function receives a closure parameter and doesn’t use it immediately, it must be marked @escaping. Think about it like this: the closure escapes the method rather than being used inside there then thrown away.
  9. The path property of a URL gives us the location as a string. It’s helpful for APIs that use a string for the filename rather than a URL.
  10. If you try to use an implicitly unwrapped optional when it is nil, your code crashes.
  11. We can add a line break to a string by writing \n. Alternatively we can use multi-line strings.
  12. We can simulate Touch ID and Face ID using the iOS Simulator. You can opt into biometric authentication, and provide both matching and unmatching faces/touches.
  13. Xcode will refuse to build if you haven’t used @objc when it’s needed. When the @objc attribute is required, it really is required.
  14. Multipeer networking can send any kind of Data instance. As long as you can encode it to Data, iOS can send it to other peers.

OH MY GOODNESS!

I DID IT!

95%!

PASSED WITH DISTINCTION!

AAAAAAAAAAAAAAAH!

Can’t wait to resume learning!

I would like to have Paul here for a big hug and to thank him for all this! I have made so much progress thanks to him and, really, if I have to say, what he taught really stayed! I really feel able to take a blank canvas and DO something!

Oh … I am so excited!

So what is your opinion? How should I go on?

Let me know down in the comments!

Thank you to everyone, especially Rob Baldwin, Filip Nemecek and others on the Slack channel! I would have not gotten here if it was not for them!

I love you guys! Hope to see you soon!


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!

Published by Michele Galvagno

Professional Musical Scores Designer and Engraver Graduated Classical Musician (cello) and Teacher Tech Enthusiast and Apprentice iOS / macOS Developer Grafico di Partiture Musicali Professionista Musicista classico diplomato (violoncello) ed insegnante Appassionato di tecnologia ed apprendista Sviluppatore iOS / macOS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: