By Developers, For Developers

Historical errata for iOS 10 SDK Development

PDF PgPaper PgTypeDescriptionFixed onComments
46SUGGEST

Text describes:
…“That’s because Swift defines an enumerate() function” or …“Now we’ll use enumerate() to count”
But the function is called enumerated() really.
Its just cosmetics

2016-11-20
53OK

Optionals are enumerations:
let optionalString : String? //throws an error in switch statement
// let optionalString : String? = nil // this works
switch optionalString { //throws an error if: let optionalString : String?
case .none:
NSLog (“nil!”)
case .some(let value):
NSLog (“some! \\(value)”) }

2016-11-20What you're seeing is the fact that variables must be initialized before they are read. It's fine to set it to nil, but not fine to not set it at all. \n \nProperties in a class are automatically set to nil, but local variables aren't set automatically, so that's why your first case produces an error when the switch reads it. \n \nWe'll try to figure out a way to work this detail into the optionals section; it's a good thing to know.
6ERROR

After entering Line 2 in the example the app generates the following error:

2016-11-12 12:49:47.255 WebRadioPlayground[19019:6016376] Failed to obtain sandbox extension for path=/var/folders/70/5f13k9md6qxgg5qlp2vrb2_r0000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.WebRadioPlayground-FD82A7BC-4B4F-48BA-994B-340E8E594D03/Library/Caches/com.apple.dt.playground.stub.iOS_Simulator.WebRadioPlayground-FD82A7BC-4B4F-48BA-994B-340E8E594D03. Errno:1

2016-11-20It's harmless, but we'll add a note saying it can be ignored. Thanks.
16ERROR

When searching for URL in the Documentation and API Reference window, the [S] URL entry may not be at the top. It was farther down in the list.

2016-11-20
18TYPO

The 3rd paragraph on the page (the first paragraph in The Swift Programming Language section) needs to be updated to reflect that this book covers Swift 3 in XCode 8, not Swift 2 in XCode 7.

2016-11-20
14TYPO

The inferred type of `bar` is `Int.Type`, not `Int.type`.

2016-11-20
148ERROR

currentEpisode.enclosureURL = url

should be currentEpisode.enclosureURL = url as NSURL? ?

2016-11-21The use of NSURL was a mistake. It'll be fixed in the next edition. No need for the typecast.
58ERROR

The text mentions that `PragmaticPodcasts.app` is “red in the figure”, but the figure shows it in black.

2016-11-20
72ERROR

The Play button should be simply clicked, not Control-clicked, before Control-dragging a line to the source pane.

2016-11-20
81ERROR

When I created the outlet, the Storage field was pre-populated with “Weak”, not with “Strong”.

2016-11-20
164ERROR

Section header did not stick on table view scroll as advertised.

2016-11-21Sample code is working for me. Can you bring this up on the forum so we can trade screenshots or something? Maybe there's a layout problem and your headers are disappearing under the navigation bar.
167TYPO

Capitalize label “Title”?

2016-11-21
165ERROR

I can’t get the assistant editor to select the EpisodeCell file.

2016-11-21Sometimes Xcode is stupid and the "automatic" file chooser on the right pane doesn't work. At that point, your only option is to switch it to "manual" mode and choose the file yourself. I'll add a note about this, because it happens to me too. \n
27TYPO

The sample code is set.insert(“iPhone 7”) but the text 2 paragraphs later says “On line 2 we add the string ”iPhone 6s“…” The text in the paragraph need to be changed to “iPhone 7”.

2016-11-20
35TYPO

size6 should be size7

2016-11-20
99SUGGEST

Instead of writing a “guard let playerVC = …” statement at the beginning of each test, would it not have been better to write it in the setUp() method?

2016-11-21Not really, because we want each test to have access to the unwrapped playerVC, but since it's created after init(), that property has to be an optional of some sort. We could make it an implicitly unwrapped optional (ie, of type "AVPlayer!") and just assume that setUp() always succeeds, and then we wouldn't need the guard let, but it if setUp() failed, we'd crash when we used playerVC. Same goes for just ignoring the guard let and calling it as "playerVC!". Granted, there's nothing in setUp() that would currently fail to set the variable -- UIStoryboard.instantiateViewController(withIdentifier:) will throw an exception if it fails, so you'd never actually complete setUp(). But I think this approach is safer and clearer about its expectations.
99SUGGEST

Just for fun I tried to write the test without adding the “import CoreMedia” statement. You might want to warn your readers about the linker errors they’re likely to encounter…

2016-11-21Seems kind of like a distraction? We explain why you need to do "import CoreMedia" in the text, so if readers choose to ignore that, I don't think they can be too surprised when things blow up.
105SUGGEST

Up to this point in the book, the unit test implies reaching out on the internet, downloading an mp3 and beginning to play it.

A unit test should ideally be something run in isolation with as little dependency on the outside world as possible. Is this something that you are going to discuss later on in the book, or something you might consider discussing in an upcoming edition?

2016-11-21Wow, that's a really good point. We'll add an aside in the next edition about how this could be done better later in the book, once ViewController isn't dowloading its own MP3 every time.
108SUGGEST

I couldn’t find where the “target’s General tab” is.

2017-01-03Once you select the target (not the project), it's the leftmost tab, as seen in the figure. It goes "General", "Resource Tags", "Info", etc. Blame Jony Ive for tabs that don't look like tabs anymore. Maybe it wasn't clear you have to select the project file to see this UI. We'll try to make that more clear.
108SUGGEST

When I tried to build for my iPhone running iOS 10.1.1 I got an error message saying that this version was not compatible with my version of Xcode (8.0). Strangely enough, the App Store didn’t list any updates for Xcode, although if I searched for it directly I found a version 8.1

You might want to warn the reader that he might have to download a more recent version of Xcode, either directly from the App Store or from Apple’s developer website.

2016-11-21
139TYPO

The same code snippet is repeated - after ‘declaring three variable properties’ and after ‘let’s rewrite the didStartDocument() delegate method to do that:’.
I think it is the correct code snippet for the second instance, while the intended code for the first instance is missing.

2016-11-23
167ERROR

cell.durationLabel.text = episode.iTunesDuration

No such animal and nothing in code completion

2017-01-03Sorry about that. Sloppy code/text mismatch in beta 2; fixed in beta 3.
170ERROR

if let url = episode.iTunesImageURL

This line fails, no such animal

2017-01-03Sorry about that; sloppy code/text correspondence in beta 2. Fixed in beta 3.
165ERROR

cell.durationLabel.text = episode.iTunesDuration

It looks like you still have not populated this property in the xml parser. It’s blank in my episode list.

2017-01-03Our bad; we were treating it as if the duration string was the element's contents, when it's actually an attribute. Fixed for beta 3.
146ERROR

Feed `itunes:image` and Episode `itunes:image` are tags with the url in the attributeDict[“href”] not as foundCharacters in currentElementText. I noticed this from the feed here: cocoaconf.libsyn.com/rss. I moved the populating of itunesImageURL into parser(didStartElement) for PodcastFeedParser and PodcastEpisodeParser.

2017-01-02Thanks. We've fixed up the image handling stuff for beta 3.
160ERROR

Populating the feeds array in ApplicationDidBecomeActive via `episodeListVC?.feeds.append(feed)` duplicates the feed everytime the app is restored from background. Suggest changing to `episodeListVC?.feeds = [feed]` for now since there is only 1 feed.

2017-01-03Great idea, thanks!
145ERROR

I apologize if I’m mistaken here, but I think when parsing the Item XML, you’ve missed having the user parse out duration and image URL. We parse an imageURL in the PodcastFeedParser, but not in the individual PodcastEpisodeParser.

So on page 145, in the didStartElement event, we parse “title” and “enclosure”. We should probably append “itunes:duration” to the line:
case “item”, “itunes:duration” :
currentElementText = “”

and later on in didEndElement….
case “itunes:duration” :
currentEpisode.iTunesDuration = currentElementText

As for the image URL for the individual Episodes, I think we have to parse out the href attribute when we encounter itunes:image in the didStartElement event.

With those changes, my app works as expected. I hope this helps. If I’ve misread somewhere, I apologize. It’s late and I can’t pull myself away from this - great book so far!

2017-01-02Thanks for the fix -- we found we had a three-way mismatch between the earlier example code, the later code, and the book text. We've fixed this for beta 3, with improvements to the image-parsing code such that we should usually have images available for all feeds and episodes.
27TYPO

Current sentence reads “We could tell Swift to use a floating-point type by using 0.0 as the initial value; try that and you’ll see the inferred type becomes Double.type”. Xcode 8.1 on my system shows Double.Type (capital ‘T’).

2017-01-02
73ERROR

Screenshot and text list “AnyObject”, as in

“@IBAction func handlePlayPauseTapped(_ sender: AnyObject) { }”

In my version of Xcode (8.2), this is just “Any”:

@IBAction func handlePlayPauseTapped(_ sender: Any) { }

2017-01-02
123TYPO

…main selling poing of a weak variable…

should be

…main selling point of a weak variable…

2017-01-02
197TYPO

The text:

…in the source editor, or be selecting it in…

should be:

…in the source editor, or by selecting it in…

2017-01-03
197TYPO

In the section “The Quick Look and Print Description Buttons”, the text:

…of that pane provides some very handy…

should be:

…of that pane provide some very handy…

2017-01-03
131SUGGEST

It may be obvious, but when creating the PodcastFeedParser class, the book doesn’t actually instruct the user to create the class definition. Being new to Xcode and Swift, I didn’t realize why the code wasn’t compiling until I looked at the source file on pragprog.com. Adding the code for the class containing the init would be helpful.

2017-01-03Of course. Good catch. I wonder if I assumed we used the "Cocoa Touch Class" template (which gives you the declaration), versus the "Swift File" template, which is pretty much empty. Since it's the latter, we need to write the class declaration ourselves. Fixed for beta 3.
97TYPO

Paragraph 4, last sentence, looks like editing notes:

“automatically fades out and is bigger than I wanted for this screenshot, so I’ve adapted the text above to say it pops up and then disappears”

2017-01-02
194TYPO

Current text: “Open PodcastEpisodeParser.swift and change both instances of ”title" to “name” (they’re in parser(didStartElement:qualifiedName:attributes:) and parser(foundCharacters:))."

The second “title” is actually in parser(didEndElement). I have verified in the source downloaded from the site.

2017-01-17
236TYPO

>>“Rather than showing test files, this shows the tests themselves, and (if they’ve been run alerady) whether they passed or failed the last time they ran”<<<

“Already” mis-spelled as “alerady”.

2017-01-17
257ERROR

​func​ testPlayerCurrentTime_WhenPlaying_IsNonZero()
{
​ \t ​guard​ ​let​ playerVC = playerVC, ​let​ player = playerVC.player ​else​ {
​ \t ​XCTFail​(​“Couldn’t set up test”​)
​ \t ​return​
​ \t }
​ \t playerVC.handlePlayPauseTapped(​self​)
​ \t ​XCTAssertNotEqual​(0, player.currentTime().seconds)
​ }

In the “guard let” expression, “let player = playerVC.player” is unused. Not in the source code but in the text.

2017-01-17
236TYPO

“When we refer to properties or methods from inside the closure, we explicitly have to use self, as we do here, to acknowledge that we we know we’re capturing self. ”

Extraneous “we” before “know”.

2017-01-17
15ERROR

In the “Counting with Numeric Types” section:
“However, %, the popular modulo operator is not available.”

The % operator works fine (although here it’s the ‘remainder’ operator, not modulo) - it just doesn’t work with Floats and Doubles, which recommend using truncatingRemainder. But % works fine with Ints, where this makes it sound like it doesn’t exist in Swift.

2017-01-17
11SUGGEST

First page of chapter 2:
“Compiled, meaning that our source code is converted into bytecode at build time”

I may sound over-picky, but “bytecode” isn’t a great word here - this wording would suggest to a lot of programmers (say, folks coming from Java or C#) that Swift is compiled into an intermediate language that needs a JVM-style runtime engine to work.
I get there’s an LLVM bitcode representation, and the SIL but that’s not the same thing - the end result of compiling Swift is machine code, not bytecode.

2017-01-17
103TYPO

In the test “testPlayerCurrentTime_WhenPlaying_IsNonZeo” there is a typo. After the guard statement, the XCTAssertNotEqual lists an argument of “player.currentTime().seconds”. I believe this should be playerVC.

2017-03-09
103SUGGEST

#81176 — I was wrong!

2017-03-09
48TYPO

In the sample source code you have:

‘if let myURL = URL (string: "foo")’

but then on page 49 you have text that says:

“Now let’s get ourselves into error handling. We’ll do that by mangling the URL string. A simple way to do this is to change the URL scheme from http to something nonsense like foo.”

It seems to me, you’d want a valid URL in the sample code on page 48 (of the PDF) which you would then change when following along on page 49.

2017-04-26Yep, we mistakenly checked in the deliberately-broken version of the code, when the text clearly expects the reader to start from a working URL string and then deliberately break it. Will fix for P2.0, thanks.
79TYPO

The line “…and to handle the differing screen sizes of the 3.5-inch models (iPhone 4s), 4-inch models (iPhone 5s and SE), the 4.7-inch iPhone 6s and 7, and 5.5-inch iPhone 7 Plus and 7 Plus.”

should probably be:

“…and to handle the differing screen sizes of the 3.5-inch models (iPhone 4s), 4-inch models (iPhone 5, 5c, 5s and SE), 4.7-inch models (iPhone 6, 6s and 7), and 5.5-inch models (iPhone 6 Plus, 6s Plus and 7 Plus).”

2017-04-26
101TYPO

The image showing the updated interface displaying the title as url.ladPathComponent should probably still have the Play button, as the code had yet to be written to set this using KVO.

2017-04-26
115TYPO

You instruct the reader to delete the testExample and testPerformaceExample methods on page 112 (Creating Tests) and then again on page 115 (Using a Scene in a Test)

2017-04-26
118TYPO

XCTAssertNotEqual(0, player.currentTime().seconds)

should be

XCTAssertNotEqual(0, playerVC.player.currentTime().seconds)

Additionally, this throws an linker error if you try to run the test at this point:

Undefined symbols for architecture x86_64:
“(extension in CoreMedia):__C.CMTime.seconds.getter : Swift.Double”, referenced from:
PragmaticPodcastsTests.PragmaticPodcastsTests.(testPlayerCurrentTime_WhenPlayer_IsNonZero () -> ()).(implicit closure #2) in PragmaticPodcastsTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

2017-04-26Thanks for the corrected code (there's an underlying problem that the code in text there doesn't match the accompanying screenshot, which actually creates a local "player" variable as a second clause of the guard let). We'll fix for P 2.0. \n \nAs for the linker error, adding "import CoreMedia" works for us, as indicated earlier on the page. Did you do that step?
148OK

Within PodcastFeedParser.swift

parser.delegate = episodeParser

This seems redundant as the PodcastEpisodeParser’s init() does this itself.

If that’s not the case, maybe some more explanation is needed.

2017-04-26It's not redundant, because what we're doing is reassigning the XMLParser's delegate between our two parser objects, the feed parser and the episode parser. The feed parser becomes the delegate in its init (p. 145), but when it hits an item tag, it creates an episode parser and reassigns the XMLParser delegate to that (pp. 147-8). Then the episode parser gets all the XML callbacks until it ends the item, at which point it passes the delegate back to the XMLParser to continue on (p. 147). This strategy is explained at the top of p. 145. \n \nIt kind of sucks, honestly, because we would love for the feed and episode structs to be able to parse themselves, but the XMLParser API requires delegates to be full-on NSObjects, so we created the FeedParser and EpisodeParser classes to create PodcastFeed and PodcastEpisode struct instances for us. \n \nFor Swift 4, a new archiving and serialization API has just been approved, and the whole point of it is to work better with structs and enums. If it supports podcast XML, we will of course rewrite this entire chapter for the iOS 11 book to adopt it. More info at: https://github.com/apple/swift-evolution/blob/master/proposals/0166-swift-archival-serialization.md
36OK

NPR.org url noted in the first example doesn’t work: www.npr.org/streams/live1_aac.pls

2017-04-26You appear to have left out part of the URL. The correct URL is: \nhttp://www.npr.org/streams/aac/live1_aac.pls \n(Notice the "aac" path segment after "streams"). \nI just tried this URL and it worked.
209TYPO

In Xcode 8.3.2 the Behavior section is title Starts instead of Start. (First paragraph after the screenshot on this page.

2017-04-26
124ERROR

“we call Dispatch.queue” in the text.
queue: DispatchQueue.global(qos: .default) in the code

127ERROR

“(qos: .default)”
Developers should not use the “default” qos, according to the Apple documentation.

78-81ERROR

Hardware: iMac (Retina 5K, 27-inch, 2019 ) Software Catalina 10.15.2, Xcode 11.0

As proposed network security disabled (info.plist XML file). Running the app and tapping the Play button (Podcast URL) does not work.

Message:
2020-01-04 11:28:28.488639+0100 PragmaticPodcasts[1119:51903] [] nw_endpoint_flow_copy_multipath_subflow_counts Called on non-Multipath connection
2020-01-04 11:28:28.620199+0100 PragmaticPodcasts[1119:51903] [] nw_endpoint_flow_copy_multipath_subflow_counts Called on non-Multipath connection
2020-01-04 11:28:48.738024+0100 PragmaticPodcasts[1119:51903] [] nw_endpoint_flow_copy_multipath_subflow_counts Called on non-Multipath connection
2020-01-04 11:28:48.741510+0100 PragmaticPodcasts[1119:51903] [] nw_connection_receive_internal_block_invoke [C1] Receive reply failed with error “Operation canceled”

Categories: