├── .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 | --------------------------------------------------------------------------------