├── .gitattributes
├── .gitignore
├── Chapter01
├── AssociatedTypes.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── DelegationPattern.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── ProtocolAsType.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── ProtocolBasics.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ └── contents.xcworkspacedata
└── RobotProtocol.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── jonhoffman.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── Chapter02
├── ClassHierarchy.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── DynamicDispatch.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Enumeration.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── RecursiveType.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Tuple.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Types.playground
│ ├── Contents.swift
│ └── contents.xcplayground
└── ValueVsReference.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── jonhoffman.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── Chapter03
├── CollectionExtension.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── DoubleExtension.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Equatable.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── Factorial.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── IntegerExtension.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── StringExtension.playground
│ ├── Contents.swift
│ └── contents.xcplayground
└── TextValidation.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Chapter04
├── COW.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ ├── jhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── Generic Type Constraint.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Generic1.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── GenericList.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── GenericSubscripts.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── ListDesign.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── jonhoffman.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── Chapter05
└── OOP_Design.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── jonhoffman.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── Chapter06
└── PPO_Design.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Chapter07
├── Bridge.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── Bridge2.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── Builder.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── CommandNew.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Facade.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── FactoryMethod.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Proxy.7z
├── Singleton.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── observer.playground
│ ├── Contents.swift
│ └── contents.xcplayground
└── strategy.playground
│ ├── Contents.swift
│ └── contents.xcplayground
├── Chapter08
├── DataAccess.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── jonhoffman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── Logging.playground
│ ├── Contents.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── jonhoffman.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── LICENSE
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # Windows shortcuts
18 | *.lnk
19 |
20 | # =========================
21 | # Operating System Files
22 | # =========================
23 |
24 | # OSX
25 | # =========================
26 |
27 | .DS_Store
28 | .AppleDouble
29 | .LSOverride
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear in the root of a volume
35 | .DocumentRevisions-V100
36 | .fseventsd
37 | .Spotlight-V100
38 | .TemporaryItems
39 | .Trashes
40 | .VolumeIcon.icns
41 |
42 | # Directories potentially created on remote AFP share
43 | .AppleDB
44 | .AppleDesktop
45 | Network Trash Folder
46 | Temporary Items
47 | .apdisk
48 |
--------------------------------------------------------------------------------
/Chapter01/AssociatedTypes.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | protocol Queue {
8 | associatedtype QueueType
9 | mutating func addItem(item: QueueType)
10 | mutating func getItem() -> QueueType?
11 | func count() -> Int
12 | }
13 |
14 | struct IntQueue: Queue {
15 | var items = [Int]()
16 | mutating func addItem(item: Int) {
17 | items.append(item)
18 | }
19 | mutating func getItem() -> Int? {
20 | if items.count > 0 {
21 | return items.remove(at: 0)
22 | }
23 | else {
24 | return nil
25 | }
26 | }
27 | func count() -> Int {
28 | return items.count
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Chapter01/AssociatedTypes.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter01/DelegationPattern.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | protocol DisplayNameDelegate {
8 | func displayName(name: String)
9 | }
10 |
11 | struct Person {
12 | var displayNameDelegate: DisplayNameDelegate
13 |
14 | var firstName = "" {
15 | didSet {
16 | displayNameDelegate.displayName(name: getFullName())
17 | }
18 | }
19 | var lastName = "" {
20 | didSet {
21 | displayNameDelegate.displayName(name: getFullName())
22 | }
23 | }
24 |
25 | init(displayNameDelegate: DisplayNameDelegate) {
26 | self.displayNameDelegate = displayNameDelegate
27 | }
28 |
29 | func getFullName() -> String {
30 | return "\(firstName) \(lastName)"
31 | }
32 | }
33 |
34 | struct MyDisplayNameDelegate: DisplayNameDelegate {
35 | func displayName(name: String) {
36 | print("Name: \(name)")
37 | }
38 | }
39 |
40 | var displayDelegate = MyDisplayNameDelegate()
41 | var person = Person(displayNameDelegate: displayDelegate)
42 | person.firstName = "Jon"
43 | person.lastName = "Hoffman"
44 |
45 |
--------------------------------------------------------------------------------
/Chapter01/DelegationPattern.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter01/ProtocolAsType.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | protocol Person {
8 | var firstName: String {get set}
9 | var lastName: String {get set}
10 | var birthDate: Date {get set}
11 | var profession: String {get}
12 | init (firstName: String, lastName: String, birthDate: Date)
13 | }
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Chapter01/ProtocolAsType.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter01/ProtocolBasics.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | protocol FullName {
8 | var firstName: String {get set}
9 | var lastName: String {get set}
10 |
11 | func getFullName() -> String
12 | }
13 |
14 | protocol Person: FullName {
15 | var age: Int {get set}
16 | }
17 |
18 | struct Student: Person {
19 | var firstName = ""
20 | var lastName = ""
21 | var age = 0
22 |
23 | func getFullName() -> String {
24 | return "(firstName) (lastName)"
25 | }
26 | }
27 |
28 |
29 | @objc protocol Phone {
30 | var phoneNumber: String {get set}
31 | @objc optional var emailAddress: String {get set}
32 | func dialNumber()
33 | @objc optional func getEmail()
34 | }
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Chapter01/ProtocolBasics.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter01/ProtocolBasics.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/Chapter01/RobotProtocol.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 |
8 | protocol RobotMovement {
9 | func forward(speedPercent: Double)
10 | func reverse(speedPercent: Double)
11 | func left(speedPercent: Double)
12 | func right(seedPercent: Double)
13 | func stop()
14 | }
15 |
16 | protocol RobotMovementThreeDimensions: RobotMovement {
17 | func up(speedPercent: Double)
18 | func down(speedPercent: Double)
19 | }
20 |
21 | protocol Sensor {
22 | var sensorName: String {get set}
23 | var sensorType: String {get}
24 | init (sensorName: String)
25 | func pollSensor()
26 | }
27 |
28 | protocol RangeSensor: Sensor {
29 | func setRangeNotification(rangeCentimeter: Double, rangeNotification: () -> Void)
30 | func currentRange() -> Double
31 | }
32 |
33 | protocol EnvironmentSensor: Sensor {
34 | func currentTemperature() -> Double
35 | func currentHumidity() -> Double
36 | }
37 |
38 | protocol DisplaySensor: Sensor {
39 | func displayMessage(message: String)
40 | }
41 |
42 | protocol WirelessSensor: Sensor {
43 | func setMessageReceivedNotification(messageNotification: (String) -> Void)
44 | func messageSend(message: String)
45 | }
46 |
47 | protocol Robot {
48 | var name: String {get set}
49 | var robotMovement: RobotMovement {get set}
50 | var sensors: [Sensor] {get}
51 |
52 | init (name: String, robotMovement: RobotMovement)
53 | func addSensor(sensor: Sensor)
54 | func pollSensors()
55 | }
56 |
57 | class SixWheelRover: Robot {
58 | var name = "No Name"
59 | var robotMovement: RobotMovement
60 | var sensors: [Sensor] = [Sensor]()
61 |
62 | required init (name: String, robotMovement: RobotMovement) {
63 | self.name = name
64 | self.robotMovement = robotMovement
65 | }
66 | func addSensor(sensor: Sensor) {
67 | sensors.append(sensor)
68 | }
69 |
70 | func pollSensors() {
71 | for sensor in sensors {
72 | sensor.pollSensor()
73 | }
74 | }
75 |
76 | func addRangeSensor(sensor: RangeSensor, rangeCentimeter: Double) {
77 | sensor.setRangeNotification(rangeCentimeter: rangeCentimeter, rangeNotification: rangeNotification)
78 | addSensor(sensor: sensor)
79 | }
80 |
81 | func addWirelessSensor(sensor: WirelessSensor) {
82 | addSensor(sensor: sensor)
83 | sensor.setMessageReceivedNotification(messageNotification: messageReceived)
84 | }
85 |
86 | func rangeNotification() {
87 | print("Too Close")
88 | }
89 |
90 | func messageReceived(message: String) {
91 | print("Message Received: " + message)
92 | }
93 | }
94 |
95 |
--------------------------------------------------------------------------------
/Chapter01/RobotProtocol.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter01/RobotProtocol.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter01/RobotProtocol.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter01/RobotProtocol.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter02/ClassHierarchy.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | class Animal {
8 | var numberOfLegs = 0
9 | func sleeps() {
10 | print("zzzzz")
11 | }
12 | func walking() {
13 | print("Walking on \(numberOfLegs) legs")
14 | }
15 | func speaking() {
16 | print("No sound")
17 | }
18 | }
19 |
20 |
21 | class Biped: Animal {
22 | override init() {
23 | super.init()
24 | numberOfLegs = 2
25 | }
26 | }
27 |
28 | class Quadruped: Animal {
29 | override init() {
30 | super.init()
31 | numberOfLegs = 4
32 | }
33 | }
34 |
35 | class Dog: Quadruped {
36 | override func speaking() {
37 | print("Barking")
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Chapter02/ClassHierarchy.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter02/ClassHierarchy.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter02/ClassHierarchy.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter02/ClassHierarchy.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter02/DynamicDispatch.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | class Animal {
8 | final var numberOfLegs = 0
9 | func sleeps() {
10 | print("zzzzz")
11 | }
12 | final func walking() {
13 | print("Walking on \(numberOfLegs) legs")
14 | }
15 | func speaking() {
16 | print("No sound")
17 | }
18 | }
19 |
20 |
21 | class Biped: Animal {
22 | override init() {
23 | super.init()
24 | numberOfLegs = 2
25 | }
26 |
27 | }
28 |
29 | class Quadruped: Animal {
30 | override init() {
31 | super.init()
32 | numberOfLegs = 4
33 | }
34 | }
35 |
36 | class Dog: Quadruped {
37 | override func speaking() {
38 | print("Barking")
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/Chapter02/DynamicDispatch.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter02/Enumeration.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | enum Devices: String {
8 | case IPod = "iPod"
9 | case IPhone = "iPhone"
10 | case IPad = "iPad"
11 | }
12 |
13 | Devices.IPod.rawValue
14 |
15 | enum Devices2 {
16 | case IPod(model: Int, year: Int, memory: Int)
17 | case IPhone(model: String, memory: Int)
18 | case IPad(model: String, memory: Int)
19 | }
20 |
21 | var myPhone = Devices2.IPhone(model: "6", memory: 64)
22 | var myTablet = Devices2.IPad(model: "Pro", memory: 128)
23 |
24 | switch myPhone {
25 | case .IPod(let model, let year, let memory):
26 | print("iPod: \(model) \(memory)")
27 | case .IPhone(let model, let memory):
28 | print("iPhone: \(model) \(memory)")
29 | case .IPad(let model, let memory):
30 | print("iPad: \(model) \(memory)")
31 | }
32 |
33 | enum Reindeer: String {
34 | case Dasher, Dancer, Prancer, Vixen,
35 | Comet, Cupid, Donner, Blitzen, Rudolph
36 | static var allCases: [Reindeer] {
37 | return [Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen, Rudolph]
38 | }
39 | static func randomCase() -> Reindeer {
40 | let randomValue = Int(
41 | arc4random_uniform( UInt32(allCases.count)
42 | )
43 | )
44 | return allCases[randomValue]
45 | }
46 | }
47 |
48 | enum BookFormat {
49 | case PaperBack (pageCount: Int, price: Double)
50 | case HardCover (pageCount: Int, price: Double)
51 | case PDF (pageCount: Int, price: Double)
52 | case EPub (pageCount: Int, price: Double)
53 | case Kindle (pageCount: Int, price: Double)
54 | }
55 |
56 | var paperBack = BookFormat.PaperBack(pageCount: 220, price: 39.99)
57 |
58 | switch paperBack {
59 | case .PaperBack(let pageCount, let price):
60 | print("\(pageCount) - \(price)")
61 | case .HardCover(let pageCount, let price):
62 | print("\(pageCount) - \(price)")
63 | case .PDF(let pageCount, let price):
64 | print("\(pageCount) - \(price)")
65 | case .EPub(let pageCount, let price):
66 | print("\(pageCount) - \(price)")
67 | case .Kindle(let pageCount, let price):
68 | print("\(pageCount) - \(price)")
69 | }
70 |
71 | enum BookFormat2 {
72 | case PaperBack (pageCount: Int, price: Double)
73 | case HardCover (pageCount: Int, price: Double)
74 | case PDF (pageCount: Int, price: Double)
75 | case EPub (pageCount: Int, price: Double)
76 | case Kindle (pageCount: Int, price: Double)
77 |
78 | var pageCount: Int {
79 | switch self {
80 | case .PaperBack(let pageCount, _):
81 | return pageCount
82 | case .HardCover(let pageCount, _):
83 | return pageCount
84 | case .PDF(let pageCount, _):
85 | return pageCount
86 | case .EPub(let pageCount, _):
87 | return pageCount
88 | case .Kindle(let pageCount, _):
89 | return pageCount
90 | }
91 | }
92 | var price: Double {
93 | switch self {
94 | case .PaperBack(_, let price):
95 | return price
96 | case .HardCover(_, let price):
97 | return price
98 | case .PDF(_, let price):
99 | return price
100 | case .EPub(_, let price):
101 | return price
102 | case .Kindle(_, let price):
103 | return price
104 | }
105 | }
106 | }
107 |
108 | var paperBack2 = BookFormat2.PaperBack(pageCount: 220, price: 39.99)
109 | print("\(paperBack2.pageCount) - \(paperBack2.price)")
110 |
111 |
--------------------------------------------------------------------------------
/Chapter02/Enumeration.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter02/RecursiveType.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | class LinkedListReferenceType {
8 | var value: String
9 | var next: LinkedListReferenceType?
10 | init(value: String) {
11 | self.value = value
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Chapter02/RecursiveType.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter02/Tuple.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | let mathGrade1 = ("Jon", 100)
8 | let (name, score) = mathGrade1
9 | print("\(name) - \(score)")
10 |
11 | let mathGrade2 = (name: "Jon", grade: 100)
12 | print("\(mathGrade2.name) - \(mathGrade2.grade)")
13 |
14 | func calculateTip(billAmount: Double,tipPercent: Double) -> (tipAmount: Double, totalAmount: Double) {
15 | let tip = billAmount * (tipPercent/100)
16 | let total = billAmount + tip
17 | return (tipAmount: tip, totalAmount: total)
18 | }
19 |
20 | var tip = calculateTip(billAmount:31.98, tipPercent: 20)
21 | print("\(tip.tipAmount) - \(tip.totalAmount)")
22 |
--------------------------------------------------------------------------------
/Chapter02/Tuple.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter02/Types.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | class MyClass {
8 | var oneProperty: String
9 |
10 | init(oneProperty: String) {
11 | self.oneProperty = oneProperty
12 | }
13 |
14 | func oneFunction() {
15 |
16 | }
17 | }
18 |
19 | struct MyStruct {
20 | var oneProperty: String
21 |
22 | func oneFunction() {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Chapter02/Types.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter02/ValueVsReference.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | struct MyValueType {
8 | var name: String
9 | var assignment: String
10 | var grade: Int
11 | }
12 |
13 | class MyReferenceType {
14 | var name: String
15 | var assignment: String
16 | var grade: Int
17 |
18 | init(name: String, assignment: String, grade: Int) {
19 | self.name = name
20 | self.assignment = assignment
21 | self.grade = grade
22 | }
23 |
24 | func extraCreditReferenceType(ref: MyReferenceType, extraCredit: Int) {
25 | ref.grade += extraCredit
26 | }
27 |
28 | }
29 |
30 | var ref = MyReferenceType(name: "Jon", assignment: "Math Test 1", grade: 90)
31 | var val = MyValueType(name: "Jon", assignment: "Math Test 1", grade: 90)
32 |
33 | func extraCreditReferenceType(ref: MyReferenceType, extraCredit: Int) {
34 | ref.grade += extraCredit
35 | }
36 |
37 | func extraCreditValueType(val: MyValueType, extraCredit: Int) {
38 | var val = val
39 | val.grade += extraCredit
40 | }
41 |
42 | var ref1 = MyReferenceType(name: "Jon", assignment: "Math Test 1", grade: 90)
43 | extraCreditReferenceType(ref: ref1, extraCredit:5)
44 | print("Reference: \(ref1.name) - \(ref1.grade)")
45 |
46 | var val2 = MyValueType(name: "Jon", assignment: "Math Test 1", grade: 90)
47 | extraCreditValueType(val: val2, extraCredit:5)
48 | print("Value: \(val2.name) - \(val2.grade)")
49 |
50 |
51 | func getGradeForAssignment(assignment: MyReferenceType) {
52 | // Code to get grade from DB
53 | // Random code here to illustrate issue
54 | let num = Int(arc4random_uniform(20) + 80)
55 | assignment.grade = num
56 | print("Grade for \(assignment.name) is \(num)")
57 | }
58 |
59 | var mathGrades = [MyReferenceType]()
60 | var students = ["Jon", "Kim", "Kailey", "Kara"]
61 | var mathAssignment = MyReferenceType(name: "", assignment: "Math Assignment", grade: 0)
62 |
63 | for student in students {
64 | mathAssignment.name = student
65 | getGradeForAssignment(assignment: mathAssignment)
66 | mathGrades.append(mathAssignment)
67 | }
68 |
69 | for assignment in mathGrades {
70 | print("\(assignment.name): grade \(assignment.grade)")
71 | }
72 |
73 | func getGradeForAssignment(assignment: inout MyValueType) {
74 | // Code to get grade from DB
75 | // Random code here to illustrate issue
76 | let num = Int(arc4random_uniform(20) + 80)
77 | assignment.grade = num
78 | print("Grade for \(assignment.name) is \(num)")
79 | }
80 |
81 | var mathGrades2 = [MyValueType]()
82 | var mathAssignment2 = MyValueType(name: "", assignment: "Math Assignment", grade: 0)
83 |
84 | for student in students {
85 | mathAssignment2.name = student
86 | getGradeForAssignment(assignment: &mathAssignment2)
87 | mathGrades2.append(mathAssignment2)
88 | }
89 |
90 | for assignment in mathGrades2 {
91 | print("\(assignment.name): grade \(assignment.grade)")
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/Chapter02/ValueVsReference.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter02/ValueVsReference.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter02/ValueVsReference.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter02/ValueVsReference.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter03/CollectionExtension.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | extension Collection {
8 | func evenElements() -> [Iterator.Element] {
9 |
10 | var index = startIndex
11 | var result: [Iterator.Element] = []
12 | var i = 0
13 | repeat {
14 | if i % 2 == 0 {
15 | result.append(self[index])
16 | }
17 | index = self.index(after: index)
18 | i += 1
19 | } while (index != endIndex)
20 | return result
21 | }
22 |
23 | func shuffle() -> [Iterator.Element] {
24 | return sorted(){ left, right in
25 | return arc4random() < arc4random()
26 | }
27 | }
28 | }
29 |
30 | extension Collection where Self: ExpressibleByArrayLiteral {
31 | //Extension code here
32 | }
33 |
34 | extension Collection where Iterator.Element: Comparable {
35 | // Add functionality here
36 | }
37 |
38 |
39 | var origArray = [1,2,3,4,5,6,7,8,9,10]
40 |
41 | var newArray = origArray.evenElements()
42 | var ranArray = origArray.shuffle()
43 |
44 |
45 | var origDict = [1:"One",2:"Two",3:"Three",4:"Four"]
46 | var returnElements = origDict.evenElements()
47 | for item in returnElements {
48 | print(item)
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/Chapter03/CollectionExtension.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter03/CollectionExtension.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter03/CollectionExtension.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter03/CollectionExtension.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter03/DoubleExtension.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | extension Double {
8 | func currencyString() -> String {
9 | let divisor = pow(10.0, 2.0)
10 | let num = (self * divisor).rounded() / divisor
11 | return "$\(num)"
12 | }
13 | }
14 |
15 | print(25.6789.currencyString())
16 |
--------------------------------------------------------------------------------
/Chapter03/DoubleExtension.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter03/Equatable.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | struct Place {
8 | let id: String
9 | let latitude: Double
10 | let longitude: Double
11 | }
12 |
13 | extension Place: Equatable {
14 | static func ==(lhs: Place, rhs: Place) -> Bool {
15 | return lhs.id == rhs.id &&
16 | lhs.latitude == rhs.latitude &&
17 | lhs.longitude == rhs.longitude
18 | }
19 | }
20 |
21 | var placeOne = Place(id: "Fenway Park", latitude: 42.3467, longitude: -71.0972)
22 | var placeTwo = Place(id: "Wrigley Field", latitude: 41.9484, longitude: -87.6553)
23 |
24 | print(placeOne == placeTwo)
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Chapter03/Equatable.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter03/Equatable.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter03/Equatable.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter03/Equatable.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter03/Factorial.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | extension Int {
8 | func factorial() -> Int {
9 | var answer = 1
10 | for x in (1...self).reversed() {
11 | answer *= x
12 | }
13 | return answer
14 | }
15 | }
16 |
17 |
18 | print(10.factorial())
19 |
20 |
--------------------------------------------------------------------------------
/Chapter03/Factorial.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter03/Factorial.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter03/Factorial.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter03/Factorial.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter03/IntegerExtension.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | extension Int {
8 | func squared() -> Int {
9 | return self * self
10 | }
11 | }
12 |
13 | extension Int {
14 | var squared2: Int {
15 | return self * self
16 | }
17 | }
18 |
19 |
20 | print(6.squared())
21 | print(6.squared2)
22 |
--------------------------------------------------------------------------------
/Chapter03/IntegerExtension.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter03/StringExtension.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | extension String {
8 | func getFirstChar() -> Character? {
9 | guard characters.count > 0 else {
10 | return nil
11 | }
12 | return self[startIndex]
13 | }
14 |
15 | subscript (r: CountableClosedRange) -> String {
16 | get {
17 | let start = index(self.startIndex, offsetBy:r.lowerBound)
18 | let end = index(self.startIndex, offsetBy:r.upperBound)
19 | return substring(with: start..
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter03/TextValidation.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | protocol TextValidation1 {
8 |
9 | var regExMatchingString: String {get}
10 | var regExFindMatchString: String {get}
11 | var validationMessage: String {get}
12 | func validateString(str: String) -> Bool
13 | func getMatchingString(str: String) -> String?
14 | }
15 |
16 | class AlphabeticValidation1: TextValidation1 {
17 | static let sharedInstance = AlphabeticValidation1()
18 | private init(){}
19 | let regExFindMatchString = "^[a-zA-Z]{0,10}"
20 | let validationMessage = "Can only contain Alpha characters"
21 | var regExMatchingString: String {
22 | get {
23 | return regExFindMatchString + "$"
24 | }
25 | }
26 | func validateString(str: String) -> Bool {
27 | if let _ = str.range(of: regExMatchingString, options:
28 | .regularExpression){
29 | return true
30 | } else {
31 | return false
32 | }
33 | }
34 | func getMatchingString(str: String) -> String? {
35 | if let newMatch = str.range(of: regExFindMatchString, options:
36 | .regularExpression) {
37 | return str.substring(with: newMatch)
38 | } else {
39 | return nil
40 | }
41 | }
42 | }
43 |
44 | protocol TextValidation {
45 | var regExFindMatchString: String {get}
46 | var validationMessage: String {get}
47 | }
48 |
49 | extension TextValidation {
50 | var regExMatchingString: String {
51 | get {
52 | return regExFindMatchString + "$"
53 | }
54 | }
55 | func validateString(str: String) -> Bool {
56 | if let _ = str.range(of: regExMatchingString, options:
57 | .regularExpression){
58 | return true
59 | } else {
60 | return false
61 | }
62 | }
63 | func getMatchingString(str: String) -> String? {
64 | if let newMatch = str.range(of: regExFindMatchString, options:
65 | .regularExpression){
66 | return str.substring(with: newMatch)
67 | } else {
68 | return nil
69 | }
70 | }
71 | }
72 |
73 | class AlphabeticValidation: TextValidation {
74 | static let sharedInstance = AlphabeticValidation()
75 | private init(){}
76 | let regExFindMatchString = "^[a-zA-Z]{0,10}"
77 | let validationMessage = "Can only contain Alpha characters"
78 | }
79 |
80 | class AlphaNumericValidation: TextValidation {
81 | static let sharedInstance = AlphaNumericValidation()
82 | private init(){}
83 | let regExFindMatchString = "^[a-zA-Z0-9]{0,15}"
84 | let validationMessage = "Can only contain Alpha Numeric characters"
85 | }
86 |
87 |
88 | class DisplayNameValidation: TextValidation {
89 | static let sharedInstance = DisplayNameValidation()
90 | private init(){}
91 | let regExFindMatchString = "^[\\s?[a-zA-Z0-9\\-_\\s]]{0,15}"
92 | let validationMessage = "Display Name can contain only contain Alphanumeric Characters"
93 | }
94 |
95 | var myString1 = "abcxyz"
96 | var myString2 = "abc123"
97 | var validation = AlphabeticValidation.sharedInstance
98 | validation.validateString(str: myString1)
99 | validation.validateString(str: myString2)
100 |
101 | validation.getMatchingString(str: myString1)
102 | validation.getMatchingString(str: myString2)
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/Chapter03/TextValidation.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter04/COW.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | fileprivate class BackendQueue {
8 | private var items = [T]()
9 |
10 | public init() {}
11 | private init(_ items: [T]) {
12 | self.items = items
13 | }
14 |
15 | public func addItem(item: T) {
16 | items.append(item)
17 | }
18 |
19 | public func getItem() -> T? {
20 | if items.count > 0 {
21 | return items.remove(at: 0)
22 | } else {
23 | return nil
24 | }
25 | }
26 | public func count() -> Int {
27 | return items.count
28 | }
29 | public func copy() -> BackendQueue {
30 | return BackendQueue(items)
31 | }
32 | }
33 |
34 | struct Queue {
35 | private var internalQueue = BackendQueue()
36 |
37 | mutating private func checkUniquelyReferencedInternalQueue() {
38 | if !isKnownUniquelyReferenced(&internalQueue) {
39 | print("Making a copy of internalQueue")
40 | internalQueue = internalQueue.copy()
41 | } else {
42 | print("Not making a copy of internalQueue")
43 | }
44 | }
45 |
46 | public mutating func addItem(item: Int) {
47 | checkUniquelyReferencedInternalQueue()
48 | internalQueue.addItem(item: item)
49 | }
50 | public mutating func getItem() -> Int? {
51 | checkUniquelyReferencedInternalQueue();
52 | return internalQueue.getItem()
53 | }
54 | public func count() -> Int {
55 | return internalQueue.count()
56 | }
57 | mutating public func uniquelyReferenced() -> Bool{
58 | return isKnownUniquelyReferenced(&internalQueue)
59 | }
60 | }
61 |
62 | fileprivate var queue1 = BackendQueue()
63 | queue1.addItem(item: 1)
64 | queue1.addItem(item: 2)
65 |
66 | isKnownUniquelyReferenced(&queue1)
67 |
68 | fileprivate var queue2 = queue1
69 |
70 | isKnownUniquelyReferenced(&queue1)
71 |
72 | var queue3 = Queue()
73 | queue3.addItem(item: 1)
74 |
75 | print(queue3.uniquelyReferenced())
76 |
77 | var queue4 = queue3
78 |
79 | print(queue3.uniquelyReferenced())
80 | print(queue4.uniquelyReferenced())
81 |
82 | queue3.addItem(item: 2)
83 |
84 | print(queue3.uniquelyReferenced())
85 | print(queue4.uniquelyReferenced())
86 | queue4.addItem(item: 3)
87 | queue3.addItem(item: 4)
88 |
89 | print(queue3.count())
90 | print(queue4.count())
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/Chapter04/COW.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter04/COW.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter04/COW.playground/playground.xcworkspace/xcuserdata/jhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter04/COW.playground/playground.xcworkspace/xcuserdata/jhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter04/COW.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter04/COW.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter04/Generic Type Constraint.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | func testGenericComparable(a: T, b: T) -> Bool{
8 | return a == b
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/Chapter04/Generic Type Constraint.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter04/Generic1.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | func swapGeneric(a: inout T, b: inout T) {
8 | let tmp = a
9 | a = b
10 | b = tmp
11 | }
12 |
13 | var a = 5
14 | var b = 10
15 | swapGeneric(a: &a, b: &b)
16 | print("a: \(a) b: \(b)")
17 |
18 | var c = "My String 1"
19 | var d = "My String 2"
20 | swapGeneric(a: &c, b: &d)
21 | print("c:\(c) d:\(d)")
22 |
23 |
24 | func testGeneric(a:T, b:E) {
25 | print("\(a) \(b)")
26 | }
27 |
--------------------------------------------------------------------------------
/Chapter04/Generic1.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter04/GenericList.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | struct List {
8 | var items = [T]()
9 | mutating func add(item: T) {
10 | items.append(item)
11 | }
12 | func getItemAtIndex(index: Int) -> T? {
13 | if items.count > index {
14 | return items[index]
15 | } else {
16 | return nil
17 | }
18 | }
19 | }
20 |
21 |
22 | var list = List()
23 | list.add(item: "Hello")
24 | list.add(item: "World")
25 | print(list.getItemAtIndex(index: 1))
26 |
--------------------------------------------------------------------------------
/Chapter04/GenericList.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter04/GenericList.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter04/GenericList.playground/playground.xcworkspace/xcuserdata/jhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter04/GenericList.playground/playground.xcworkspace/xcuserdata/jhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter04/GenericSubscripts.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import UIKit
4 |
5 | var str = "Hello, playground"
6 |
7 | struct List {
8 | private var items = [T]()
9 | public mutating func add(item: T) {
10 | items.append(item)
11 | }
12 | public func getItemAtIndex(index: Int) -> T? {
13 | if items.count > index {
14 | return items[index]
15 | } else {
16 | return nil
17 | }
18 | }
19 | public subscript(index: Int) -> T? {
20 | return getItemAtIndex(index: index)
21 | }
22 | public subscript(indices: E) -> [T]
23 | where E.Iterator.Element == Int {
24 | var result = [T]()
25 | for index in indices {
26 | result.append(items[index])
27 | }
28 | return result
29 | }
30 | }
31 |
32 |
33 |
34 | var myList = List()
35 | myList.add(item: 1)
36 | myList.add(item: 2)
37 | myList.add(item: 3)
38 | myList.add(item: 4)
39 | myList.add(item: 5)
40 |
41 | myList[2...4]
42 |
43 | myList[4]
44 |
--------------------------------------------------------------------------------
/Chapter04/GenericSubscripts.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter04/GenericSubscripts.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter04/GenericSubscripts.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter04/GenericSubscripts.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter04/ListDesign.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | protocol List {
8 | associatedtype T
9 | subscript(indices: E) -> [T] where E.Iterator.Element == Int { get }
10 | mutating func add(_ item: T)
11 | func length() -> Int
12 | func get(at: Int) -> T?
13 | mutating func delete(at: Int)
14 | }
15 |
16 | private class BackendList {
17 | private var items: [T] = []
18 |
19 | public init() {}
20 | private init(_ items: [T]) {
21 | self.items = items
22 | }
23 |
24 | public func add(_ item: T) {
25 | items.append(item)
26 | }
27 | public func length() -> Int {
28 | return items.count
29 | }
30 | public func get(at index: Int) -> T? {
31 | return items[index]
32 | }
33 | public func delete(at index: Int) {
34 | items.remove(at: index)
35 | }
36 | public func copy() -> BackendList {
37 | return BackendList(items)
38 | }
39 | }
40 |
41 | struct ArrayList: List {
42 | private var items = BackendList()
43 |
44 | public subscript(indices: E) -> [T]
45 | where E.Iterator.Element == Int {
46 | var result = [T]()
47 | for index in indices {
48 | if let item = items.get(at: index) {
49 | result.append(item)
50 | }
51 | }
52 | return result
53 | }
54 |
55 | public mutating func add(_ item: T) {
56 | checkUniquelyReferencedInternalQueue()
57 | items.add(item)
58 | }
59 | public func length() -> Int {
60 | return items.length()
61 | }
62 | public func get(at index: Int) -> T? {
63 | return items.get(at: index)
64 | }
65 | public mutating func delete(at index: Int) {
66 | checkUniquelyReferencedInternalQueue()
67 | items.delete(at: index)
68 | }
69 |
70 | mutating private func checkUniquelyReferencedInternalQueue() {
71 | if !isKnownUniquelyReferenced(&items) {
72 | print("Making a copy of internalQueue")
73 | items = items.copy()
74 | } else {
75 | print("Not making a copy of internalQueue")
76 | }
77 | }
78 | }
79 |
80 |
81 |
82 | var arrayList = ArrayList()
83 | arrayList.add(1)
84 | arrayList.add(2)
85 | arrayList.add(3)
86 |
87 | var newArrayList = arrayList
88 | arrayList.add(4)
89 |
90 |
--------------------------------------------------------------------------------
/Chapter04/ListDesign.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter04/ListDesign.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter04/ListDesign.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter04/ListDesign.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter05/OOP_Design.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 |
8 | enum TerrainType {
9 | case Land
10 | case Sea
11 | case Air
12 | }
13 |
14 | class Vehicle {
15 | fileprivate var vehicleTypes = [TerrainType]()
16 | fileprivate var vehicleAttackTypes = [TerrainType]()
17 | fileprivate var vehicleMovementTypes = [TerrainType]()
18 |
19 | fileprivate var landAttackRange = -1
20 | fileprivate var seaAttackRange = -1
21 | fileprivate var airAttackRange = -1
22 |
23 | fileprivate var hitPoints = 0
24 |
25 | func isVehicleType(type: TerrainType) -> Bool {
26 | return vehicleTypes.contains(type)
27 | }
28 | func canVehicleAttack(type: TerrainType) -> Bool {
29 | return vehicleAttackTypes.contains(type)
30 | }
31 | func canVehicleMove(type: TerrainType) -> Bool {
32 | return vehicleMovementTypes.contains(type)
33 | }
34 | func doLandAttack() {}
35 | func doLandMovement() {}
36 |
37 | func doSeaAttack() {}
38 | func doSeaMovement() {}
39 |
40 | func doAirAttack() {}
41 | func doAirMovement() {}
42 |
43 | func takeHit(amount: Int) { hitPoints -= amount }
44 | func hitPointsRemaining() -> Int { return hitPoints }
45 | func isAlive() -> Bool { return hitPoints > 0 ? true : false }
46 | }
47 |
48 | class Tank: Vehicle {
49 | override init() {
50 | super.init()
51 | vehicleTypes = [.Land]
52 |
53 | vehicleAttackTypes = [.Land]
54 | vehicleMovementTypes = [.Land]
55 | landAttackRange = 5
56 |
57 | hitPoints = 68
58 | }
59 |
60 | override func doLandAttack() {
61 | print("Tank Attack")
62 | }
63 | override func doLandMovement() {
64 | print("Tank Move") }
65 | }
66 |
67 | class Amphibious: Vehicle {
68 | override init() {
69 | super.init()
70 | vehicleTypes = [.Land, .Sea]
71 | vehicleAttackTypes = [.Land, .Sea]
72 | vehicleMovementTypes = [.Land, .Sea]
73 |
74 | landAttackRange = 1
75 | seaAttackRange = 1
76 |
77 | hitPoints = 25
78 | }
79 | override func doLandAttack() {
80 | print("Amphibious Land Attack")
81 | }
82 | override func doLandMovement() {
83 | print("Amphibious Land Move")
84 | }
85 | override func doSeaAttack() {
86 | print("Amphibious Sea Attack")
87 | }
88 | override func doSeaMovement() {
89 | print("Amphibious Sea Move")
90 | }
91 | }
92 |
93 | class Transformer: Vehicle {
94 | override init() {
95 | super.init()
96 | vehicleTypes = [.Land, .Sea, .Air]
97 | vehicleAttackTypes = [.Land, .Sea, .Air]
98 | vehicleMovementTypes = [.Land, .Sea, .Air]
99 |
100 | landAttackRange = 7
101 | seaAttackRange = 10
102 | airAttackRange = 12
103 |
104 | hitPoints = 75
105 | }
106 |
107 | override func doLandAttack() {
108 | print("Transformer Land Attack")
109 | }
110 | override func doLandMovement() {
111 | print("Transformer Land Move")
112 | }
113 |
114 | override func doSeaAttack() {
115 | print("Transformer Sea Attack")
116 | }
117 | override func doSeaMovement() {
118 | print("Transformer Sea Move")
119 | }
120 |
121 | override func doAirAttack() {
122 | print("Transformer Air Attack")
123 | }
124 | override func doAirMovement() {
125 | print("Transformer Air Move")
126 | }
127 | }
128 |
129 | class Infantry: Vehicle {
130 | override init() {
131 | super.init()
132 | vehicleTypes = [.Land]
133 | vehicleAttackTypes = [.Land]
134 | vehicleMovementTypes = [.Sea]
135 |
136 | landAttackRange = 1
137 | seaAttackRange = 1
138 |
139 | hitPoints = 25
140 | }
141 | override func doLandAttack() {
142 | print("Amphibious Land Attack")
143 | }
144 | override func doLandMovement() {
145 | print("Amphibious Land Move")
146 | }
147 | }
148 |
149 |
150 | var vehicles = [Vehicle]()
151 |
152 | var vh1 = Amphibious()
153 | var vh2 = Amphibious()
154 | var vh3 = Tank()
155 | var vh4 = Transformer()
156 |
157 | vehicles.append(vh1)
158 | vehicles.append(vh2)
159 | vehicles.append(vh3)
160 | vehicles.append(vh4)
161 |
162 |
163 | for (index, vehicle) in vehicles.enumerated() {
164 | if vehicle.isVehicleType(type: .Air) {
165 | print("Vehicle at \(index) is Air")
166 | if vehicle.canVehicleAttack(type: .Air) {
167 | vehicle.doAirAttack()
168 | }
169 |
170 | if vehicle.canVehicleMove(type: .Air) {
171 | vehicle.doAirMovement()
172 | }
173 | }
174 |
175 | if vehicle.isVehicleType(type: .Land){
176 | print("Vehicle at \(index) is Land")
177 |
178 | if vehicle.canVehicleAttack(type: .Land) {
179 | vehicle.doLandAttack()
180 | }
181 | if vehicle.canVehicleMove(type: .Land) {
182 | vehicle.doLandMovement()
183 | }
184 | }
185 | if vehicle.isVehicleType(type: .Sea) {
186 | print("Vehicle at \(index) is Sea")
187 | if vehicle.canVehicleAttack(type: .Sea) {
188 | vehicle.doSeaAttack()
189 | }
190 | if vehicle.canVehicleMove(type: .Sea) {
191 | vehicle.doSeaMovement()
192 | }
193 | }
194 | }
195 |
196 | for (index, vehicle) in vehicles.enumerated() where vehicle.isVehicleType(type: .Air) {
197 | if vehicle.isVehicleType(type: .Air) {
198 | print("**Vehicle at \(index) is Air")
199 | if vehicle.canVehicleAttack(type: .Air) {
200 | vehicle.doAirAttack()
201 | }
202 |
203 | if vehicle.canVehicleMove(type: .Air) {
204 | vehicle.doAirMovement()
205 | }
206 | }
207 | }
208 |
209 |
210 | func takeHit(vehicle: Vehicle) {
211 | vehicle.takeHit(amount: 10)
212 | }
213 |
214 | var vh = Tank()
215 | takeHit(vehicle: vh)
216 | print(vh.hitPointsRemaining())
217 |
--------------------------------------------------------------------------------
/Chapter05/OOP_Design.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter05/OOP_Design.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter05/OOP_Design.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter05/OOP_Design.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter06/PPO_Design.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var str = "Hello, playground"
6 |
7 | protocol Vehicle {
8 | var hitPoints: Int {get set}
9 | }
10 |
11 | extension Vehicle {
12 |
13 | mutating func takeHit(amount: Int) {
14 | hitPoints -= amount
15 | }
16 | func hitPointsRemaining() -> Int {
17 | return hitPoints }
18 | func isAlive() -> Bool {
19 | return hitPoints > 0 ? true : false
20 | }
21 | }
22 |
23 | protocol LandVehicle: Vehicle {
24 | var landAttack: Bool {get}
25 | var landMovement: Bool {get}
26 | var landAttackRange: Int {get}
27 |
28 | func doLandAttack()
29 | func doLandMovement()
30 | }
31 |
32 | protocol SeaVehicle: Vehicle {
33 | var seaAttack: Bool {get}
34 | var seaMovement: Bool {get}
35 | var seaAttackRange: Int {get}
36 |
37 | func doSeaAttack()
38 | func doSeaMovement()
39 | }
40 |
41 | protocol AirVehicle: Vehicle {
42 | var airAttack: Bool {get}
43 | var airMovement: Bool {get}
44 | var airAttackRange: Int {get}
45 |
46 | func doAirAttack()
47 | func doAirMovement()
48 | }
49 |
50 | struct Tank: LandVehicle {
51 | var hitPoints = 68
52 | let landAttackRange = 5
53 | let landAttack = true
54 | let landMovement = true
55 |
56 | func doLandAttack() { print("Tank Attack") }
57 | func doLandMovement() { print("Tank Move") }
58 | }
59 |
60 | struct Amphibious: LandVehicle, SeaVehicle {
61 | var hitPoints = 25
62 | let landAttackRange = 1
63 | let seaAttackRange = 1
64 |
65 | let landAttack = true
66 | let landMovement = true
67 |
68 | let seaAttack = true
69 | let seaMovement = true
70 |
71 | func doLandAttack() {
72 | print("Amphibious Land Attack")
73 | }
74 | func doLandMovement() {
75 | print("Amphibious Land Move")
76 | }
77 | func doSeaAttack() {
78 | print("Amphibious Sea Attack")
79 | }
80 | func doSeaMovement() {
81 | print("Amphibious Sea Move")
82 | }
83 | }
84 |
85 |
86 | struct Transformer: LandVehicle, SeaVehicle, AirVehicle {
87 | var hitPoints = 75
88 | let landAttackRange = 7
89 | let seaAttackRange = 5
90 | let airAttackRange = 6
91 |
92 | let landAttack = true
93 | let landMovement = true
94 |
95 | let seaAttack = true
96 | let seaMovement = true
97 |
98 | let airAttack = true
99 | let airMovement = true
100 |
101 | func doLandAttack() {
102 | print("Transformer Land Attack")
103 | }
104 | func doLandMovement() {
105 | print("Transformer Land Move")
106 | }
107 | func doSeaAttack() {
108 | print("Transformer Sea Attack")
109 | }
110 | func doSeaMovement() {
111 | print("Transformer Sea Move")
112 | }
113 | func doAirAttack() {
114 | print("Transformer Sea Attack")
115 | }
116 | func doAirMovement() {
117 | print("Transformer Sea Move")
118 | }
119 | }
120 |
121 |
122 |
123 |
124 | var vehicles = [Vehicle]()
125 |
126 | var vh1 = Amphibious()
127 | var vh2 = Amphibious()
128 | var vh3 = Tank()
129 | var vh4 = Transformer()
130 |
131 | vehicles.append(vh1)
132 | vehicles.append(vh2)
133 | vehicles.append(vh3)
134 | vehicles.append(vh4)
135 |
136 |
137 | for (index, vehicle) in vehicles.enumerated() {
138 | if let Vehicle = vehicle as? AirVehicle {
139 | print("Vehicle at \(index) is Air")
140 | }
141 | if let Vehicle = vehicle as? LandVehicle {
142 | print("Vehicle at \(index) is Land")
143 | }
144 | if let Vehicle = vehicle as? SeaVehicle {
145 | print("Vehicle at \(index) is Sea")
146 | }
147 | }
148 |
149 |
150 | for (index, vehicle) in vehicles.enumerated() where vehicle is LandVehicle {
151 | let vh = vehicle as! LandVehicle
152 | if vh.landAttack {
153 | vh.doLandAttack()
154 | }
155 | if vh.landMovement {
156 | vh.doLandMovement()
157 | }
158 | }
159 |
160 |
161 |
162 | func takeHit(vehicle: inout T) {
163 | vehicle.takeHit(amount: 10)
164 | }
165 |
166 | var tank = Tank()
167 | takeHit(vehicle: &tank)
168 | print(tank.hitPointsRemaining())
169 |
--------------------------------------------------------------------------------
/Chapter06/PPO_Design.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/Bridge.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | protocol Message {
6 | var messageString: String {get set}
7 | init(messageString: String)
8 | func prepareMessage()
9 | }
10 |
11 | protocol Sender {
12 | func sendMessage(message: Message)
13 | }
14 |
15 | class PlainTextMessage: Message {
16 | var messageString: String
17 | required init(messageString: String) {
18 | self.messageString = messageString
19 | }
20 | func prepareMessage() {
21 | //Nothing to do
22 | }
23 | }
24 |
25 | class DESEncryptedMessage: Message {
26 | var messageString: String
27 | required init(messageString: String) {
28 | self.messageString = messageString
29 | }
30 | func prepareMessage() {
31 | // Encrypt message here
32 | self.messageString = "DES: " + self.messageString
33 | }
34 | }
35 |
36 | class EmailSender: Sender{
37 | func sendMessage(message: Message) {
38 | print("Sending through E-Mail:")
39 | print(" \(message.messageString)")
40 | }
41 | }
42 |
43 | class SMSSender: Sender {
44 | func sendMessage(message: Message) {
45 | print("Sending through SMS:")
46 | print(" \(message.messageString)")
47 | }
48 | }
49 |
50 | var myMessage = PlainTextMessage(messageString: "Plain Text Message")
51 | myMessage.prepareMessage()
52 | var sender = SMSSender()
53 | sender.sendMessage(message: myMessage)
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/Chapter07/Bridge.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/Bridge.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter07/Bridge.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter07/Bridge.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter07/Bridge2.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | protocol Message {
6 | var messageString: String {get set}
7 | init(messageString: String)
8 | func prepareMessage()
9 | }
10 |
11 | class PlainTextMessage: Message {
12 | var messageString: String
13 | required init(messageString: String) {
14 | self.messageString = messageString
15 | }
16 | func prepareMessage() {
17 | //Nothing to do
18 | }
19 | }
20 |
21 | protocol Sender {
22 | var message: Message? {get set}
23 | func sendMessage()
24 | func verifyMessage()
25 | }
26 |
27 | class EmailSender: Sender {
28 | var message: Message?
29 | func sendMessage() {
30 | print("Sending through E-Mail:")
31 | print("\(message!.messageString)")
32 | }
33 | func verifyMessage() {
34 | print("Verifying E-Mail message")
35 | }
36 | }
37 |
38 | class SMSSender: Sender {
39 | var message: Message?
40 | func sendMessage() {
41 | print("Sending through SMS:")
42 | print(" \(message!.messageString)")
43 | }
44 | func verifyMessage() {
45 | print("Verifying SMS message")
46 | }
47 | }
48 |
49 |
50 | var myMessage = PlainTextMessage(messageString: "Plain Text Message")
51 | myMessage.prepareMessage()
52 | var sender = SMSSender()
53 | sender.message = myMessage
54 | sender.verifyMessage()
55 | sender.sendMessage()
56 |
57 |
58 | struct MessageingBridge {
59 | static func sendMessage(message: Message, sender: Sender)
60 | {
61 | var sender = sender
62 | message.prepareMessage()
63 | sender.message = message
64 | sender.verifyMessage()
65 | sender.sendMessage()
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/Chapter07/Bridge2.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/Bridge2.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter07/Bridge2.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter07/Bridge2.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter07/Builder.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | struct BurgerOld {
6 | var name: String
7 | var patties: Int
8 | var bacon: Bool
9 | var cheese: Bool
10 | var pickles: Bool
11 | var ketchup: Bool
12 | var mustard: Bool
13 | var lettuce: Bool
14 | var tomato: Bool
15 | init(name: String, patties: Int, bacon: Bool, cheese: Bool, pickles: Bool,ketchup: Bool,mustard:
16 | Bool,lettuce: Bool,tomato: Bool) {
17 | self.name = name
18 | self.patties = patties
19 | self.bacon = bacon
20 | self.cheese = cheese
21 | self.pickles = pickles
22 | self.ketchup = ketchup
23 | self.mustard = mustard
24 | self.lettuce = lettuce
25 | self.tomato = tomato
26 | }
27 | }
28 |
29 | // Create Hamburger
30 | var burgerOld = BurgerOld(name: "Hamburger", patties: 1, bacon:false, cheese: false, pickles: false, ketchup: false, mustard:false, lettuce: false, tomato: false)
31 |
32 | // Create Cheeseburger
33 | var cheeseburgerOld = BurgerOld(name: "Cheeseburger", patties: 1, bacon:false, cheese: false, pickles: false, ketchup: false, mustard: false, lettuce: false, tomato: false)
34 |
35 |
36 | protocol BurgerBuilder {
37 | var name: String {get}
38 | var patties: Int {get}
39 | var bacon: Bool {get}
40 | var cheese: Bool {get}
41 | var pickles: Bool {get}
42 | var ketchup: Bool {get}
43 | var mustard: Bool {get}
44 | var lettuce: Bool {get}
45 | var tomato: Bool {get}
46 | }
47 |
48 | struct HamBurgerBuilder: BurgerBuilder {
49 | let name = "Burger"
50 | let patties = 1
51 | let bacon = false
52 | let cheese = false
53 | let pickles = true
54 | let ketchup = true
55 | let mustard = true
56 | let lettuce = false
57 | let tomato = false
58 | }
59 |
60 | struct CheeseBurgerBuilder: BurgerBuilder {
61 | let name = "CheeseBurger"
62 | let patties = 1
63 | let bacon = false
64 | let cheese = true
65 | let pickles = true
66 | let ketchup = true
67 | let mustard = true
68 | let lettuce = false
69 | let tomato = false
70 | }
71 |
72 | struct Burger {
73 | var name: String
74 | var patties: Int
75 | var bacon: Bool
76 | var cheese: Bool
77 | var pickles: Bool
78 | var ketchup: Bool
79 | var mustard: Bool
80 | var lettuce: Bool
81 | var tomato: Bool
82 |
83 | init(builder: BurgerBuilder) {
84 | self.name = builder.name
85 | self.patties = builder.patties
86 | self.bacon = builder.bacon
87 | self.cheese = builder.cheese
88 | self.pickles = builder.pickles
89 | self.ketchup = builder.ketchup
90 | self.mustard = builder.mustard
91 | self.lettuce = builder.lettuce
92 | self.tomato = builder.tomato
93 | }
94 |
95 | func showBurger() {
96 | print("Name:\(name)")
97 | print("Patties: \(patties)")
98 | print("Bacon:\(bacon)")
99 | print("Cheese:\(cheese)")
100 | print("Pickles: \(pickles)")
101 | print("Ketchup: \(ketchup)")
102 | print("Mustard: \(mustard)")
103 | print("Lettuce: \(lettuce)")
104 | print("Tomato:\(tomato)")
105 | }
106 | }
107 |
108 |
109 | // Create Hamburger
110 | var myBurger = Burger(builder: HamBurgerBuilder())
111 | myBurger.showBurger()
112 |
113 | // Create Cheeseburger with tomatos
114 | var myCheeseBurgerBuilder = CheeseBurgerBuilder()
115 | var myCheeseBurger = Burger(builder: myCheeseBurgerBuilder)
116 |
117 | // Lets hold the tomatos
118 | myCheeseBurger.tomato = false
119 | myCheeseBurger.showBurger()
120 |
121 | struct BurgerBuilder1 {
122 | var name = "Burger"
123 | var patties = 1
124 | var bacon = false
125 | var cheese = false
126 | var pickles = true
127 | var ketchup = true
128 | var mustard = true
129 | var lettuce = false
130 | var tomato = false
131 |
132 | mutating func setPatties(choice: Int) {self.patties = choice}
133 | mutating func setBacon(choice: Bool) {self.bacon = choice}
134 | mutating func setCheese(choice: Bool) {self.cheese = choice}
135 | mutating func setPickles(choice: Bool) {self.pickles = choice}
136 | mutating func setKetchup(choice: Bool) {self.ketchup = choice}
137 | mutating func setMustard(choice: Bool) {self.mustard = choice}
138 | mutating func setLettuce(choice: Bool) {self.lettuce = choice}
139 | mutating func setTomato(choice: Bool) {self.tomato = choice}
140 |
141 | func buildBurgerOld(name: String) -> BurgerOld {
142 | return BurgerOld(name: name, patties: self.patties, bacon: self.bacon, cheese: self.cheese, pickles: self.pickles, ketchup: self.ketchup, mustard: self.mustard, lettuce: self.lettuce, tomato: self.tomato)
143 | }
144 | }
145 |
146 | var burgerBuilder = BurgerBuilder1()
147 | burgerBuilder.setCheese(choice: true)
148 | burgerBuilder.setBacon(choice: true)
149 | var jonBurger = burgerBuilder.buildBurgerOld(name: "Jon's Burger")
150 |
151 |
152 |
--------------------------------------------------------------------------------
/Chapter07/Builder.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/CommandNew.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | protocol MathCommand {
6 | func execute(num1: Double, num2: Double) -> Double
7 | }
8 |
9 | struct AdditionCommand: MathCommand {
10 | func execute(num1: Double, num2: Double) -> Double {
11 | return num1 + num2
12 | }
13 | }
14 |
15 | struct SubtractionCommand: MathCommand {
16 | func execute(num1: Double, num2: Double) -> Double {
17 | return num1 - num2
18 | }
19 | }
20 |
21 | struct MultiplicationCommand: MathCommand {
22 | func execute(num1: Double, num2: Double) -> Double {
23 | return num1 * num2
24 | }
25 | }
26 |
27 | struct DivisionCommand: MathCommand {
28 | func execute(num1: Double, num2: Double) -> Double {
29 | return num1 / num2
30 | }
31 | }
32 |
33 | struct Calculator {
34 | func performCalculation(num1: Double, num2: Double, command: MathCommand) -> Double{
35 | return command.execute(num1: num1, num2: num2)
36 | }
37 | }
38 | var calc = Calculator()
39 | var startValue = calc.performCalculation(num1: 25, num2: 10, command: SubtractionCommand())
40 | var answer = calc.performCalculation(num1: startValue, num2: 5, command: MultiplicationCommand())
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Chapter07/CommandNew.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/Facade.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | struct Hotel {
6 | //Information about hotel room
7 | }
8 |
9 | struct HotelBooking {
10 | static func getHotelNameForDates(to: NSDate, from: NSDate) -> [Hotel]? {
11 | let hotels = [Hotel]()
12 | //logic to get hotels return hotels
13 | return hotels
14 | }
15 |
16 | static func bookHotel(hotel: Hotel) {
17 | // logic to reserve hotel room
18 | }
19 | }
20 |
21 | struct Flight {
22 | //Information about flights
23 | }
24 |
25 | struct FlightBooking {
26 | static func getFlightNameForDates(to: NSDate, from: NSDate) -> [Flight]? {
27 | let flights = [Flight]()
28 | //logic to get flights return flights
29 | return flights
30 | }
31 |
32 | static func bookFlight(fight: Flight) {
33 | // logic to reserve flight
34 | }
35 | }
36 |
37 |
38 | struct RentalCar {
39 | //Information about rental cars
40 | }
41 |
42 |
43 | struct TravelFacade {
44 |
45 | var hotels: [Hotel]?
46 | var flights: [Flight]?
47 | var cars: [RentalCar]?
48 |
49 | init(to: NSDate, from: NSDate) {
50 | hotels = HotelBooking.getHotelNameForDates(to: to, from: from)
51 | flights = FlightBooking.getFlightNameForDates(to: to, from:from)
52 | cars = RentalCarBooking.getRentalCarNameForDates(to: to, from: from)
53 | }
54 |
55 | func bookTrip(hotel: Hotel, flight: Flight, rentalCar: RentalCar) {
56 | HotelBooking.bookHotel(hotel: hotel)
57 | FlightBooking.bookFlight(flight: flight)
58 | RentalCarBooking.bookRentalCar(rentalCar: rentalCar)
59 | }
60 | }
61 |
62 |
63 | struct RentalCarBooking {
64 | static func getRentalCarNameForDates(to: NSDate, from: NSDate)
65 | -> [RentalCar]? {
66 | let cars = [RentalCar]()
67 | //logic to get flights return cars
68 | return cars
69 | }
70 |
71 | static func bookRentalCar(rentalCar: RentalCar) {
72 | // logic to reserve rental car
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Chapter07/Facade.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/FactoryMethod.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | protocol TextValidation {
6 | var regExFindMatchString: String {get}
7 | var validationMessage: String {get}
8 | }
9 |
10 | extension TextValidation {
11 | var regExMatchingString: String {
12 | get {
13 | return regExFindMatchString + "$"
14 | }
15 | }
16 |
17 | func validateString(str: String) -> Bool {
18 | if let _ = str.range(of: regExMatchingString, options: .regularExpression) {
19 | return true
20 | } else {
21 | return false
22 | }
23 | }
24 | func getMatchingString(str: String) -> String? {
25 | if let newMatch = str.range(of: regExFindMatchString, options: .regularExpression) {
26 | return String(str[newMatch])
27 | } else {
28 | return nil
29 | }
30 | }
31 | }
32 |
33 | class AlphaValidation: TextValidation {
34 | static let sharedInstance = AlphaValidation()
35 | private init(){}
36 | let regExFindMatchString = "^[a-zA-Z]{0,10}"
37 | let validationMessage = "Can only contain Alpha characters"
38 | }
39 |
40 | class AlphaNumericValidation: TextValidation {
41 | static let sharedInstance = AlphaNumericValidation()
42 | private init(){}
43 | let regExFindMatchString = "^[a-zA-Z0-9]{0,10}"
44 | let validationMessage = "Can only contain Alpha Numeric characters"
45 | }
46 |
47 | class NumericValidation: TextValidation {
48 | static let sharedInstance = NumericValidation()
49 | private init(){}
50 | let regExFindMatchString = "^[0-9]{0,10}"
51 | let validationMessage = "Display Name can contain a maximum of 15 Alphanumeric Characters"
52 | }
53 |
54 | func getValidator(alphaCharacters: Bool, numericCharacters: Bool) -> TextValidation? {
55 | if alphaCharacters && numericCharacters {
56 | return AlphaNumericValidation.sharedInstance
57 | } else if alphaCharacters && !numericCharacters {
58 | return AlphaValidation.sharedInstance
59 | } else if !alphaCharacters && numericCharacters {
60 | return NumericValidation.sharedInstance
61 | } else {
62 | return nil
63 | }
64 | }
65 |
66 | var str = "abc123"
67 | var validator1 = getValidator(alphaCharacters: true, numericCharacters: false)
68 | print("String validated: \(validator1?.validateString(str: str))")
69 |
70 | var validator2 = getValidator(alphaCharacters: true, numericCharacters: true)
71 | print("String validated: \(validator2?.validateString(str: str))")
72 |
73 |
--------------------------------------------------------------------------------
/Chapter07/FactoryMethod.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/Proxy.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter07/Proxy.7z
--------------------------------------------------------------------------------
/Chapter07/Singleton.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 |
6 | class MySingleton {
7 | static let sharedInstance = MySingleton()
8 | var number = 0
9 | private init() {}
10 |
11 | }
12 |
13 | var singleA = MySingleton.sharedInstance
14 | var singleB = MySingleton.sharedInstance
15 | var singleC = MySingleton.sharedInstance
16 |
17 | singleB.number = 2
18 | print(singleA.number)
19 | print(singleB.number)
20 | print(singleC.number)
21 |
22 | singleC.number = 3
23 | print(singleA.number)
24 | print(singleB.number)
25 | print(singleC.number)
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Chapter07/Singleton.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/observer.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | let NCNAME = "Notification Name"
6 |
7 | class PostType {
8 | let nc = NotificationCenter.default
9 | func post() {
10 | nc.post(name: Notification.Name(rawValue: NCNAME), object: nil)
11 | }
12 | }
13 |
14 | class ObserverType {
15 | let nc = NotificationCenter.default
16 | init() {
17 | nc.addObserver(self, selector:
18 | #selector(receiveNotification(notification:)), name: Notification.Name(rawValue: NCNAME), object: nil)
19 | }
20 | @objc func receiveNotification(notification: Notification) {
21 | print("Notification Received")
22 | }
23 | }
24 |
25 | var postType = PostType()
26 | var observerType = ObserverType()
27 | postType.post()
28 |
29 |
30 |
31 |
32 | protocol ZombieObserver {
33 | func turnLeft()
34 | func turnRight()
35 | func seesUs()
36 | }
37 |
38 | class MyObserver: ZombieObserver {
39 | func turnLeft() {
40 | print("Zombie turned left, we move right")
41 | }
42 | func turnRight() {
43 | print("Zombie turned right, we move left")
44 | }
45 | func seesUs() {
46 | print("Zombie sees us, RUN!!!!")
47 | }
48 | }
49 |
50 | struct Zombie {
51 | var observer: ZombieObserver
52 |
53 | func turnZombieLeft() {
54 | //Code to turn left
55 | //Notify observer
56 | observer.turnLeft()
57 | }
58 | func turnZombieRight() {
59 | //Code to turn right
60 | //Notify observer
61 | observer.turnRight()
62 | }
63 | func spotHuman() {
64 | //Code to lock onto a human
65 | //Notify observer
66 | observer.seesUs()
67 | }
68 | }
69 | var observer = MyObserver()
70 | var zombie = Zombie(observer: observer)
71 |
72 | zombie.turnZombieLeft()
73 | zombie.spotHuman()
74 |
75 |
76 |
77 | protocol PropertyObserver{
78 | func propertyChanged(propertyName: String, newValue: Any)
79 | }
80 |
81 | class MyObserverType: PropertyObserver {
82 | func propertyChanged(propertyName: String, newValue: Any) {
83 | print("----changed----")
84 | print("Property Name: \(propertyName)")
85 | print("New Value: \(newValue)")
86 | }
87 | }
88 | struct PropertyObserverTest {
89 | var observer: PropertyObserver
90 | var property1: String {
91 | didSet{
92 | observer.propertyChanged(propertyName: "property1", newValue: property1)
93 | }
94 | willSet(newValue) {
95 | print("Property Changing")
96 | }
97 | }
98 | }
99 |
100 |
--------------------------------------------------------------------------------
/Chapter07/observer.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter07/strategy.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | protocol CompressionStrategy {
6 | func compressFiles(filePaths: [String])
7 | }
8 |
9 | struct ZipCompressionStrategy: CompressionStrategy {
10 | func compressFiles(filePaths: [String]) {
11 | print("Using Zip Compression")
12 | }
13 | }
14 |
15 | struct RarCompressionStrategy: CompressionStrategy {
16 | func compressFiles(filePaths: [String]) {
17 | print("Using RAR Compression")
18 | }
19 | }
20 |
21 | struct CompressContent {
22 | var strategy: CompressionStrategy
23 | func compressFiles(filePaths: [String]) {
24 | self.strategy.compressFiles(filePaths: filePaths)
25 | }
26 | }
27 |
28 | var filePaths = ["file1.txt", "file2.txt"]
29 | var zip = ZipCompressionStrategy()
30 | var rar = RarCompressionStrategy()
31 |
32 | var compress = CompressContent(strategy: zip)
33 | compress.compressFiles(filePaths: filePaths)
34 |
35 | compress.strategy = rar
36 | compress.compressFiles(filePaths: filePaths)
37 |
--------------------------------------------------------------------------------
/Chapter07/strategy.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter08/DataAccess.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | enum Positions: String {
6 | case pitcher = "Pitcher"
7 | case catcher = "Catcher"
8 | case firstBase = "First Base"
9 | case secondBase = "Second Base"
10 | case thirdBase = "Third Base"
11 | case shortstop = "Shortstop"
12 | case leftField = "Left Field"
13 | case centerField = "Center Field"
14 | case rightField = "Right field"
15 | case designatedHitter = "Designated Hitter"
16 | }
17 |
18 | enum DataAccessError: Error {
19 | case datastoreConnectionError
20 | case insertError
21 | case deleteError
22 | case searchError
23 | case nilInData
24 | }
25 |
26 | /*** Data Model Layer ***/
27 | typealias TeamData = ( teamId: Int64?, city: String?, nickName: String?, abbreviation: String?)
28 |
29 | typealias PlayerData = ( playerId: Int64?, firstName: String?, lastName: String?, number: Int?, teamId: Int64?, position: Positions?)
30 |
31 |
32 | /*** Data Helper Layer ***/
33 | protocol DataHelper {
34 | associatedtype T
35 | static func insert(_ item: T) throws -> Int64
36 | static func delete(_ item: T) throws -> Void
37 | static func findAll() throws -> [T]?
38 | }
39 |
40 | struct TeamDataHelper: DataHelper {
41 | typealias T = TeamData
42 | static var teamData: [T] = []
43 |
44 | static func insert(_ item: T) throws -> Int64 {
45 | guard item.teamId != nil && item.city != nil && item.nickName != nil && item.abbreviation != nil else {
46 | throw DataAccessError.nilInData
47 | }
48 |
49 | teamData.append(item)
50 | return item.teamId!
51 | }
52 | static func delete (_ item: T) throws -> Void {
53 | guard let id = item.teamId else {
54 | throw DataAccessError.nilInData
55 | }
56 | let teamArray = teamData
57 | for (index, team) in teamArray.enumerated() where team.teamId == id {
58 | teamData.remove(at: index)
59 | return
60 | }
61 | throw DataAccessError.deleteError
62 | }
63 |
64 | static func findAll() throws -> [T]? {
65 | return teamData
66 | }
67 | static func find(_ id: Int64) throws -> T? {
68 | for team in teamData where team.teamId == id {
69 | return team
70 | }
71 | return nil
72 | }
73 |
74 | }
75 |
76 |
77 | struct PlayerDataHelper: DataHelper {
78 | typealias T = PlayerData
79 | static var playerData: [T] = []
80 |
81 | static func insert(_ item: T) throws -> Int64 {
82 | guard item.playerId != nil && item.firstName != nil && item.lastName != nil && item.teamId != nil && item.position != nil else {
83 | throw DataAccessError.nilInData
84 | }
85 | playerData.append(item)
86 | return item.playerId!
87 | }
88 | static func delete (_ item: T) throws -> Void {
89 | guard let id = item.playerId else {
90 | throw DataAccessError.deleteError
91 | }
92 | let playerArray = playerData
93 | for (index, player) in playerArray.enumerated() where player.playerId == id {
94 | playerData.remove(at: index)
95 | }
96 | }
97 |
98 | static func findAll() throws -> [T]? {
99 | return playerData
100 | }
101 | static func find(_ id: Int64) throws -> T? {
102 | for player in playerData where player.playerId == id {
103 | return player
104 | }
105 | return nil
106 | }
107 |
108 | }
109 |
110 |
111 | /*** Bridge Layer ***/
112 | struct Team {
113 | var teamId: Int64?
114 | var city: String?
115 | var nickName:String?
116 | var abbreviation:String?
117 |
118 | }
119 |
120 | struct Player {
121 | var playerId: Int64?
122 | var firstName: String?
123 | var lastName: String?
124 | var number: Int?
125 | var teamId: Int64? {
126 | didSet {
127 | if let t = try? TeamBridge.retrieve(teamId!) {
128 | team = t
129 | }
130 | }
131 | }
132 | var position: Positions?
133 | var team: Team?
134 | init(playerId: Int64?, firstName: String?, lastName: String?, number: Int?, teamId: Int64?, position: Positions?) {
135 | self.playerId = playerId
136 | self.firstName = firstName
137 | self.lastName = lastName
138 | self.number = number
139 | self.teamId = teamId
140 | self.position = position
141 | if let
142 | id = self.teamId {
143 | if let t = try? TeamBridge.retrieve(id) {
144 | team = t
145 | }
146 | }
147 | }
148 | }
149 |
150 | struct TeamBridge {
151 | static func save(_ team:inout Team) throws {
152 | let teamData = toTeamData(team)
153 | let id = try TeamDataHelper.insert(teamData)
154 | team.teamId = id
155 | }
156 | static func delete(_ team:Team) throws {
157 | let teamData = toTeamData(team)
158 | try TeamDataHelper.delete(teamData)
159 | }
160 | static func retrieve(_ id: Int64) throws -> Team? {
161 | if let t = try TeamDataHelper.find(id) {
162 | return toTeam(t)
163 | }
164 | return nil
165 | }
166 | static func toTeamData(_ team: Team) -> TeamData {
167 | return TeamData(teamId: team.teamId , city: team.city, nickName: team.nickName, abbreviation: team.abbreviation)
168 | }
169 | static func toTeam(_ teamData: TeamData) -> Team {
170 | return Team(teamId: teamData.teamId, city: teamData.city, nickName: teamData.nickName, abbreviation: teamData.abbreviation)
171 | }
172 | }
173 |
174 | struct PlayerBridge {
175 | static func save(_ player:inout Player) throws {
176 | let playerData = toPlayerData(player)
177 | let id = try PlayerDataHelper.insert(playerData)
178 | player.playerId = id
179 | }
180 | static func delete(_ player:Player) throws {
181 | let playerData = toPlayerData(player)
182 | try PlayerDataHelper.delete(playerData)
183 | }
184 | static func retrieve(_ id: Int64) throws -> Player? {
185 | if let p = try PlayerDataHelper.find(id) {
186 | return toPlayer(p)
187 | }
188 | return nil
189 | }
190 | static func toPlayerData(_ player: Player) -> PlayerData {
191 | return PlayerData(playerId: player.playerId, firstName:
192 | player.firstName, lastName: player.lastName,
193 | number: player.number, teamId: player.teamId,
194 | position: player.position)
195 | }
196 | static func toPlayer(_ playerData: PlayerData) -> Player {
197 | return Player(playerId: playerData.playerId, firstName:
198 | playerData.firstName, lastName: playerData.lastName, number:
199 | playerData.number, teamId: playerData.teamId, position:
200 | playerData.position)
201 | }
202 | }
203 |
204 | var bos = Team( teamId: 0, city: "Boston",
205 | nickName: "Red Sox", abbreviation: "BOS")
206 |
207 | try? TeamBridge.save(&bos)
208 | var ortiz = Player(
209 | playerId: 0,firstName: "David", lastName: "Ortiz", number: 34,
210 | teamId: bos.teamId, position: Positions.designatedHitter)
211 |
212 | try? PlayerBridge.save(&ortiz)
213 |
214 | if let team = try? TeamBridge.retrieve(0) {
215 | print("--- \(team?.city)")
216 | }
217 |
218 | if let player = try? PlayerBridge.retrieve(0) {
219 | print("---- \(player?.firstName) \(player?.lastName) plays for (player?.team?.city)")
220 | }
221 |
222 |
--------------------------------------------------------------------------------
/Chapter08/DataAccess.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter08/DataAccess.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter08/DataAccess.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter08/DataAccess.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter08/Logging.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | protocol LoggerProfile {
6 | var loggerProfileId: String {get}
7 | func writeLog(level: String, message: String)
8 | }
9 |
10 | extension LoggerProfile {
11 | func getCurrentDateString() -> String{ let date = Date()
12 | let dateFormatter = DateFormatter()
13 | dateFormatter.dateFormat = "MM/dd/yyyy hh:mm"
14 | return dateFormatter.string(from: date)
15 | }
16 | }
17 |
18 | struct LoggerNull: LoggerProfile {
19 | let loggerProfileId = "hoffman.jon.logger.null"
20 | func writeLog(level: String, message: String) {
21 | // Do nothing
22 | }
23 | }
24 |
25 | struct LoggerConsole: LoggerProfile {
26 | let loggerProfileId = "hoffman.jon.logger.console"
27 | func writeLog(level: String, message: String) {
28 | let now = getCurrentDateString()
29 | print("\(now): \(level) - \(message)")
30 | }
31 | }
32 |
33 | enum LogLevels: String {
34 | case Fatal
35 | case Error
36 | case Warn
37 | case Debug
38 | case Info
39 |
40 | static let allValues = [Fatal, Error, Warn, Debug, Info]
41 | }
42 |
43 | protocol Logger {
44 | static var loggers: [LogLevels:[LoggerProfile]] {get set}
45 | static func writeLog(logLevel: LogLevels, message: String)
46 | }
47 |
48 | extension Logger {
49 |
50 | static func logLevelContainsProfile(logLevel: LogLevels, loggerProfile: LoggerProfile) -> Bool {
51 | if let logProfiles = loggers[logLevel] {
52 | for logProfile in logProfiles where
53 | logProfile.loggerProfileId == loggerProfile.loggerProfileId {
54 | return true
55 | }
56 | }
57 | return false
58 | }
59 |
60 |
61 | static func setLogLevel(logLevel: LogLevels, loggerProfile: LoggerProfile) {
62 |
63 | if let _ = loggers[logLevel] {
64 | if !logLevelContainsProfile(logLevel: logLevel, loggerProfile: loggerProfile) {
65 | loggers[logLevel]?.append(loggerProfile)
66 | }
67 | } else {
68 | var a = [LoggerProfile]()
69 | a.append(loggerProfile)
70 |
71 | loggers[logLevel] = a
72 | }
73 | }
74 |
75 | static func addLogProfileToAllLevels( defaultLoggerProfile: LoggerProfile) {
76 | for level in LogLevels.allValues {
77 | setLogLevel(logLevel: level, loggerProfile: defaultLoggerProfile)
78 | }
79 | }
80 |
81 | static func removeLogProfileFromLevel(logLevel: LogLevels, loggerProfile:LoggerProfile) {
82 | if var logProfiles = loggers[logLevel] {
83 | if let index = logProfiles.index(where:
84 | {$0.loggerProfileId == loggerProfile.loggerProfileId}) {
85 | logProfiles.remove(at: index)
86 | }
87 | loggers[logLevel] = logProfiles
88 | }
89 | }
90 |
91 | static func removeLogProfileFromAllLevels(loggerProfile:LoggerProfile) {
92 | for level in LogLevels.allValues {
93 | removeLogProfileFromLevel(logLevel: level, loggerProfile: loggerProfile)
94 | }
95 | }
96 |
97 | static func hasLoggerForLevel(logLevel: LogLevels) -> Bool {
98 | guard let _ = loggers[logLevel] else {
99 | return false
100 | }
101 | return true
102 | }
103 | }
104 |
105 | struct MyLogger: Logger {
106 | static var loggers = [LogLevels:[LoggerProfile]]()
107 | static func writeLog(logLevel: LogLevels, message: String) {
108 | guard hasLoggerForLevel(logLevel: logLevel) else {
109 | print("No logger")
110 | return
111 | }
112 | if let logProfiles = loggers[logLevel] {
113 |
114 | for logProfile in logProfiles {
115 | logProfile.writeLog(level: logLevel.rawValue, message: message)
116 | }
117 | }
118 | }
119 | }
120 |
121 | MyLogger.addLogProfileToAllLevels(defaultLoggerProfile: LoggerConsole())
122 | MyLogger.writeLog(logLevel: LogLevels.Debug, message: "Debug Message 1")
123 |
124 | MyLogger.writeLog(logLevel: LogLevels.Error, message: "Error Message 1")
125 |
126 |
--------------------------------------------------------------------------------
/Chapter08/Logging.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter08/Logging.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter08/Logging.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/Swift-4-Protocol-Oriented-Programming-Third-Edition/e2f3dcee5a8bede76a6f2c88ff8bae488461fed2/Chapter08/Logging.playground/playground.xcworkspace/xcuserdata/jonhoffman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Packt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift 4 Protocol-Oriented Programming - Third Edition
2 | This is the code repository for [Swift 4 Protocol-Oriented Programming - Third Edition](https://www.packtpub.com/web-development/swift-protocol-oriented-programming-third-edition?utm_source=github&utm_medium=repository&utm_campaign=9781788470032), published by [Packt](https://www.packtpub.com/?utm_source=github). It contains all the supporting project files necessary to work through the book from start to finish.
3 | ## About the Book
4 | This book will help you understand the differences between object-oriented programming and protocol-oriented programming. It will demonstrate how to work with protocol-oriented programming using real-world use cases. You will gain a solid knowledge of the various types that can be used in Swift and the differences between value and reference types. You will be taught how protocol-oriented programming techniques can be used to develop very flexible and easy-to-maintain code.
5 | ## Instructions and Navigation
6 | All of the code is organized into folders. Each folder starts with a number followed by the application name. For example, Chapter02.
7 |
8 |
9 |
10 | The code will look like the following:
11 | ```
12 | protocol ZombieObserver {
13 | func turnLeft()
14 | func turnRight()
15 | func seesUs()
16 | }
17 | ```
18 |
19 | To follow along with the examples in this book, the reader will need to have an Apple computer with OS X 10.13 or higher installed. They will also need to install XCode version 9.0 or higher with Swift version 4 or higher. The reader should possess at least basic knowledge of the Swift programming language.
20 |
21 | ## Related Products
22 | * [Mastering Swift 4 - Fourth Edition](https://www.packtpub.com/application-development/mastering-swift-4-fourth-edition?utm_source=github&utm_medium=repository&utm_campaign=9781788477802)
23 |
24 | * [Swift 4 Programming Cookbook](https://www.packtpub.com/application-development/swift-4-programming-cookbook?utm_source=github&utm_medium=repository&utm_campaign=9781786460899)
25 |
26 | * [Swift: Mastering the Core Concepts [Integrated Course]](https://www.packtpub.com/application-development/swift-mastering-core-concepts-integrated-course?utm_source=github&utm_medium=repository&utm_campaign=9781788393225)
27 |
28 |
--------------------------------------------------------------------------------