Errata for Swift Apprentice 4th Edition

Thank you. A lot of the time hashable can now be automatically generated by the compiler. But if you go off and make your own == you better make your own hash method too.

In the topic “When to call super” you write "'Suppose you replace the overriden recordGrade(:slight_smile: method in the StudentAthlete class with the following version that recalculates the failedClasses each time a grade is recorded". So you are replacing the code of recordGrade(:slight_smile: with the implementation beneath that phrase.

Problem doing so is that failedClasses is introduced as a property of StudentAthlete and not of Student. So if you code in its implementation “failedClasses = newFailedClasses” you would crash as failedClasses does not exist. Your code would work properly if the implementation was done as a subclass of StudentAthlete.

Chapter 18. It is not an errata. I realize singletons being used in things as UserDefaults and so on. What escapes me however is why they exist at all. A singleton creates one instance. On this instance all (non-static) methods are called. The instance is created through a static property.

Why not simply render all methods and properties static? Hence not creating the singleton but work via static methods and properties.

In chapter 18 a part of the answer to the challenge looks like this
public struct GameCharacterFactory {
static public func make(ofType type: GameCharacterType) → GameCharacter {
switch type {
case .giant:
return Giant()
case .wizard:
return Wizard()
case .elf:
return Elf()
}
}
}

After reading the chapter on protocols I had expected to find this:
public struct GameCharacterFactory<AGameCharacter: GameCharacter>{
static public func make(ofType type: GameCharacterType) → AGameCharacter {
switch type {
case .giant:
return Giant()
case .wizard:
return Wizard()
case .elf:
return Elf()
}
}
}

Chapter 19. The first final challenge makes no sense unless you add the call. The code as it is would run if you’d make following calls: let numbers = [-2, -1, 0, 1, 2]
numbers[0]
numbers[1]

Thanks for your reply, it’s easy to understand.
However, I confused again.
In Chapter 19 with Keypaths part.
When I want type in playground the following code:
let title = \Tutorial.title
let tutorialTitle = tutorial[keyPath: title]

Playground automatically full the second one with
let tutorialTitle = tutorial[KeyPath: ]

Although use KeyPath: doesn’t work, but it is like the right thing to do.

Can you please explain the difference? use keyPath makes me feel guilty.

Chapter 22
In English you have two or no commas
‘All collections types, like Array and Dictionary are also codable if they contain codable types’

Uittreksel van: By Ray Fix. ‘Swift Apprentice’. Apple Books. "

Chapter 22
‘You’ll notice that you need to use try because encode(_:)’

Yet you stipulated a type needs to implement ‘func encode(to: Encoder) throws’

Where did the to label go?

chapter 23

To be sure that I comprehended this the right way. When you do not add a capture list a reference is stored to the object. So if that object changes the value is also changed within the closure. If however you add a capture list the following happens: the moment you create the closure it takes the value of the object at that moment. This value will be used within the closure. Even if the value of the object changes outside of the closure.

If this is true it does surprise me a memory cycle still appears with a capture list. You would think this value could be stored as a value type and no longer as a reference type?

Chapter 23 Another question on capture lists

I remain confused. I made some modifications to the original code. You can find my adjustments in beneath. I made title a variable. I wondered which value would be stored in the capture list. To my surprise the value of the capture list does change the second time I call for it. I set the changes in fat. Can you explain what is happening?

class Tutorial {

var title: String

unowned let author: Author

weak var editor: Editor?

init (title: String, author: Author) {

self .title = title

self .author = author

}

deinit {

print(“Goodbye Tutorial (title)!”)

}

lazy var createDescription: () -> String = {

[unowned self ] in

return “( self .title) by ( self .author.name)”

}

}

class Editor {

let name: String

var tutorials: [Tutorial] = []

init (name: String) {

self .name = name

}

deinit {

print(“Goodbye Editor (name)!”)

}

}

class Author {

let name: String

var tutorials: [Tutorial] = []

init (name: String) {

self .name = name

}

deinit {

print(“Goodbye Author (name)!”)

}

}

do {

let author = Author(name: “Cosmin”)

let tutorial = Tutorial(title: “Memory management”, author: author)

print(tutorial.createDescription())

let editor = Editor(name: “Ray”)

author.tutorials.append(tutorial)

tutorial.editor = editor

/ The two lines in beneath I added. I find this strange. At this moment the value of createDescription is already set to a closure. This closure has a capture list. So I would have thought that the capture list would have stored a copy of the value of the object upon creation. Consequently I thought the next print would print ‘Memory management by Cosmin’ It prints however ‘Test by Cosmin’. Why?
/*

tutorial.title = “Test”

print(tutorial.createDescription())

editor.tutorials.append(tutorial)

}

Another remark on chapter 23

You state ‘Although there is no reference cycle happening in this case, because you decided you did not want feedback to extend the lifetime of an Editor object, you declared self as unowned’. This seems strange though. The Editor object points strongly to the closure. It is because of the unowned keyword the closure no longer points strong to the object. If you were to omit the unowned (or weak) keyword you would point strongly to the object and have a strong reference cycle?

Another question on chapter 23

‘If self is not nil it will capture a strong reference and make sure it sticks around until the print statement finishes’. You make this remark after using [weak self]. So if self is not nil the guard statement will turn the weak self into a strong one? Furthermore if the closure now references strong to the object? Or is this possible the moment the closure has finished its statements? This would imply a closure is removed from memory the moment its statements are finished. This seems doubtful as the Editor object still references strong to it?

p. 379: "When dealing with objects, remember that “constant” has a different meaning for reference types. With reference types, a capture list will cause the closure to capture and store the current reference stored inside the captured variable. "

It captures another reference to the object. Changes in the object’s properties will still be reflected when the code actually executes.

If you were to omit the unowned (or weak) keyword you would point strongly to the object and have a strong reference cycle?

It wouldn’t be a reference cycle because it would be self referencing self. However if all other references to the Editor were set to nil, a captured strong reference would keep the Editor alive until the closure had executed. So if you don’t want “feedback to extend the lifetime of an Editor object”, you need an unowned or weak capture.

This would imply a closure is removed from memory the moment its statements are finished.

No, it implies that as with all local variables in methods, the variables go out of scope when the statements are finished.

I looked back at the examples. I started out with the counter example. This counter is a value type. If you do not use a capture list does the closure create a reference/pointer to the value type? I get this impression as in the first example the value of counter is changed from 0 to 1 and the print reveals the last value of counter being 1. This seems to imply that the closure just takes the reference the counter variable is pointing to at any time when you do not use a capture list.

Example: counter first has a reference of 253. At this reference the Int instance with value 0 is to be found. The closure is defined (not using a capture list). If we were to execute the closure at this time it would look which instance is present at reference 253. Counter is assigned another value being 1. This Int instance is stored at reference 42. The closure is still looking at the counter variable. This variable references now to reference 42. The closure, not using a capture list, takes the instance at reference 42. This instance has a value of 1.

This would explain why a capture list is handy with value types. The capture list stores the current reference the variable is pointing to (in our example 253) at the moment of definition of the closure. The moment counter is assigned another value (in our example 1) the reference of counter is changed (in our example to 42). The capture list however keeps pointing at the original reference (in our example 253) which hold the initial value of counter (in our example 0). Is this correct?

I realize that it is a value type. I read somewhere this is the way value types are handled though.

This brings me to another question (assuming the reasoning above is correct). When is the closure removed from memory? Because that closure is holding a reference to the old structure instance as we did not use weak or unowned. This instance cannot be removed as long as the closure is still around? The closure being a global variable implies it will be around as long as the app runs.

In the case of a class object a reference is stored so to the class object. This reference would be strong (if nor weak nor unowned is added to it). This strong reference would indeed create a retain cycle. As it is a reference to the object it also explains why changes to the object are reflected within the closure.

But what is the use of that capture list in the case of a class object? When could the reference to the object ever change? If changes are made to the object (for instance properties getting a different value) this would not cause the reference to change? If this is the case I do not see immediately why you need to add a capture list in front? You also could use something like (weak)self or so in the closure instead of adding a capture list then? Unless of course this was done to avoid each time coding (weak)?

I am confused. I agree that unowned avoids the closure pointing strongly to the Editor object. Let’s say we do not use unowned or weak. In that case you say that the Editor object is not pointing strongly to the asynchronous closure of queue. Is this correct? Because if it were to point strongly we would have a retain cycle.

If the Editor object is not pointing strongly to the closure I reckon this is because in the implementation only a asynchronous closure is called upon queue, and not upon self. In contrast to the createDescription variable of self which holds a closure itself?

I also do not entirely grasp what you mean by ‘self referencing self’.

So the asynchronous closure no longer points strongly to self. It did capture the reference of the Editor object self was pointing to at the moment editTutorial(: ) was defined. In the implementation of editTutorial(: ) we check if that Editor instance is not nil. If it is not we create a new strong reference to that initial reference to avoid it being removed from memory. This is done with the guard statement. Doing so we rest assured that the initial Editor instance will be around to call self.feedback(for:).

Assuming this new reference is the only strong reference left to the initial Editor instance. When is this new reference set to nil so that the initial Editor instance can be removed from memory? Is this done the moment all the statements of the asynchronous method of queue are finished?

I’m left wondering though. We first use unowned to make sure the Editor object can be removed from memory. If it is not yet removed from memory when we call the editTutorial(_ :slight_smile: method we make sure it cannot be removed from memory anymore. Why did we bother to render it unowned in the first place? The Editor object wasn’t strongly referenced to it anyway?

The moment the statements in the closure are finished the local variables can be removed by the OS. This means that the new strong pointer to self could be set to nil by the OS. Is this correct? Is this what you meant saying going out of scope?

Thanks for your answer. This chapter isn’t easy to comprehend.

Chapter 25

The solution to Challenge 1 omitted the conformance of Food to Discountable. It should read
struct Food: Taxable, Discountable {}

Hi there,

Chapter 2.

**In the challenge #2, the book says:

“Create a constant called namedCoordinate with a row and column component.”

So there is an easy answer for this -with any value-, but in the playground, the answer is another because the same question is this, Plus: “
of 2 and 3”

**In the challenge #10, the question is:
“What is the numeric difference between Double.pi and Float.pi?”

I got confused, and I dont know if is the wording, or it was just me ( I apologize if I’m wrong)

So, when asking for numeric diference, I guess is Double - Float, but when you use between, (instead of “of”) you are asking a wordy (theoretical) answer, instad of a number. Am I wrong here?

Thanks

Chapter 11: Properties page 199

The tricky is that you can’t change this newValue, and it will still be set, so you’ll have to go beyond adding a willSet observer.

The word tricky doesn’t fit this context, the correct word should be trick

Chapter 8, from page 280:

“Remember, you already declared multiplyClosure as a closure taking two Ints and returning an Int, so you can let Swift infer these types for you.”

I might be wrong, but it seems to me that Swift infers these types from the context (as the return type is Int, parameters should also be Int), not because the closure is already declared. When you write a brand new (not previously declared) closure you can let Swift infer the parameter types from the return type. Am I missing a point here? Maybe I am interpreting the words “already declared” in a wrong way.

Chapter 33, from page 744:

You can find the project files for this chaper under 33 - Custom Table Cells in the Source Code folder.

The word chapter is misspelled.

Did you mean to report this to iOS Apprentice? SA only has 25 chapters. Thanks though!