Swift in Depth
Tjeerd in 't Veen
  • MEAP began September 2017
  • Publication in December 2018 (estimated)
  • ISBN 9781617295188
  • 376 pages (estimated)
  • printed in black & white
Swift is more than just a fun language to build iOS applications with. It features a host of powerful tools that, if you know how to effectively use them, can help create even better apps with clean, crystal-clear code and awesome features. Swift in Depth is designed to help you unlock these tools and quirks and get developing next-gen apps, web services, and more!
Table of Contents detailed table of contents

1 Introducing Swift in depth

1.1 The sweet spot of Swift

1.2 Below the surface

1.3 Swift’s downsides

1.3.1 ABI Stability

1.3.2 Strictness

1.3.3 Protocols are tricky

1.3.4 Concurrency

1.3.5 Venturing away from Apple’s platforms

1.3.6 Compile times

1.4 What you will learn in this book

1.5 How to make the most of this book

1.6 Minimum qualifications

1.7 Swift version

1.8 Summary

2 Modeling data with enums

2.1 Or versus and

2.1.1 Modeling data with a struct

2.1.2 Turning a struct into an enum

2.1.3 Deciding between structs and enums

2.2 Enums for polymorphism

2.2.1 Compile-time polymorphism

2.3 Enums instead of subclassing

2.3.1 Forming a model for a workout app

2.3.2 Creating a superclass

2.3.3 The downsides of subclassing

2.3.4 Refactoring a data model with enums

2.3.5 Deciding on subclassing or enums

2.3.6 Exercises

2.4 Algebraic data types

2.4.1 Sum types

2.4.2 Product types

2.4.3 Distributing a sum over an enum

2.4.4 Exercise

2.5 A safer use of strings

2.5.1 Dangers of raw values

2.5.2 Matching on Strings

2.5.3 Exercises

2.6 Closing thoughts

2.7 Summary

2.8 Answers

3 Writing cleaner properties

3.1 Computed properties

3.1.1 Modelling an exercise

3.1.2 Converting functions to computed properties

3.1.3 Rounding up

3.2 Lazy properties

3.2.1 Creating a learning plan

3.2.2 When computed properties don’t cut it

3.2.3 Using lazy properties

3.2.4 Making a lazy property robust

3.2.5 Mutable properties and lazy properties

3.2.6 Exercises

3.3 Property observers

3.3.1 Trimming whitespace

3.3.2 Trigger property observers from initializers

3.3.3 Exercises

3.4 Closing thoughts

3.5 Summary

4 Making optionals second nature

4.1 The purpose of optionals

4.2 Clean optional unwrapping

4.2.1 Matching on optionals

4.2.2 Unwrapping techniques

4.2.3 When you’re not interested in a value

4.3 Variable shadowing

4.3.1 Implementing CustomStringConvertible

4.4 When optionals are prohibited

4.4.1 Adding a computed property

4.5 Returning optional strings

4.6 Granular control over optionals

4.6.1 Exercises

4.7 Falling back when an optional is nil

4.8 Simplifying optional enums

4.8.1 Exercise

4.9 Chaining optionals

4.10 Constraining optional booleans

4.10.1 Reducing a boolean to two states

4.10.2 Falling back on true

4.10.3 A boolean with three states

4.10.4 Implementing RawRepresentable

4.10.5 Exercise

4.11 Force unwrapping guidelines

4.11.1 When force unwrapping is "acceptable"

4.11.2 Crashing with style

4.12 Taming Implicitly Unwrapped Optionals

4.12.1 Recognizing IUO’s

4.12.2 IUO’s in practice

4.12.3 Exercise

4.13 Closing thoughts

4.14 Summary

4.15 Answers

5 Demystifying initializers

5.1 Struct initializer rules

5.1.1 Custom initializers

5.1.2 Struct initializer quirk

5.1.2 Exercises

5.2 Initializers and subclassing

5.2.1 Creating a board game superclass

5.2.2 BoardGame’s initializers

5.2.3 Creating a subclass

5.2.4 Losing convenience initializers

5.2.5 Getting the superclass initializers back

5.2.6 Exercise

5.3 Minimizing class initializers

5.3.1 Convenience overrides

5.3.2 Subclassing a subclass

5.3.3 Exercise

5.4 Required initializers

5.4.1 Factory methods

5.4.2 Protocols

5.4.3 When classes are final

5.4.4 Exercises

5.5 Closing thoughts

5.6 Summary

5.7 Answers

6 Effortless error handling

6.1 Errors in Swift

6.1.1 The Error protocol

6.1.2 Throwing errors

6.1.3 Swift doesn’t reveal errors

6.1.4 Keeping the environment in a predictable state

6.1.5 Exercises

6.2 Error propagation and catching

6.2.1 Propagating errors

6.2.2 Adding technical details for troubleshooting

6.2.3 Centralizing error handling

6.2.4 Exercises

6.3 Delivering pleasant API’s

6.3.1 Capturing validity within a type

6.3.2 Try?

6.3.3 Try!

6.3.4 Returning optionals

6.3.5 Exercises

6.4 Closing thoughts

6.5 Summary

6.6 Answers

7 Generics

7.1 The benefits of generics

7.1.1 Creating a generic function

7.1.2 Reasoning about generics

7.1.3 Exercises

7.2 Constraining generics

7.2.1 Needing a constrained function

7.2.2 The Equatable and Comparable protocols

7.2.3 Constraining means specializing

7.2.4 Implementing Comparable

7.2.5 Constraining versus flexibility

7.3 Multiple constraints

7.3.1 The Hashable protocol

7.3.2 Combining constraints

7.3.3 Exercise

7.4 Creating a generic type

7.4.1 Wanting to combine two Hashable types

7.4.2 Creating a Pair type

7.4.3 Multiple generics

7.4.4 Conforming to Hashable

7.4.5 Exercise

7.5 Generics and subtypes

7.5.1 Subtyping and invariance

7.5.2 Invariance in Swift

7.5.3 Swift’s generic types get special privileges

7.5.4 Closing thoughts

7.6 Summary

7.7 Answers

8 Putting the pro in Protocol-Oriented Programming

8.1 Runtime versus compile-time

8.1.1 Creating a protocol

8.1.2 Generics versus protocols

8.1.3 A trade-off with generics

8.1.4 Moving to runtime

8.1.5 Choosing between compile-time and runtime

8.1.6 When a generic is the better choice

8.1.7 Exercises

8.2 The why of associated types

8.2.1 Running into a shortcoming with protocols

8.2.2 Trying to make everything a protocol

8.2.3 Designing a generic protocol

8.2.4 Modeling a protocol with associated types

8.2.5 Implementing a PAT

8.2.6 PATs in the standard library

8.2.7 Other uses for associated types

8.2.8 Exercises

8.3 Passing protocols with associated types

8.3.1 Where clauses with associated types

8.3.2 Types constraining associated types

8.3.3 Cleaning up our API with Protocol inheritance

8.3.4 Exercises

8.4 Summary

8.5 Answers

9 Iterators, Sequences, and Collections

9.1 Iterating

9.1.1 IteratorProtocol

9.1.2 The IteratorProtocol

9.1.3 The Sequence protocol

9.1.4 Taking a closer look at Sequence

9.2 The powers of Sequence

9.2.1 filter

9.2.2 forEach

9.2.3 enumerated

9.2.4 Lazy iteration

9.2.5 Reduce

9.2.6 Reduce into

9.2.7 zip

9.2.8 Exercise

9.3 Creating a generic data structure with Sequence

9.3.1 Bags in action

9.3.2 Creating a BagIterator

9.3.3 Implementing AnyIterator

9.3.4 Implementing ExpressibleByArrayLiteral

9.3.5 Exercise

9.4 The Collection protocol

9.4.1 The Collection landscape

9.4.2 MutableCollection

9.4.3 RangeReplaceableCollection

9.4.4 BidirectionalCollection

9.4.5 RandomAccessCollection

9.5 Creating a Collection

9.5.1 Creating a travel plan

9.5.2 Implementing Collection

9.5.3 Custom subscripts

9.5.4 ExpressibleByDictionaryLiteral

9.5.5 Exercise

9.6 Closing thoughts

9.7 Summary

9.8 Answers

10 Understanding map, flatMap, and compactMap

10.1 Becoming familiar with map

10.1.1 Creating a pipeline with map

10.1.2 Mapping over a dictionary

10.1.3 Exercises

10.2 Mapping over sequences

10.2.1 Exercises

10.3 Mapping over optionals

10.3.1 When to use map on optionals

10.3.2 Creating a cover

10.3.3 A shorter map notation

10.3.4 Exercise

10.4 Map is an abstraction

10.5 Grokking flatMap

10.5.1 What are the benefits of flatMap?

10.5.2 When map doesn’t cut it

10.5.3 Fighting the pyramid of doom

10.5.4 FlatMapping over an optional

10.6 flatMapping over collections

10.6.1 flatMapping over strings

10.6.2 Combining flatMap with map

10.6.3 Using compactMap

10.6.4 Nesting or chaining

10.6.5 Exercises

10.6.6 Closing thoughts

10.7 Summary

10.8 Answers

11 Asynchronous error handling with Result

11.1 Why use the Result type?

11.1.1 Getting your hands on Result

11.1.2 Result is like Optional, with a twist

11.1.3 Understanding the benefits of Result

11.1.4 Creating an API using Result

11.1.5 Bridging from Cocoa Touch to Result

11.2 Propagating Result

11.2.1 Typealiasing for convenience

11.2.2 The search function

11.3 Transforming values inside Result

11.3.1 Exercise

11.3.2 flatMapping over Result

11.3.3 Exercises

11.4 Mixing Result with throwing functions

11.4.1 From throwing to a Result type

11.4.2 Converting a throwing function inside flatMap

11.4.3 Weaving errors through a pipeline

11.4.4 Finishing up

11.4.5 Exercises

11.5 Multiple errors inside of Result

11.5.1 Introducing AnyError

11.6 Impossible failure and Result

11.6.1 When a protocol defines a Result

11.7 Closing thoughts

11.8 Summary

11.9 Answers

12 Protocol extensions

12.1 Class inheritance versus Protocol inheritance

12.1.1 Modeling data horizontally instead of vertically.

12.1.2 Creating a protocol extension

12.1.3 Multiple extensions

12.2 Protocol inheritance versus Protocol composition

12.2.1 When protocol inheritance is a tad rigid

12.2.2 Protocol inheritance

12.2.3 The composition approach

12.2.4 Unlocking the powers of an intersection

12.2.5 Exercises

12.3 Overriding priorities

12.3.1 Overriding a default implementation

12.3.2 Overriding with protocol inheritance

12.3.3 Exercise

12.4 Extending in two directions

12.4.1 Opting in to extensions

12.4.2 Exercises

12.5 Extending with associated types

12.5.1 A specialized extension

12.5.2 A wart in our extension

12.6 Extending with concrete constraints

12.7 Extending Sequence

12.7.1 Looking under the hood of filter

12.7.2 Creating the take(while:) method

12.7.3 Creating the Inspect method

12.7.4 Exercise

12.8 Closing thoughts

12.9 Summary

12.10 Answers

13 Swift Patterns

13.1 Dependency injection

13.1.1 Swapping an implementation

13.1.2 Passing a custom Session

13.1.3 Constraining an associated type

13.1.4 Swapping an implementation

13.1.5 Unit testing and Mocking with associated types

13.1.6 Using the Result type

13.1.7 Exercise

13.2 Conditional conformance

13.2.1 Free functionality

13.2.2 Conditional conformance on associated types

13.2.3 Making Array conditionally conform to a custom protocol

13.2.4 Conditional conformance and generics

13.2.5 Conditional conformance on your types

13.2.6 Exercise

13.3 Falling back to concrete types

13.3.1 Avoiding a protocol using an enum

13.3.2 Type erasing a protocol

13.3.3 Exercise

13.4 An alternative to protocols

13.4.1 With great power comes great unreadability

13.4.2 Creating a generic struct

13.4.3 Rules of thumb for polymorphism

13.5 Closing thoughts

13.6 Summary

13.7 Answers

14 Delivering quality Swift code

14.1 API documentation

14.1.1 How Quick Help works

14.1.2 Adding callouts to Quick Help

14.1.3 Documentation as HTML with Jazzy

14.2 Comments

14.2.1 Explain the why

14.2.2 Only explain obscure elements

14.2.3 Code has the truth

14.2.4 Comments are no band-aid to bad names

14.2.5 Zombie code

14.3 Settling on a style

14.3.1 Consistency is key

14.3.2 Enforcing rules with a linter

14.3.3 Installing Swift Lint

14.3.4 Configure SwiftLint

14.3.5 Temporarily disabling SwiftLint rules

14.3.6 Autocorrecting SwiftLint rules

14.3.7 Keeping SwiftLint in sync

14.4 Kill the Managers

14.4.1 The value of managers

14.4.2 Attacking managers

14.4.3 Paving the road for generics

14.5 Naming abstractions

14.5.1 Generic versus specific

14.5.2 Good names don’t change

14.5.3 Generic naming

14.6 Checklist

14.7 Closing thoughts

14.8 Summary

15 Where to Swift from here

15.1 Build frameworks that build on Linux

15.2 Explore the Swift Package Manager

15.3 Explore frameworks

15.4 Challenge yourself

15.4.1 Join the Swift evolution

15.4.2 Final words

About the Technology

Apple's Swift is the standard language for all macOS development, and is even used for web services, machine learning, and beyond. It's is a modern marvel—easy to pick up, comfortable to use, and loaded with features. After you master the basics, there's a rich, deep world of Swift skills for delivering cleaner, faster code. This book distills the hard-won experience of seasoned Swift developer Tjeerd in 't Veen into a collection of high-value, hard-to-find techniques that will help set you and your Swift applications apart.

About the book

Swift in Depth builds on your core Swift language skills, introducing you to powerful techniques like generics, efficient error handling, protocol-oriented programming, and advanced Swift patterns. You'll explore each new concept through concrete examples, enlightened explanations, and engaging exercises. Some of this stuff is difficult, so you'll really appreciate the careful, crystal clear writing and precise illustrations. When you're finished, you'll be a more productive Swift developer, and a happier Swift developer, as well!

What's inside

  • Adding advanced Swift features to your code
  • Writing reusable code with generics
  • Iterators, sequences, and collections
  • Protocol oriented programming

About the reader

Readers should have some prior experience with the basics of Swift.

About the author

Tjeerd in 't Veen is a senior software engineer and architect who builds iOS apps. Having worked together with many developers, he currently helps creating clean, scalable architectures in the mobile division of a large international banking firm.

Manning Early Access Program (MEAP) Read chapters as they are written, get the finished eBook as soon as it’s ready, and receive the pBook long before it's in bookstores.

FREE domestic shipping on three or more pBooks