├── Chapter01 └── Playgrounds │ ├── .DS_Store │ └── Ch01-Introduction.playground │ ├── Pages │ ├── ARC.xcplaygroundpage │ │ └── Contents.swift │ ├── AnyAnyObject.xcplaygroundpage │ │ └── Contents.swift │ ├── Collections.xcplaygroundpage │ │ └── Contents.swift │ ├── ControlFlows.xcplaygroundpage │ │ └── Contents.swift │ ├── DeclarativeImperative.xcplaygroundpage │ │ └── Contents.swift │ ├── Enumerations.xcplaygroundpage │ │ └── Contents.swift │ ├── ErrorHandling.xcplaygroundpage │ │ └── Contents.swift │ ├── ExtensionsAndProtocols.xcplaygroundpage │ │ └── Contents.swift │ ├── Functions.xcplaygroundpage │ │ └── Contents.swift │ ├── Generics.xcplaygroundpage │ │ └── Contents.swift │ ├── Immutability.xcplaygroundpage │ │ └── Contents.swift │ ├── Initialization.xcplaygroundpage │ │ └── Contents.swift │ ├── LazyEvaluation.xcplaygroundpage │ │ └── Contents.swift │ ├── MapFilterReduce.xcplaygroundpage │ │ └── Contents.swift │ ├── Methods.xcplaygroundpage │ │ └── Contents.swift │ ├── ModernSyntax.xcplaygroundpage │ │ └── Contents.swift │ ├── NestedTypes.xcplaygroundpage │ │ └── Contents.swift │ ├── Optionals.xcplaygroundpage │ │ └── Contents.swift │ ├── Protocols.xcplaygroundpage │ │ └── Contents.swift │ ├── Strings.xcplaygroundpage │ │ └── Contents.swift │ ├── Subscripts.xcplaygroundpage │ │ └── Contents.swift │ ├── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ ├── Tuples.xcplaygroundpage │ │ └── Contents.swift │ └── Types.xcplaygroundpage │ │ └── Contents.swift │ ├── Resources │ └── Ch01-Introduction.playground │ │ ├── Pages │ │ ├── ARC.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── AnyAnyObject.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Collections.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── ControlFlows.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── DeclarativeImperative.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Enumerations.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── ErrorHandling.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── ExtensionsAndProtocols.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Functions.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Generics.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Immutability.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Initialization.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── LazyEvaluation.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── MapFilterReduce.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Methods.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── ModernSyntax.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── NestedTypes.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Optionals.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Protocols.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Strings.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Subscripts.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── TableOfContents.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Tuples.xcplaygroundpage │ │ │ └── Contents.swift │ │ └── Types.xcplaygroundpage │ │ │ └── Contents.swift │ │ ├── Resources │ │ └── Ch01-Introduction.playground │ │ │ ├── Pages │ │ │ └── ARC.xcplaygroundpage │ │ │ │ └── Contents.swift │ │ │ └── contents.xcplayground │ │ └── contents.xcplayground │ ├── contents.xcplayground │ └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── nayefa.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Chapter02 └── Playgrounds │ ├── .DS_Store │ └── Ch02-FuncsClosures.playground │ ├── Pages │ ├── CapturingValues.xcplaygroundpage │ │ └── Contents.swift │ ├── Closures.xcplaygroundpage │ │ └── Contents.swift │ ├── Definition.xcplaygroundpage │ │ └── Contents.swift │ ├── FirstClassFunctions.xcplaygroundpage │ │ └── Contents.swift │ ├── FunctionComposition.xcplaygroundpage │ │ └── Contents.swift │ ├── FunctionCurrying.xcplaygroundpage │ │ └── Contents.swift │ ├── FunctionTypes.xcplaygroundpage │ │ └── Contents.swift │ ├── HigherOrderFunctions.xcplaygroundpage │ │ └── Contents.swift │ ├── Memoization.xcplaygroundpage │ │ └── Contents.swift │ ├── NestedFunctions.xcplaygroundpage │ │ └── Contents.swift │ ├── Recursion.xcplaygroundpage │ │ └── Contents.swift │ ├── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ └── TailRecursion.xcplaygroundpage │ │ └── Contents.swift │ └── contents.xcplayground ├── Chapter03 └── Playgrounds │ ├── .DS_Store │ └── Ch03-Types.playground │ ├── Pages │ ├── Copying.xcplaygroundpage │ │ └── Contents.swift │ ├── CopyingReferenceTypes.xcplaygroundpage │ │ └── Contents.swift │ ├── EqualityVsIdentity.xcplaygroundpage │ │ └── Contents.swift │ ├── EquatableComparable.xcplaygroundpage │ │ └── Contents.swift │ ├── MixingValueReferenceTypes.xcplaygroundpage │ │ └── Contents.swift │ ├── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ ├── TypeCheckingCasting.xcplaygroundpage │ │ └── Contents.swift │ └── ValueVsReferenceTypes.xcplaygroundpage │ │ └── Contents.swift │ └── contents.xcplayground ├── Chapter04 └── Playgrounds │ ├── .DS_Store │ └── Ch04-EnumsPatternMatching.playground │ ├── Pages │ ├── AlgebraicDataTypes.xcplaygroundpage │ │ └── Contents.swift │ ├── Definition.xcplaygroundpage │ │ └── Contents.swift │ ├── NestingContaining.xcplaygroundpage │ │ └── Contents.swift │ ├── PatternMatching.xcplaygroundpage │ │ └── Contents.swift │ ├── Patterns.xcplaygroundpage │ │ └── Contents.swift │ └── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ └── contents.xcplayground ├── Chapter05 └── Playgrounds │ ├── .DS_Store │ └── Ch05-Generics.playground │ ├── Pages │ ├── AssociatedTypeProtocols.xcplaygroundpage │ │ └── Contents.swift │ ├── Definition.xcplaygroundpage │ │ └── Contents.swift │ ├── ExtendingGenericTypes.xcplaygroundpage │ │ └── Contents.swift │ ├── GenericDataStructures.xcplaygroundpage │ │ └── Contents.swift │ ├── SubclassingGenericClasses.xcplaygroundpage │ │ └── Contents.swift │ ├── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ └── TypeConstraints.xcplaygroundpage │ │ └── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── nayefa.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Chapter06 └── Playgrounds │ ├── .DS_Store │ └── Ch06-MapFilterReduce.playground │ ├── Pages │ ├── Apply.xcplaygroundpage │ │ └── Contents.swift │ ├── ChainingHigherOrderFuncs.xcplaygroundpage │ │ └── Contents.swift │ ├── Examples.xcplaygroundpage │ │ └── Contents.swift │ ├── Filter.xcplaygroundpage │ │ └── Contents.swift │ ├── FlatMap.xcplaygroundpage │ │ └── Contents.swift │ ├── Higher-KindedTypes.xcplaygroundpage │ │ └── Contents.swift │ ├── Join.xcplaygroundpage │ │ └── Contents.swift │ ├── Joined.xcplaygroundpage │ │ └── Contents.swift │ ├── Map.xcplaygroundpage │ │ └── Contents.swift │ ├── Reduce.xcplaygroundpage │ │ └── Contents.swift │ ├── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ └── Zip.xcplaygroundpage │ │ └── Contents.swift │ └── contents.xcplayground ├── Chapter07 └── Playgrounds │ ├── .DS_Store │ └── Ch07-Optionals.playground │ ├── Pages │ ├── Definition.xcplaygroundpage │ │ └── Contents.swift │ ├── ErrorHandling.xcplaygroundpage │ │ └── Contents.swift │ ├── Guard.xcplaygroundpage │ │ └── Contents.swift │ ├── ImplicitlyUnwrappedOptionals.xcplaygroundpage │ │ └── Contents.swift │ ├── OptionalChaining.xcplaygroundpage │ │ └── Contents.swift │ ├── OptionalMapping.xcplaygroundpage │ │ └── Contents.swift │ ├── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ └── Unwrapping.xcplaygroundpage │ │ └── Contents.swift │ └── contents.xcplayground ├── Chapter08 └── Playgrounds │ ├── .DS_Store │ └── Ch08-FunctionalDataStructures.playground │ ├── Pages │ ├── LazyList.xcplaygroundpage │ │ └── Contents.swift │ ├── LinkedList.xcplaygroundpage │ │ └── Contents.swift │ ├── Monoid.xcplaygroundpage │ │ └── Contents.swift │ ├── Semigroup.xcplaygroundpage │ │ └── Contents.swift │ ├── Stack.xcplaygroundpage │ │ └── Contents.swift │ ├── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ └── Trees.xcplaygroundpage │ │ └── Contents.swift │ └── contents.xcplayground ├── Chapter09 └── Playgrounds │ ├── .DS_Store │ └── Ch09-ImportanceOfImmutability.playground │ ├── Pages │ ├── CopyConstructor.xcplaygroundpage │ │ └── Contents.swift │ ├── Definition.xcplaygroundpage │ │ └── Contents.swift │ ├── FunctionalExample.xcplaygroundpage │ │ └── Contents.swift │ ├── Lens.xcplaygroundpage │ │ └── Contents.swift │ └── TableOfContents.xcplaygroundpage │ │ └── Contents.swift │ └── contents.xcplayground ├── Chapter10 └── Playgrounds │ ├── .DS_Store │ └── Ch10-BestOfBothWorlds.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Chapter11 ├── Ch11-Backend │ ├── .DS_Store │ └── vapor-example │ │ ├── .DS_Store │ │ ├── .gitignore │ │ ├── .swift-version │ │ ├── .travis.yml │ │ ├── Config │ │ ├── app.json │ │ ├── development │ │ │ └── app.json │ │ ├── production │ │ │ ├── app.json │ │ │ └── servers.json │ │ ├── secrets │ │ │ ├── .gitkeep │ │ │ └── app.json │ │ └── servers.json │ │ ├── LICENSE │ │ ├── Localization │ │ ├── default.json │ │ ├── en.json │ │ └── es.json │ │ ├── Package.swift │ │ ├── Procfile │ │ ├── Public │ │ ├── images │ │ │ └── vapor-logo.png │ │ └── styles │ │ │ └── app.css │ │ ├── README.md │ │ ├── Resources │ │ └── Views │ │ │ ├── embeds │ │ │ └── header.leaf │ │ │ ├── template.leaf │ │ │ └── welcome.html │ │ ├── Sources │ │ └── App │ │ │ ├── Controllers │ │ │ └── UserController.swift │ │ │ ├── Middleware │ │ │ └── SampleMiddleware.swift │ │ │ ├── Models │ │ │ ├── Todo.swift │ │ │ ├── TodoStore.swift │ │ │ └── User.swift │ │ │ └── main.swift │ │ └── app.json └── Ch11-Frontend │ ├── .DS_Store │ └── TodoApp │ ├── .DS_Store │ ├── Podfile │ ├── Podfile.lock │ ├── Pods │ ├── Alamofire │ │ ├── LICENSE │ │ ├── README.md │ │ └── Source │ │ │ ├── AFError.swift │ │ │ ├── Alamofire.swift │ │ │ ├── DispatchQueue+Alamofire.swift │ │ │ ├── MultipartFormData.swift │ │ │ ├── NetworkReachabilityManager.swift │ │ │ ├── Notifications.swift │ │ │ ├── ParameterEncoding.swift │ │ │ ├── Request.swift │ │ │ ├── Response.swift │ │ │ ├── ResponseSerialization.swift │ │ │ ├── Result.swift │ │ │ ├── ServerTrustPolicy.swift │ │ │ ├── SessionDelegate.swift │ │ │ ├── SessionManager.swift │ │ │ ├── TaskDelegate.swift │ │ │ ├── Timeline.swift │ │ │ └── Validation.swift │ ├── Argo │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ └── Argo │ │ │ ├── Extensions │ │ │ ├── Dictionary.swift │ │ │ ├── NSNumber.swift │ │ │ └── RawRepresentable.swift │ │ │ ├── Functions │ │ │ ├── catDecoded.swift │ │ │ ├── decode.swift │ │ │ ├── flatReduce.swift │ │ │ └── sequence.swift │ │ │ ├── Operators │ │ │ ├── Argo.swift │ │ │ └── DecodeOperators.swift │ │ │ └── Types │ │ │ ├── Decodable.swift │ │ │ ├── DecodeError.swift │ │ │ ├── Decoded │ │ │ ├── Alternative.swift │ │ │ ├── Applicative.swift │ │ │ ├── Decoded.swift │ │ │ ├── FailureCoalescing.swift │ │ │ ├── Functor.swift │ │ │ └── Monad.swift │ │ │ ├── JSON.swift │ │ │ └── StandardTypes.swift │ ├── Curry │ │ ├── LICENSE │ │ ├── README.md │ │ └── Source │ │ │ └── Curry.swift │ ├── Delta │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ ├── Action.swift │ │ │ ├── Delta.h │ │ │ ├── DynamicAction.swift │ │ │ ├── ObservableProperty.swift │ │ │ └── Store.swift │ ├── Local Podspecs │ │ ├── Curry.podspec.json │ │ ├── Delta.podspec.json │ │ └── ReactiveCocoa.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ ├── ReactiveCocoa │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── ReactiveCocoa │ │ │ ├── CocoaAction.swift │ │ │ ├── CocoaTarget.swift │ │ │ ├── Deprecations+Removals.swift │ │ │ ├── DynamicProperty.swift │ │ │ ├── NSObject+Association.swift │ │ │ ├── NSObject+BindingTarget.swift │ │ │ ├── NSObject+Intercepting.swift │ │ │ ├── NSObject+KeyValueObserving.swift │ │ │ ├── NSObject+Lifetime.swift │ │ │ ├── NSObject+ObjCRuntime.swift │ │ │ ├── NSObject+ReactiveExtensionsProvider.swift │ │ │ ├── NSObject+Synchronizing.swift │ │ │ ├── ObjC+Constants.swift │ │ │ ├── ObjC+Messages.swift │ │ │ ├── ObjC+Runtime.swift │ │ │ ├── ObjC+RuntimeSubclassing.swift │ │ │ ├── ObjC+Selector.swift │ │ │ ├── ObjCRuntimeAliases.h │ │ │ ├── ObjCRuntimeAliases.m │ │ │ ├── ReactiveCocoa.h │ │ │ ├── Shared │ │ │ ├── MKMapView.swift │ │ │ └── NSLayoutConstraint.swift │ │ │ ├── UIKit │ │ │ ├── ReusableComponents.swift │ │ │ ├── UIActivityIndicatorView.swift │ │ │ ├── UIBarButtonItem.swift │ │ │ ├── UIBarItem.swift │ │ │ ├── UIButton.swift │ │ │ ├── UICollectionView.swift │ │ │ ├── UIControl.swift │ │ │ ├── UIGestureRecognizer.swift │ │ │ ├── UIImageView.swift │ │ │ ├── UILabel.swift │ │ │ ├── UIProgressView.swift │ │ │ ├── UIScrollView.swift │ │ │ ├── UISegmentedControl.swift │ │ │ ├── UITableView.swift │ │ │ ├── UITextField.swift │ │ │ ├── UITextView.swift │ │ │ ├── UIView.swift │ │ │ └── iOS │ │ │ │ ├── UIDatePicker.swift │ │ │ │ ├── UIKeyboard.swift │ │ │ │ ├── UIRefreshControl.swift │ │ │ │ ├── UISearchBar.swift │ │ │ │ ├── UISlider.swift │ │ │ │ ├── UIStepper.swift │ │ │ │ └── UISwitch.swift │ │ │ └── module.modulemap │ ├── ReactiveSwift │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── Sources │ │ │ ├── Action.swift │ │ │ ├── Atomic.swift │ │ │ ├── Bag.swift │ │ │ ├── Deprecations+Removals.swift │ │ │ ├── Disposable.swift │ │ │ ├── Event.swift │ │ │ ├── EventLogger.swift │ │ │ ├── Flatten.swift │ │ │ ├── FoundationExtensions.swift │ │ │ ├── Lifetime.swift │ │ │ ├── Observer.swift │ │ │ ├── Optional.swift │ │ │ ├── Property.swift │ │ │ ├── Reactive.swift │ │ │ ├── ResultExtensions.swift │ │ │ ├── Scheduler.swift │ │ │ ├── Signal.swift │ │ │ ├── SignalProducer.swift │ │ │ ├── TupleExtensions.swift │ │ │ └── UnidirectionalBinding.swift │ ├── Result │ │ ├── LICENSE │ │ ├── README.md │ │ └── Result │ │ │ ├── Result.swift │ │ │ └── ResultProtocol.swift │ ├── Runes │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ ├── Array.swift │ │ │ ├── Optional.swift │ │ │ └── Runes.swift │ └── Target Support Files │ │ ├── Alamofire │ │ ├── Alamofire-dummy.m │ │ ├── Alamofire-prefix.pch │ │ ├── Alamofire-umbrella.h │ │ ├── Alamofire.modulemap │ │ ├── Alamofire.xcconfig │ │ └── Info.plist │ │ ├── Argo │ │ ├── Argo-dummy.m │ │ ├── Argo-prefix.pch │ │ ├── Argo-umbrella.h │ │ ├── Argo.modulemap │ │ ├── Argo.xcconfig │ │ └── Info.plist │ │ ├── Curry │ │ ├── Curry-dummy.m │ │ ├── Curry-prefix.pch │ │ ├── Curry-umbrella.h │ │ ├── Curry.modulemap │ │ ├── Curry.xcconfig │ │ └── Info.plist │ │ ├── Delta │ │ ├── Delta-dummy.m │ │ ├── Delta-prefix.pch │ │ ├── Delta-umbrella.h │ │ ├── Delta.modulemap │ │ ├── Delta.xcconfig │ │ └── Info.plist │ │ ├── Pods-TodoApp │ │ ├── Info.plist │ │ ├── Pods-TodoApp-acknowledgements.markdown │ │ ├── Pods-TodoApp-acknowledgements.plist │ │ ├── Pods-TodoApp-dummy.m │ │ ├── Pods-TodoApp-frameworks.sh │ │ ├── Pods-TodoApp-resources.sh │ │ ├── Pods-TodoApp-umbrella.h │ │ ├── Pods-TodoApp.debug.xcconfig │ │ ├── Pods-TodoApp.modulemap │ │ └── Pods-TodoApp.release.xcconfig │ │ ├── Pods-TodoAppTests │ │ ├── Info.plist │ │ ├── Pods-TodoAppTests-acknowledgements.markdown │ │ ├── Pods-TodoAppTests-acknowledgements.plist │ │ ├── Pods-TodoAppTests-dummy.m │ │ ├── Pods-TodoAppTests-frameworks.sh │ │ ├── Pods-TodoAppTests-resources.sh │ │ ├── Pods-TodoAppTests-umbrella.h │ │ ├── Pods-TodoAppTests.debug.xcconfig │ │ ├── Pods-TodoAppTests.modulemap │ │ └── Pods-TodoAppTests.release.xcconfig │ │ ├── ReactiveCocoa │ │ ├── Info.plist │ │ ├── ReactiveCocoa-dummy.m │ │ ├── ReactiveCocoa-prefix.pch │ │ ├── ReactiveCocoa.modulemap │ │ └── ReactiveCocoa.xcconfig │ │ ├── ReactiveSwift │ │ ├── Info.plist │ │ ├── ReactiveSwift-dummy.m │ │ ├── ReactiveSwift-prefix.pch │ │ ├── ReactiveSwift-umbrella.h │ │ ├── ReactiveSwift.modulemap │ │ └── ReactiveSwift.xcconfig │ │ ├── Result │ │ ├── Info.plist │ │ ├── Result-dummy.m │ │ ├── Result-prefix.pch │ │ ├── Result-umbrella.h │ │ ├── Result.modulemap │ │ └── Result.xcconfig │ │ └── Runes │ │ ├── Info.plist │ │ ├── Runes-dummy.m │ │ ├── Runes-prefix.pch │ │ ├── Runes-umbrella.h │ │ ├── Runes.modulemap │ │ └── Runes.xcconfig │ ├── TodoApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── TodoApp.xcworkspace │ └── contents.xcworkspacedata │ ├── TodoApp │ ├── Actions │ │ ├── ClearCompletedTodosAction.swift │ │ ├── CreateTodoAction.swift │ │ ├── DeleteTodoAction.swift │ │ ├── DetailsTodoAction.swift │ │ ├── LoadTodosAction.swift │ │ ├── SetFilterAction.swift │ │ ├── ToggleCompletedAction.swift │ │ └── UpdateTodoAction.swift │ ├── AppDelegate.swift │ ├── Communication │ │ ├── Urls.swift │ │ └── WebServiceManager.swift │ ├── Controllers │ │ ├── DetailsViewController.swift │ │ └── MasterViewController.swift │ ├── Extensions │ │ └── ReactiveCocoa.swift │ ├── Info.plist │ ├── Managers │ │ └── TodoManager.swift │ ├── Models │ │ ├── RequestProtocol.swift │ │ ├── Todo.swift │ │ ├── TodoLens.swift │ │ ├── TodoRequest.swift │ │ ├── TodoViewModel.swift │ │ └── TodosViewModel.swift │ ├── Resources │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ └── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ ├── State │ │ └── State.swift │ ├── Stores │ │ ├── Store.swift │ │ └── StoreExtensions.swift │ └── Views │ │ ├── FooterView.swift │ │ └── TodoTableViewCell.swift │ └── TodoAppTests │ ├── Info.plist │ └── TodoAppTests.swift ├── LICENSE ├── README.md └── __MACOSX └── SwiftFP ├── ._.DS_Store ├── Ch11-Backend ├── ._.DS_Store └── vapor-example │ └── ._.DS_Store ├── Ch11-Frontend ├── ._.DS_Store └── TodoApp │ └── ._.DS_Store └── Playgrounds ├── ._.DS_Store └── Ch05-Generics.playground └── Pages ├── ._AssociatedTypeProtocols.xcplaygroundpage └── ._ExtendingGenericTypes.xcplaygroundpage /Chapter01/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter01/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/ARC.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // ARC 6 | class AClassWithLazyClosure { 7 | lazy var aClosure: (Int, String) -> String = { 8 | [unowned self] (index: Int, stringToProcess: String) -> String in 9 | // closure body goes here 10 | return "" 11 | } 12 | } 13 | 14 | //: [Next](@next) 15 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/AnyAnyObject.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Any and AnyObject - not recommended 6 | 7 | class Movie { 8 | var director: String 9 | var name: String 10 | init(name: String, director: String) { 11 | self.director = director 12 | self.name = name 13 | } 14 | } 15 | 16 | let objects: [AnyObject] = [ 17 | Movie(name: "The Shawshank Redemption", director: "Frank Darabont"), 18 | Movie(name: "The Godfather", director: "Francis Ford Coppola") 19 | ] 20 | 21 | for object in objects { 22 | let movie = object as! Movie 23 | print("Movie: '\(movie.name)', dir. \(movie.director)") 24 | } 25 | 26 | // Shorter syntax 27 | for movie in objects as! [Movie] { 28 | print("Movie: '\(movie.name)', dir. \(movie.director)") 29 | } 30 | 31 | //: [Next](@next) 32 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Collections.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Collections 6 | 7 | // Arrays and Dictionaries 8 | var cheeses = ["Brie", "Tete de Moine", "Cambozola", "Camembert"] 9 | cheeses[2] = "Roquefort" 10 | var cheeseWinePairs = [ 11 | "Brie":"Chardonnay", 12 | "Camembert":"Champagne", 13 | "Gruyere":"Sauvignon Blanc" 14 | ] 15 | 16 | cheeseWinePairs ["Cheddar"] = "Cabarnet Sauvignon" 17 | // To create an empty array or dictionary 18 | let emptyArray = [String]() 19 | let emptyDictionary = Dictionary() 20 | cheeses = [] 21 | cheeseWinePairs = [:] 22 | 23 | 24 | // Iteration over dictionaries 25 | 26 | for (cheese, wine) in cheeseWinePairs { 27 | print("\(cheese): \(wine)") 28 | } 29 | 30 | //: [Next](@next) 31 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/DeclarativeImperative.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Declarative vs. Imperative 3 | 4 | let numbers = [9, 29, 19, 79] 5 | 6 | // Imperative example 7 | var tripledNumbers:[Int] = [] 8 | for number in numbers { 9 | tripledNumbers.append(number * 3) 10 | } 11 | print(tripledNumbers) 12 | 13 | // Declarative example 14 | let tripledIntNumbers = numbers.map({ 15 | number in 16 | number * 3 17 | }) 18 | print(tripledIntNumbers) 19 | 20 | let newTripledIntNumbers = numbers.map { $0 * 3 } 21 | 22 | //: [Next](@next) 23 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Enumerations.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Enumerations 6 | 7 | enum MLSTeam { 8 | case montreal 9 | case toronto 10 | case newYork 11 | case columbus 12 | case losAngeles 13 | case seattle 14 | } 15 | 16 | let theTeam = MLSTeam.montreal 17 | 18 | // Pattern matching 19 | 20 | switch theTeam { 21 | case .montreal: 22 | print("Montreal Impact") 23 | case .toronto: 24 | print("Toronto FC") 25 | case .newYork: 26 | print("Newyork Redbulls") 27 | case .columbus: 28 | print("Columbus Crew") 29 | case .losAngeles: 30 | print("LA Galaxy") 31 | case .seattle: 32 | print("Seattle Sounders") 33 | } 34 | 35 | // Algebraic data types 36 | 37 | enum NHLTeam { case canadiens, senators, rangers, penguins, blackHawks, capitals } 38 | 39 | enum Team { 40 | case hockey(NHLTeam) 41 | case soccer(MLSTeam) 42 | } 43 | 44 | //struct HockeyAndSoccerTeams { 45 | // var hockey: NHLTeam 46 | // var soccer: MLSTeam 47 | //} 48 | 49 | // product type 50 | 51 | enum HockeyAndSoccerTeams { 52 | case value(hockey: NHLTeam, soccer: MLSTeam) 53 | } 54 | 55 | //: [Next](@next) 56 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/ErrorHandling.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Error Protocol 6 | 7 | enum HttpError: Error { 8 | case badRequest 9 | case unauthorized 10 | case forbidden 11 | case requestTimeOut 12 | case unsupportedMediaType 13 | case internalServerError 14 | case notImplemented 15 | case badGateway 16 | case serviceUnavailable 17 | } 18 | 19 | //: [Next](@next) 20 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Functions.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Functions 6 | 7 | func greet(name: String, day: String) -> String { 8 | return "Hello \(name), today is \(day)" 9 | } 10 | 11 | greet(name: "Jorge", day: "Saturday") 12 | 13 | // Variable number of arguments in functions - Variadic Parameters 14 | func sumOf(numbers:Int...) -> (Int, Int) { 15 | var sum = 0 16 | var counter = 0 17 | for number in numbers { 18 | sum += number 19 | counter += 1 20 | } 21 | return (sum, counter) 22 | } 23 | 24 | sumOf() 25 | sumOf(numbers: 7, 9, 45) 26 | 27 | // inout parameters 28 | 29 | func swapTwoInts( a: inout Int, b: inout Int) { 30 | let temporaryA = a 31 | a = b 32 | b = temporaryA 33 | } 34 | 35 | // Nested functions 36 | 37 | func returnTwenty() -> Int { 38 | var y = 10 39 | func add() { 40 | y += 10 41 | } 42 | add() 43 | return y 44 | } 45 | 46 | returnTwenty() 47 | 48 | // Return another function as its value 49 | func makeIncrementer() -> ((Int) -> Int) { 50 | func addOne(number: Int) -> Int { 51 | return 1 + number 52 | } 53 | return addOne 54 | } 55 | 56 | var increment = makeIncrementer() 57 | increment(7) 58 | 59 | //: [Next](@next) 60 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Generics.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Generics 6 | 7 | func swapTwoIntegers( a: inout Int, b: inout Int) { 8 | let tempA = a 9 | a = b 10 | b = tempA 11 | } 12 | 13 | func swapTwoValues( a: inout T, b: inout T) { 14 | let tempA = a 15 | a = b 16 | b = tempA 17 | } 18 | 19 | //: [Next](@next) 20 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Immutability.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Immutability vs. Mutability 6 | 7 | var aMutableString = "This is a variable String" 8 | let aConstString = "This is a constant String" 9 | 10 | //: [Next](@next) 11 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Initialization.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Initialization 6 | 7 | class ShoppingItem { 8 | var name: String? 9 | var quantity = 1 10 | var purchased = false 11 | } 12 | 13 | var item = ShoppingItem() 14 | 15 | //: [Next](@next) 16 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/LazyEvaluation.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Lazy evaluation 3 | 4 | import Foundation 5 | 6 | let oneToFour = [1, 2, 3, 4] 7 | let firstNumber = oneToFour.lazy.map({ $0 * 3}).first! 8 | print(firstNumber) // The result is going to be 3 9 | //: [Next](@next) 10 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/MapFilterReduce.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // map 6 | 7 | // Return an `Array` containing the results of calling `transform(x)` on each element `x` of `self` 8 | // func map(transform: (T) -> U) -> [U] 9 | let numbers = [10, 30, 91, 50, 100, 39, 74] 10 | var formattedNumbers: [String] = [] 11 | 12 | for number in numbers { 13 | let formattedNumber = "\(number)$" 14 | formattedNumbers.append(formattedNumber) 15 | } 16 | 17 | let mappedNumbers = numbers.map { "\($0)$" } 18 | 19 | // filter 20 | 21 | // Return an Array containing the elements x of self for which includeElement(x)` is `true` 22 | // func filter(includeElement: (T) -> Bool) -> [T] 23 | let evenNumbers = numbers.filter { $0 % 2 == 0 } 24 | 25 | 26 | // reduce 27 | 28 | // Return the result of repeatedly calling `combine` with an accumulated value initialized to `initial` and each element of `self`, in turn, i.e. return `combine(combine(...combine(combine(initial, self[0]), self[1]),...self[count-2]), self[count-1])`. 29 | // func reduce(initial: U, combine: (U, T) -> U) -> U 30 | let total = numbers.reduce(0) { $0 + $1 } 31 | 32 | //: [Next](@next) 33 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Methods.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Methods 6 | 7 | class AClass { 8 | class func someTypeMethod() { 9 | // type method body 10 | } 11 | } 12 | 13 | // We can call this method as follows: 14 | AClass.someTypeMethod() 15 | 16 | //: [Next](@next) 17 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/ModernSyntax.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Modern syntax 3 | 4 | /* ObjC 5 | 6 | // VerboseClass.h 7 | @interface VerboseClass: NSObject 8 | @property (nonatomic, strong) NSArray *ourArray; 9 | - (void)aMethod:(NSArray *)anArray; 10 | @end 11 | 12 | // TestVerboseClass.m 13 | #import "VerboseClass.h" 14 | 15 | @interface TestVerboseClass : NSObject 16 | 17 | @end 18 | 19 | @implementation TestVerboseClass 20 | 21 | - (void)aMethod { 22 | VerboseClass *ourOBJClass = [[VerboseClass alloc] init]; 23 | [ourOBJClass aMethod: @[@"One", @"Two", @"Three"]]; 24 | } 25 | 26 | @end 27 | 28 | // TestVerboseClass.m 29 | #import "VerboseClass.h" 30 | 31 | @interface TestVerboseClass : NSObject 32 | 33 | @end 34 | 35 | @implementation TestVerboseClass 36 | 37 | - (void)aMethod { 38 | VerboseClass *ourOBJCClass = [[VerboseClass alloc] init]; 39 | [ourOBJCClass aMethod: @[@"One", @"Two", @"Three"]]; 40 | NSLog(@"%@", ourOBJCClass.ourArray); 41 | } 42 | */ 43 | 44 | 45 | 46 | class ASwiftClass { 47 | var ourArray: [String] = [] 48 | 49 | func aMethod(anArray: [String]) { 50 | self.ourArray = anArray 51 | } 52 | } 53 | 54 | let aSwiftClassInstance = ASwiftClass() 55 | aSwiftClassInstance.aMethod(anArray: ["one", "Two", "Three"]) 56 | print(aSwiftClassInstance.ourArray) 57 | //: [Next](@next) 58 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/NestedTypes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Nested types 6 | 7 | struct BlackjackCard { 8 | // nested Suit enumeration 9 | enum Suit: Character { 10 | case spades = "♠", 11 | hearts = "♡", 12 | diamonds = "♢", 13 | clubs = "♣" 14 | } 15 | 16 | // nested Rank enumeration 17 | enum Rank: Int { 18 | case two = 2, three, four, five, six, seven, eight, nine, ten 19 | case jack, queen, king, ace 20 | 21 | // nested struct 22 | struct Values { 23 | let first: Int, second: Int? 24 | } 25 | 26 | var values: Values { 27 | switch self { 28 | case .ace: 29 | return Values(first: 1, second: 11) 30 | case .jack, .queen, .king: 31 | return Values(first: 10, second: nil) 32 | default: 33 | return Values(first: self.rawValue, second: nil) 34 | } 35 | } 36 | } 37 | 38 | let rank: Rank, suit: Suit 39 | 40 | var description: String { 41 | var output = "suit is \(suit.rawValue)," 42 | output += " value is \(rank.values.first)" 43 | if let second = rank.values.second { 44 | output += " or \(second)" 45 | } 46 | return output 47 | } 48 | } 49 | 50 | //: [Next](@next) 51 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Optionals.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Optional value either contains a value or contains nil 6 | var optionalString: String? = "A String literal" 7 | optionalString = nil 8 | 9 | optionalString = "An optional String" 10 | print(optionalString!) 11 | 12 | let nilName: String? = nil 13 | if let familyName = nilName { 14 | let greetingfamilyName = "Hello, Mr. \(familyName)" 15 | } else { 16 | // Optional does not have a value 17 | } 18 | 19 | // Optional chaining 20 | class Residence { 21 | var numberOfRooms = 1 22 | } 23 | 24 | class Person { 25 | var residence: Residence? 26 | } 27 | 28 | let jeanMarc = Person() 29 | // This can be used for calling methods and subscripts through optional chaining too 30 | if let roomCount = jeanMarc.residence?.numberOfRooms { 31 | // Use the roomCount 32 | } 33 | //: [Next](@next) 34 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Protocols.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | protocol HttpProtocol{ 6 | func didRecieveResults(results: Any) 7 | } 8 | 9 | struct WebServiceManager { 10 | var delegate:HttpProtocol? 11 | let data: Data 12 | func test() { 13 | do { 14 | let jsonResult = try JSONSerialization.jsonObject(with: self.data, options: JSONSerialization.ReadingOptions.mutableContainers) 15 | self.delegate?.didRecieveResults(results: jsonResult) 16 | } catch let error as NSError { 17 | print("json error" + error.localizedDescription) 18 | } 19 | } 20 | } 21 | 22 | //: [Next](@next) 23 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Strings.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // String literal 6 | 7 | let aVegetable = "Arugula" 8 | 9 | // Initializing an Empty String 10 | var anEmptyString = "" 11 | var anotherEmptyString = String() 12 | 13 | if anEmptyString.isEmpty { 14 | print("String is empty") 15 | } 16 | 17 | // Concatenating Strings and Characters 18 | 19 | let string1 = "Hello" 20 | let string2 = " Mr" 21 | var welcome = string1 + string2 22 | 23 | var instruction = "Follow us please" 24 | instruction += string2 25 | 26 | let exclamationMark: Character = "!" 27 | welcome.append(exclamationMark) 28 | 29 | 30 | // String Interpolation 31 | 32 | let multiplier = 3 33 | let message = "\(multiplier) times 7.5 is \(Double (multiplier) * 7.5)" 34 | // message is "3 times 2.5 is 22.5” 35 | 36 | //: [Next](@next) 37 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Subscripts.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Subscripts 6 | 7 | struct TimesTable { 8 | let multiplier: Int 9 | subscript(index: Int) -> Int { 10 | return multiplier * index 11 | } 12 | } 13 | 14 | let fiveTimesTable = TimesTable(multiplier: 5) 15 | print("six times five is \(fiveTimesTable[6])") 16 | // prints "six times five is 30” 17 | 18 | //: [Next](@next) 19 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | /*: Markdown documentation 3 | 4 | ### Table of contents 5 | * [Declarative vs. Imperative](DeclarativeImperative) 6 | * [Lazy Evaluation](LazyEvaluation) 7 | * [Modern Syntax](ModernSyntax) 8 | * [Types](Types) 9 | * [Immutability vs. Mutability](Immutability) 10 | * [Tuples](Tuples) 11 | * [Optionals](Optionals) 12 | * [Strings](Strings) 13 | * [Collections](Collections) 14 | * [Control Flows](ControlFlows) 15 | * [Functions](Functions) 16 | * [map, filter and reduce](MapFilterReduce) 17 | * [Enumerations](Enumerations) 18 | * [Generics](Generics) 19 | * [Methods](Methods) 20 | * [Subscripts](Subscripts) 21 | * [Initialization](Initialization) 22 | * [ARC](ARC) 23 | * [Optional Chaining](OptionalChaining) 24 | * [ErrorType](ErrorType) 25 | * [Protocols as variables](ProtocolAsVar) 26 | * [Any and AnyObject](AnyAnyObject) 27 | * [Nested Types](NestedTypes) 28 | * [Extensions and Protocols](ExtensionsAndProtocols) 29 | */ 30 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Tuples.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Tuples 6 | 7 | let http400Error = (400, "Bad Request") 8 | // http400Error is of type (Int, String), and equals (400, "Bad Request") 9 | 10 | // Decompose a Tuple's content 11 | let (requestStatusCode, requestStatusMessage) = http400Error 12 | 13 | //: [Next](@next) 14 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Pages/Types.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Types 3 | import Foundation 4 | 5 | // Type inference 6 | 7 | let constString = "This is a string constant" 8 | let pi = 3.14159 9 | var primeNumber = 691 10 | let name = "my name" 11 | 12 | // Type annotation 13 | 14 | let pi2: Double = 3.14159 15 | let piAndPhi: (Double, Double) = (3.14159, 1.618) 16 | func ourFunction(a: Int) { /* ... */ } 17 | 18 | // Type aliases 19 | 20 | typealias UnsignedInteger = UInt32 21 | 22 | //: [Next](@next) 23 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/ARC.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // ARC 6 | class AClassWithLazyClosure { 7 | lazy var aClosure: (Int, String) -> String = { 8 | [unowned self] (index: Int, stringToProcess: String) -> String in 9 | // closure body goes here 10 | return "" 11 | } 12 | } 13 | 14 | //: [Next](@next) 15 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/AnyAnyObject.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Any and AnyObject - not recommended 6 | 7 | class Movie { 8 | var director: String 9 | var name: String 10 | init(name: String, director: String) { 11 | self.director = director 12 | self.name = name 13 | } 14 | } 15 | 16 | let objects: [AnyObject] = [ 17 | Movie(name: "The Shawshank Redemption", director: "Frank Darabont"), 18 | Movie(name: "The Godfather", director: "Francis Ford Coppola") 19 | ] 20 | 21 | for object in objects { 22 | let movie = object as! Movie 23 | print("Movie: '\(movie.name)', dir. \(movie.director)") 24 | } 25 | 26 | // Shorter syntax 27 | for movie in objects as! [Movie] { 28 | print("Movie: '\(movie.name)', dir. \(movie.director)") 29 | } 30 | 31 | //: [Next](@next) 32 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Collections.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Collections 6 | 7 | // Arrays and Dictionaries 8 | var cheeses = ["Brie", "Tete de Moine", "Cambozola", "Camembert"] 9 | cheeses[2] = "Roquefort" 10 | var cheeseWinePairs = [ 11 | "Brie":"Chardonnay", 12 | "Camembert":"Champagne", 13 | "Gruyere":"Sauvignon Blanc" 14 | ] 15 | 16 | cheeseWinePairs ["Cheddar"] = "Cabarnet Sauvignon" 17 | // To create an empty array or dictionary 18 | let emptyArray = [String]() 19 | let emptyDictionary = Dictionary() 20 | cheeses = [] 21 | cheeseWinePairs = [:] 22 | 23 | 24 | // Iteration over dictionaries 25 | 26 | for (cheese, wine) in cheeseWinePairs { 27 | print("\(cheese): \(wine)") 28 | } 29 | 30 | //: [Next](@next) 31 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/DeclarativeImperative.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Declarative vs. Imperative 3 | 4 | let numbers = [9, 29, 19, 79] 5 | 6 | // Imperative example 7 | var tripledNumbers:[Int] = [] 8 | for number in numbers { 9 | tripledNumbers.append(number * 3) 10 | } 11 | print(tripledNumbers) 12 | 13 | // Declarative example 14 | let tripledIntNumbers = numbers.map({ 15 | number in 16 | number * 3 17 | }) 18 | print(tripledIntNumbers) 19 | 20 | let newTripledIntNumbers = numbers.map { $0 * 3 } 21 | 22 | //: [Next](@next) 23 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Enumerations.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Enumerations 6 | 7 | enum MLSTeam { 8 | case montreal 9 | case toronto 10 | case newYork 11 | case columbus 12 | case losAngeles 13 | case seattle 14 | } 15 | 16 | let theTeam = MLSTeam.montreal 17 | 18 | // Pattern matching 19 | 20 | switch theTeam { 21 | case .montreal: 22 | print("Montreal Impact") 23 | case .toronto: 24 | print("Toronto FC") 25 | case .newYork: 26 | print("Newyork Redbulls") 27 | case .columbus: 28 | print("Columbus Crew") 29 | case .losAngeles: 30 | print("LA Galaxy") 31 | case .seattle: 32 | print("Seattle Sounders") 33 | } 34 | 35 | // Algebraic data types 36 | 37 | enum NHLTeam { case canadiens, senators, rangers, penguins, blackHawks, capitals } 38 | 39 | enum Team { 40 | case hockey(NHLTeam) 41 | case soccer(MLSTeam) 42 | } 43 | 44 | //struct HockeyAndSoccerTeams { 45 | // var hockey: NHLTeam 46 | // var soccer: MLSTeam 47 | //} 48 | 49 | // product type 50 | 51 | enum HockeyAndSoccerTeams { 52 | case value(hockey: NHLTeam, soccer: MLSTeam) 53 | } 54 | 55 | //: [Next](@next) 56 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/ErrorHandling.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Error Protocol 6 | 7 | enum HttpError: Error { 8 | case badRequest 9 | case unauthorized 10 | case forbidden 11 | case requestTimeOut 12 | case unsupportedMediaType 13 | case internalServerError 14 | case notImplemented 15 | case badGateway 16 | case serviceUnavailable 17 | } 18 | 19 | //: [Next](@next) 20 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Functions.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Functions 6 | 7 | func greet(name: String, day: String) -> String { 8 | return "Hello \(name), today is \(day)" 9 | } 10 | 11 | greet(name: "Jorge", day: "Saturday") 12 | 13 | // Variable number of arguments in functions - Variadic Parameters 14 | func sumOf(numbers:Int...) -> (Int, Int) { 15 | var sum = 0 16 | var counter = 0 17 | for number in numbers { 18 | sum += number 19 | counter += 1 20 | } 21 | return (sum, counter) 22 | } 23 | 24 | sumOf() 25 | sumOf(numbers: 7, 9, 45) 26 | 27 | // inout parameters 28 | 29 | func swapTwoInts( a: inout Int, b: inout Int) { 30 | let temporaryA = a 31 | a = b 32 | b = temporaryA 33 | } 34 | 35 | // Nested functions 36 | 37 | func returnTwenty() -> Int { 38 | var y = 10 39 | func add() { 40 | y += 10 41 | } 42 | add() 43 | return y 44 | } 45 | 46 | returnTwenty() 47 | 48 | // Return another function as its value 49 | func makeIncrementer() -> ((Int) -> Int) { 50 | func addOne(number: Int) -> Int { 51 | return 1 + number 52 | } 53 | return addOne 54 | } 55 | 56 | var increment = makeIncrementer() 57 | increment(7) 58 | 59 | //: [Next](@next) 60 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Generics.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Generics 6 | 7 | func swapTwoIntegers( a: inout Int, b: inout Int) { 8 | let tempA = a 9 | a = b 10 | b = tempA 11 | } 12 | 13 | func swapTwoValues( a: inout T, b: inout T) { 14 | let tempA = a 15 | a = b 16 | b = tempA 17 | } 18 | 19 | //: [Next](@next) 20 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Immutability.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Immutability vs. Mutability 6 | 7 | var aMutableString = "This is a variable String" 8 | let aConstString = "This is a constant String" 9 | 10 | //: [Next](@next) 11 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Initialization.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Initialization 6 | 7 | class ShoppingItem { 8 | var name: String? 9 | var quantity = 1 10 | var purchased = false 11 | } 12 | 13 | var item = ShoppingItem() 14 | 15 | //: [Next](@next) 16 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/LazyEvaluation.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Lazy evaluation 3 | 4 | import Foundation 5 | 6 | let oneToFour = [1, 2, 3, 4] 7 | let firstNumber = oneToFour.lazy.map({ $0 * 3}).first! 8 | print(firstNumber) // The result is going to be 3 9 | //: [Next](@next) 10 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/MapFilterReduce.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // map 6 | 7 | // Return an `Array` containing the results of calling `transform(x)` on each element `x` of `self` 8 | // func map(transform: (T) -> U) -> [U] 9 | let numbers = [10, 30, 91, 50, 100, 39, 74] 10 | var formattedNumbers: [String] = [] 11 | 12 | for number in numbers { 13 | let formattedNumber = "\(number)$" 14 | formattedNumbers.append(formattedNumber) 15 | } 16 | 17 | let mappedNumbers = numbers.map { "\($0)$" } 18 | 19 | // filter 20 | 21 | // Return an Array containing the elements x of self for which includeElement(x)` is `true` 22 | // func filter(includeElement: (T) -> Bool) -> [T] 23 | let evenNumbers = numbers.filter { $0 % 2 == 0 } 24 | 25 | 26 | // reduce 27 | 28 | // Return the result of repeatedly calling `combine` with an accumulated value initialized to `initial` and each element of `self`, in turn, i.e. return `combine(combine(...combine(combine(initial, self[0]), self[1]),...self[count-2]), self[count-1])`. 29 | // func reduce(initial: U, combine: (U, T) -> U) -> U 30 | let total = numbers.reduce(0) { $0 + $1 } 31 | 32 | //: [Next](@next) 33 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Methods.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Methods 6 | 7 | class AClass { 8 | class func someTypeMethod() { 9 | // type method body 10 | } 11 | } 12 | 13 | // We can call this method as follows: 14 | AClass.someTypeMethod() 15 | 16 | //: [Next](@next) 17 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/ModernSyntax.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Modern syntax 3 | 4 | /* ObjC 5 | 6 | // VerboseClass.h 7 | @interface VerboseClass: NSObject 8 | @property (nonatomic, strong) NSArray *ourArray; 9 | - (void)aMethod:(NSArray *)anArray; 10 | @end 11 | 12 | // TestVerboseClass.m 13 | #import "VerboseClass.h" 14 | 15 | @interface TestVerboseClass : NSObject 16 | 17 | @end 18 | 19 | @implementation TestVerboseClass 20 | 21 | - (void)aMethod { 22 | VerboseClass *ourOBJClass = [[VerboseClass alloc] init]; 23 | [ourOBJClass aMethod: @[@"One", @"Two", @"Three"]]; 24 | } 25 | 26 | @end 27 | 28 | // TestVerboseClass.m 29 | #import "VerboseClass.h" 30 | 31 | @interface TestVerboseClass : NSObject 32 | 33 | @end 34 | 35 | @implementation TestVerboseClass 36 | 37 | - (void)aMethod { 38 | VerboseClass *ourOBJCClass = [[VerboseClass alloc] init]; 39 | [ourOBJCClass aMethod: @[@"One", @"Two", @"Three"]]; 40 | NSLog(@"%@", ourOBJCClass.ourArray); 41 | } 42 | */ 43 | 44 | 45 | 46 | class ASwiftClass { 47 | var ourArray: [String] = [] 48 | 49 | func aMethod(anArray: [String]) { 50 | self.ourArray = anArray 51 | } 52 | } 53 | 54 | let aSwiftClassInstance = ASwiftClass() 55 | aSwiftClassInstance.aMethod(anArray: ["one", "Two", "Three"]) 56 | print(aSwiftClassInstance.ourArray) 57 | //: [Next](@next) 58 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/NestedTypes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Nested types 6 | 7 | struct BlackjackCard { 8 | // nested Suit enumeration 9 | enum Suit: Character { 10 | case spades = "♠", 11 | hearts = "♡", 12 | diamonds = "♢", 13 | clubs = "♣" 14 | } 15 | 16 | // nested Rank enumeration 17 | enum Rank: Int { 18 | case two = 2, three, four, five, six, seven, eight, nine, ten 19 | case jack, queen, king, ace 20 | 21 | // nested struct 22 | struct Values { 23 | let first: Int, second: Int? 24 | } 25 | 26 | var values: Values { 27 | switch self { 28 | case .ace: 29 | return Values(first: 1, second: 11) 30 | case .jack, .queen, .king: 31 | return Values(first: 10, second: nil) 32 | default: 33 | return Values(first: self.rawValue, second: nil) 34 | } 35 | } 36 | } 37 | 38 | let rank: Rank, suit: Suit 39 | 40 | var description: String { 41 | var output = "suit is \(suit.rawValue)," 42 | output += " value is \(rank.values.first)" 43 | if let second = rank.values.second { 44 | output += " or \(second)" 45 | } 46 | return output 47 | } 48 | } 49 | 50 | //: [Next](@next) 51 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Optionals.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Optional value either contains a value or contains nil 6 | var optionalString: String? = "A String literal" 7 | optionalString = nil 8 | 9 | optionalString = "An optional String" 10 | print(optionalString!) 11 | 12 | let nilName: String? = nil 13 | if let familyName = nilName { 14 | let greetingfamilyName = "Hello, Mr. \(familyName)" 15 | } else { 16 | // Optional does not have a value 17 | } 18 | 19 | // Optional chaining 20 | class Residence { 21 | var numberOfRooms = 1 22 | } 23 | 24 | class Person { 25 | var residence: Residence? 26 | } 27 | 28 | let jeanMarc = Person() 29 | // This can be used for calling methods and subscripts through optional chaining too 30 | if let roomCount = jeanMarc.residence?.numberOfRooms { 31 | // Use the roomCount 32 | } 33 | //: [Next](@next) 34 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Protocols.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | protocol HttpProtocol{ 6 | func didRecieveResults(results: Any) 7 | } 8 | 9 | struct WebServiceManager { 10 | var delegate:HttpProtocol? 11 | let data: Data 12 | func test() { 13 | do { 14 | let jsonResult = try JSONSerialization.jsonObject(with: self.data, options: JSONSerialization.ReadingOptions.mutableContainers) 15 | self.delegate?.didRecieveResults(results: jsonResult) 16 | } catch let error as NSError { 17 | print("json error" + error.localizedDescription) 18 | } 19 | } 20 | } 21 | 22 | //: [Next](@next) 23 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Strings.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // String literal 6 | 7 | let aVegetable = "Arugula" 8 | 9 | // Initializing an Empty String 10 | var anEmptyString = "" 11 | var anotherEmptyString = String() 12 | 13 | if anEmptyString.isEmpty { 14 | print("String is empty") 15 | } 16 | 17 | // Concatenating Strings and Characters 18 | 19 | let string1 = "Hello" 20 | let string2 = " Mr" 21 | var welcome = string1 + string2 22 | 23 | var instruction = "Follow us please" 24 | instruction += string2 25 | 26 | let exclamationMark: Character = "!" 27 | welcome.append(exclamationMark) 28 | 29 | 30 | // String Interpolation 31 | 32 | let multiplier = 3 33 | let message = "\(multiplier) times 7.5 is \(Double (multiplier) * 7.5)" 34 | // message is "3 times 2.5 is 22.5” 35 | 36 | //: [Next](@next) 37 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Subscripts.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Subscripts 6 | 7 | struct TimesTable { 8 | let multiplier: Int 9 | subscript(index: Int) -> Int { 10 | return multiplier * index 11 | } 12 | } 13 | 14 | let fiveTimesTable = TimesTable(multiplier: 5) 15 | print("six times five is \(fiveTimesTable[6])") 16 | // prints "six times five is 30” 17 | 18 | //: [Next](@next) 19 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | /*: Markdown documentation 3 | 4 | ### Table of contents 5 | * [Declarative vs. Imperative](DeclarativeImperative) 6 | * [Lazy Evaluation](LazyEvaluation) 7 | * [Modern Syntax](ModernSyntax) 8 | * [Types](Types) 9 | * [Immutability vs. Mutability](Immutability) 10 | * [Tuples](Tuples) 11 | * [Optionals](Optionals) 12 | * [Strings](Strings) 13 | * [Collections](Collections) 14 | * [Control Flows](ControlFlows) 15 | * [Functions](Functions) 16 | * [map, filter and reduce](MapFilterReduce) 17 | * [Enumerations](Enumerations) 18 | * [Generics](Generics) 19 | * [Methods](Methods) 20 | * [Subscripts](Subscripts) 21 | * [Initialization](Initialization) 22 | * [ARC](ARC) 23 | * [Optional Chaining](OptionalChaining) 24 | * [ErrorType](ErrorType) 25 | * [Protocols as variables](ProtocolAsVar) 26 | * [Any and AnyObject](AnyAnyObject) 27 | * [Nested Types](NestedTypes) 28 | * [Extensions and Protocols](ExtensionsAndProtocols) 29 | */ 30 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Tuples.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Tuples 6 | 7 | let http400Error = (400, "Bad Request") 8 | // http400Error is of type (Int, String), and equals (400, "Bad Request") 9 | 10 | // Decompose a Tuple's content 11 | let (requestStatusCode, requestStatusMessage) = http400Error 12 | 13 | //: [Next](@next) 14 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/Types.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | //: ### Types 3 | import Foundation 4 | 5 | // Type inference 6 | 7 | let constString = "This is a string constant" 8 | let pi = 3.14159 9 | var primeNumber = 691 10 | let name = "my name" 11 | 12 | // Type annotation 13 | 14 | let pi2: Double = 3.14159 15 | let piAndPhi: (Double, Double) = (3.14159, 1.618) 16 | func ourFunction(a: Int) { /* ... */ } 17 | 18 | // Type aliases 19 | 20 | typealias UnsignedInteger = UInt32 21 | 22 | //: [Next](@next) 23 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Pages/ARC.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // ARC 6 | class AClassWithLazyClosure { 7 | lazy var aClosure: (Int, String) -> String = { 8 | [unowned self] (index: Int, stringToProcess: String) -> String in 9 | // closure body goes here 10 | return "" 11 | } 12 | } 13 | 14 | //: [Next](@next) 15 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/Resources/Ch01-Introduction.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter01/Playgrounds/Ch01-Introduction.playground/playground.xcworkspace/xcuserdata/nayefa.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter01/Playgrounds/Ch01-Introduction.playground/playground.xcworkspace/xcuserdata/nayefa.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Chapter02/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter02/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/CapturingValues.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func sendRequest(completion: @escaping (_ response: String?, _ error: Error?) -> Void) { 6 | // execute some time consuming operation, if successfull { 7 | completion("Response", nil) 8 | //} 9 | } 10 | 11 | sendRequest() { 12 | (response: String?, error: Error?) in 13 | if let result = response { 14 | print(result) 15 | } else if let serverError = error { 16 | // Error 17 | } 18 | } 19 | 20 | //: [Next](@next) 21 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/FirstClassFunctions.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let name: String = "Grace" 6 | 7 | func sayHello(name: String) { 8 | print("Hello, \(name)") 9 | } 10 | 11 | sayHello(name: "Your name") // or 12 | sayHello(name: name) 13 | 14 | var sayHelloFunc = sayHello 15 | 16 | //: [Next](@next) 17 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/FunctionComposition.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let content = "10,20,40,30,80,60" 6 | 7 | func extractElements(_ content: String) -> [String] { 8 | return content.characters.split(separator: ",").map { String($0) } 9 | } 10 | 11 | let elements = extractElements(content) 12 | 13 | func formatWithCurrency(content: [String]) -> [String] { 14 | return content.map {"\($0)$"} 15 | } 16 | 17 | let formattedElements = formatWithCurrency(content: elements) 18 | 19 | let composedFunction = { 20 | data in 21 | formatWithCurrency(content: extractElements(data)) 22 | } 23 | 24 | composedFunction(content) 25 | 26 | // Composed function with custom operators 27 | 28 | precedencegroup AssociativityLeft { 29 | associativity: left 30 | } 31 | 32 | infix operator |> : AssociativityLeft 33 | func |> (f: @escaping (T) -> V, g: @escaping (V) -> V ) -> (T) -> V { 34 | return { x in g(f(x)) } 35 | } 36 | 37 | let composedWithCustomOperator = extractElements |> formatWithCurrency 38 | composedWithCustomOperator("10,20,40,30,80,60") 39 | // The result will be: ["10$", "20$", "40$", "30$", "80$", "60$"] 40 | //: [Next](@next) 41 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/FunctionCurrying.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func extractFullName(firstName: String, lastName: String) -> String { 6 | return "\(firstName) \(lastName)" 7 | } 8 | 9 | // Pre Swift 3.0 10 | //func curriedExtractFullUserName(firstName: String)(lastName: String) -> String { 11 | // return "\(firstName) \(lastName)" 12 | //} 13 | // 14 | //let fnIncludingFirstName = curriedExtractFullUserName("John") 15 | //let extractedFullName = fnIncludingFirstName(lastName: "Doe") 16 | 17 | // Swift 3.0 syntax 18 | 19 | // Before: 20 | //func curried(x: Int)(y: String) -> Float { 21 | // return Float(x) + Float(y)! 22 | //} 23 | 24 | // Swift 3.0 syntax: 25 | func curried(x: Int) -> (String) -> Float { 26 | return { 27 | (y: String) -> Float in 28 | return Float(x) + Float(y)! 29 | } 30 | } 31 | 32 | // Explicitly return closures 33 | 34 | func explicityRetunClosure(firstName: String) -> (String) -> String { 35 | return { 36 | (lastName: String) -> String in 37 | return "\(firstName) \(lastName)" 38 | } 39 | } 40 | 41 | let fnIncludingFirstName = explicityRetunClosure(firstName: "John") 42 | let extractedFullName = fnIncludingFirstName("Doe") 43 | 44 | //: [Next](@next) 45 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/HigherOrderFunctions.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func subtractTwoValues(a: Int, b: Int) -> Int { 6 | return a - b 7 | } 8 | 9 | func addTwoValues(a: Int, b: Int) -> Int { 10 | return a + b 11 | } 12 | 13 | func square(a: Int) -> Int { 14 | return a * a 15 | } 16 | 17 | func triple(a: Int) -> Int { 18 | return a * a * a // or return square(a) * a 19 | } 20 | 21 | func subtractTwoSquaredValues(a: Int, b: Int) -> Int { 22 | return (a * a) - (b * b) 23 | } 24 | 25 | func addTwoSquaredValues(a: Int, b: Int) -> Int { 26 | return (a * a) + (b * b) 27 | } 28 | 29 | func multiplyTwoTripledValues(a: Int, b: Int) -> Int { 30 | return (a * a * a) * (b * b * b) 31 | } 32 | 33 | typealias AddSubtractOperator = (Int, Int) -> Int 34 | typealias SquareTripleOperator = (Int) -> Int 35 | 36 | func calculate(a: Int, b: Int, funcA: AddSubtractOperator, funcB: SquareTripleOperator) -> Int { 37 | return funcA(funcB(a), funcB(b)) 38 | } 39 | 40 | print("The result of adding two squared values is: \(calculate(a: 2, b: 2, funcA: addTwoValues, funcB: square))") // prints “The result of adding two squared value is: 8” 41 | 42 | print("The result of subtracting two tripled value is: \(calculate(a: 3, b: 2, funcA: subtractTwoValues, funcB: triple))") // prints “The result of adding two tripled value is: 19” 43 | 44 | //: [Next](@next) 45 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/Memoization.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Simple memoization 6 | 7 | var memo = Dictionary() 8 | 9 | func memoizedPower2(n: Int) -> Int { 10 | if let memoizedResult = memo[n] { 11 | return memoizedResult 12 | } 13 | var y = 1 14 | for _ in 0...n-1 { 15 | y *= 2 16 | } 17 | memo[n] = y 18 | return y 19 | } 20 | print(memoizedPower2(n: 2)) 21 | print(memoizedPower2(n: 3)) 22 | print(memoizedPower2(n: 4)) 23 | print(memo) // result: [2: 4, 3: 8, 4: 16] 24 | 25 | // Advanced memoization 26 | 27 | func memoize(fn: @escaping ((T) -> U, T) -> U) -> (T) -> U { 28 | var memo = Dictionary() 29 | var result: ((T) -> U)! 30 | result = { 31 | x in 32 | if let q = memo[x] { return q } 33 | let r = fn(result, x) 34 | memo[x] = r 35 | return r 36 | } 37 | return result 38 | } 39 | 40 | let factorial = memoize { 41 | factorial, x in 42 | x == 0 ? 1 : x * factorial(x - 1) 43 | } 44 | 45 | print(factorial(5)) 46 | 47 | let powerOf2 = memoize { 48 | pow2, x in 49 | x == 0 ? 1 : 2 * pow2(x - 1) 50 | } 51 | 52 | print(powerOf2(5)) 53 | 54 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/NestedFunctions.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func choosePlusMinus(isPlus: Bool) -> (Int, Int) -> Int { 6 | func plus(a: Int, b: Int) -> Int { 7 | return a + b 8 | } 9 | func minus(a: Int, b: Int) -> Int { 10 | return a - b 11 | } 12 | return isPlus ? plus : minus 13 | } 14 | 15 | //: [Next](@next) 16 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/Recursion.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | /* 6 | func factorial(n: Int) -> Int { 7 | return n * factorial(n: n - 1) 8 | } 9 | */ 10 | 11 | func factorial(n: Int) -> Int { 12 | return n == 0 || n == 1 ? 1 : n * factorial(n: n - 1) 13 | } 14 | 15 | print(factorial(n: 3)) 16 | 17 | // recursive example 18 | 19 | func powerOfTwo(n: Int) -> Int { 20 | return n == 0 ? 1 : 2 * powerOfTwo(n: n - 1) 21 | } 22 | 23 | let fnResult = powerOfTwo(n: 3) 24 | 25 | // Non-recursive version 26 | 27 | func power2(n: Int) -> Int { 28 | var y = 1 29 | for _ in 0...n - 1 { 30 | y *= 2 31 | } 32 | return y 33 | } 34 | 35 | let result = power2(n: 4) 36 | 37 | // Recursive example 38 | 39 | func repateString(str: String, n: Int) -> String { 40 | return n == 0 ? "" : str + repateString(str: str , n: n - 1) 41 | } 42 | 43 | print(repateString(str: "Hello", n: 4)) 44 | 45 | // Non-recursive version 46 | 47 | func repeatString(str: String, n: Int) -> String { 48 | var ourString = "" 49 | for _ in 1...n { 50 | ourString += str 51 | } 52 | return ourString 53 | } 54 | 55 | print(repeatString(str: "Hello", n: 4)) 56 | 57 | 58 | //: [Next](@next) 59 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | /*: Markdown documentation 3 | 4 | ### Table of contents 5 | * [Function Definition and usage](Definition) 6 | * [Function Types](FunctionTypes) 7 | * [Nested Functions](NestedFunctions) 8 | * [First Class Functions](FirstClassFunctions) 9 | * [Higher Order Functions](HigherOrderFunctions) 10 | * [Function Compostion](FunctionComposition) 11 | * [Closures](Closures) 12 | * [Capturing Values with Closures](CapturingValues) 13 | * [Function Currying](FunctionCurrying) 14 | * [Recursion](Recursion) 15 | * [Tail Recursion](TailRecursion) 16 | * [Memoization](Memoization) 17 | 18 | */ 19 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/Pages/TailRecursion.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func factorial(n: Int, currentFactorial: Int = 1) -> Int { 6 | return n == 0 ? currentFactorial : factorial(n: n - 1, currentFactorial: currentFactorial * n) 7 | } 8 | 9 | print(factorial(n: 3)) 10 | 11 | /* 12 | factorial(n: 3, currentFactorial: 1) 13 | return factorial(n: 2, currentFactorial: 1 * 3) // n = 3 14 | return factorial(n: 1, currentFactorial: 3 * 2) // n = 2 15 | return 6 // n = 1 16 | */ 17 | 18 | 19 | 20 | //: [Next](@next) 21 | -------------------------------------------------------------------------------- /Chapter02/Playgrounds/Ch02-FuncsClosures.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter03/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/Copying.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | class User { 6 | var name: String 7 | init(name: String) { 8 | self.name = name 9 | } 10 | } 11 | 12 | let julie = User(name: "Julie") 13 | let steve = User(name: "Steve") 14 | let alain = User(name: "Alain") 15 | let users = [alain, julie, steve] 16 | 17 | let copyOfUsers = users 18 | users[0].name = "Jean-Marc" 19 | 20 | print(users[0].name) // prints "Jean-Marc" 21 | print(copyOfUsers[0].name) // prints "Jean-Marc" 22 | 23 | 24 | //: [Next](@next) 25 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/CopyingReferenceTypes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | class Manager: NSObject, NSCopying { 6 | var firstName: String 7 | var lastName: String 8 | var age: Int 9 | 10 | init(firstName: String, lastName: String, age: Int) { 11 | self.firstName = firstName 12 | self.lastName = lastName 13 | self.age = age 14 | } 15 | 16 | func copy(with: NSZone? = nil) -> Any { 17 | let copy = Manager(firstName: firstName, lastName: lastName, age: age) 18 | return copy 19 | } 20 | } 21 | 22 | let john = Manager(firstName: "John", lastName: "Doe", age: 35) 23 | let jane = john.copy() as! Manager 24 | 25 | jane.firstName = "Jane" 26 | jane.lastName = "Doe" 27 | jane.age = 40 28 | 29 | print("\(john.firstName) \(john.lastName) is \(john.age)") 30 | print("\(jane.firstName) \(jane.lastName) is \(jane.age)") 31 | 32 | 33 | //: [Next](@next) 34 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/EqualityVsIdentity.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | class User { 6 | var name: String 7 | init(name: String) { 8 | self.name = name 9 | } 10 | } 11 | 12 | let firstNumber = 1 13 | let secondNumber = 1 14 | 15 | if firstNumber == secondNumber { 16 | print("Two numbers are equal") // prints "Two numbers are equal\n" 17 | } 18 | 19 | let tarang = User(name: "Tarang") 20 | let sangeeth = User(name: "Sangeeth") 21 | 22 | if tarang === sangeeth { 23 | print("Identical") 24 | } else { 25 | print("Not identical") // prints "Not identical" 26 | } 27 | 28 | //: [Next](@next) 29 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/EquatableComparable.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | /* 6 | struct Point { 7 | let x: Double 8 | let y: Double 9 | } 10 | 11 | let firstPoint = Point(x: 3.0, y: 5.5) 12 | let secondPoint = Point(x: 7.0, y: 9.5) 13 | 14 | let isEqual = (firstPoint == secondPoint) // Compile error - Binary operator '==' cannot be apploed to two 'Point' operands 15 | */ 16 | 17 | /* 18 | struct Point: Equatable { 19 | let x: Double 20 | let y: Double 21 | } 22 | 23 | func ==(lhs: Point, rhs:Point) -> Bool { 24 | return (lhs.x == rhs.x) && (lhs.y == lhs.y) 25 | } 26 | 27 | let firstPoint = Point(x: 3.0, y: 5.5) 28 | let secondPoint = Point(x: 7.0, y: 9.5) 29 | 30 | let isEqual = (firstPoint == secondPoint) 31 | */ 32 | 33 | 34 | struct Point: Equatable, Comparable { 35 | let x: Double 36 | let y: Double 37 | } 38 | 39 | func ==(lhs: Point, rhs:Point) -> Bool { 40 | return (lhs.x == rhs.x) && (lhs.y == lhs.y) 41 | } 42 | 43 | func <(lhs: Point, rhs: Point) -> Bool { 44 | return (lhs.x < rhs.x) && (lhs.y < rhs.y) 45 | } 46 | 47 | let firstPoint = Point(x: 3.0, y: 5.5) 48 | let secondPoint = Point(x: 7.0, y: 9.5) 49 | 50 | let isEqual = (firstPoint == secondPoint) 51 | let isLess = (firstPoint < secondPoint) 52 | 53 | //: [Next](@next) 54 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/MixingValueReferenceTypes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | class User { 6 | var name: String 7 | init(name: String) { 8 | self.name = name 9 | } 10 | } 11 | let julie = User(name: "Julie") 12 | 13 | struct Student { 14 | var user: User 15 | } 16 | 17 | let student = Student(user:julie) 18 | student.user.name // prints "Julie" 19 | let anotherStudent = student 20 | julie.name = "Julie Jr." 21 | anotherStudent.user.name // prints "Julie Jr." 22 | 23 | //: [Next](@next) 24 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | /*: Markdown documentation 3 | 4 | ### Table of contents 5 | * [Value Types vs. Reference Types](ValueVsReferenceTypes) 6 | * [Mixing Value Types and Reference Types](MixingValueReferenceTypes) 7 | * [Copying](Copying) 8 | * [Copying Reference Types](CopyingReferenceTypes) 9 | * [Equality vs. Identity](EqualityVsIdentity) 10 | * [Equatable and Comparable](EquatableComparable) 11 | * [Type Checking and Type Casting](TypeCheckingCasting) 12 | 13 | */ 14 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/TypeCheckingCasting.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let aConstant = "String" 6 | 7 | if aConstant is String { 8 | print("aConstant is a String") 9 | } else { 10 | print("aConstant is not a String") 11 | } 12 | 13 | let anyString: Any = "string" 14 | 15 | if anyString is String { 16 | print("anyString is a String") 17 | } else { 18 | print("anyString is not a String") 19 | } 20 | 21 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/Pages/ValueVsReferenceTypes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // struct with copying behavior 6 | 7 | struct ourStruct { 8 | var data: Int = 3 9 | } 10 | 11 | var valueA = ourStruct() 12 | var valueB = valueA // valueA is copied to valueB 13 | valueA.data = 5 // Changes valueA, not valueB 14 | print("\(valueA.data), \(valueB.data)") // prints "5, 3" 15 | 16 | // class with referencing behavior 17 | 18 | class ourClass { 19 | var data: Int = 3 20 | } 21 | 22 | var referenceA = ourClass() 23 | var referenceB = referenceA // referenceA is copied to referenceB 24 | referenceA.data = 5 // changes the instance referred to by referenceA and referenceB 25 | print("\(referenceA.data), \(referenceB.data)") // prints "5, 5" 26 | 27 | // Value and reference type constans 28 | 29 | class User { 30 | var name: String 31 | init(name: String) { 32 | self.name = name 33 | } 34 | } 35 | 36 | let grace = User(name: "Grace") 37 | let tamina = User(name: "Tamina") 38 | 39 | struct Student { 40 | var user: User 41 | } 42 | 43 | let student = Student(user: grace) 44 | // student.user = tamina // compiler error - cannot assign to property: 'student' is a 'let' constant 45 | 46 | tamina.name = "Su Tamina" 47 | print(tamina.name) // prints "Su Tamina" 48 | 49 | //: [Next](@next) 50 | -------------------------------------------------------------------------------- /Chapter03/Playgrounds/Ch03-Types.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter04/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter04/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter04/Playgrounds/Ch04-EnumsPatternMatching.playground/Pages/Definition.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | enum MLSTeam { 6 | case montreal 7 | case toronto 8 | case newYork 9 | case columbus 10 | case losAngeles 11 | case seattle 12 | } 13 | 14 | //let theTeam = MLSTeam.montreal 15 | 16 | /* 17 | 18 | enum MLSTeam { 19 | case montreal, toronto, newYork, columbus, losAngeles, Seattle 20 | } 21 | */ 22 | 23 | var theTeam = MLSTeam.montreal 24 | 25 | 26 | theTeam = .newYork 27 | 28 | // Associated values 29 | 30 | enum Length { 31 | case us(Double) 32 | case metric(Double) 33 | } 34 | 35 | let lengthMetric = Length.metric(1.6) 36 | 37 | // Raw values 38 | 39 | enum HttpError: Int { 40 | case badRequest = 400 41 | case unauthorized = 401 42 | case forbidden = 403 43 | } 44 | 45 | let possibleError = HttpError(rawValue: 400) 46 | print(possibleError?.rawValue ?? 404) // prints 400 47 | 48 | -------------------------------------------------------------------------------- /Chapter04/Playgrounds/Ch04-EnumsPatternMatching.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | /*: Markdown documentation 3 | 4 | ### Table of contents 5 | * [Definition](Definition) 6 | * [Algebraic Data Types](AlgebraicDataTypes) 7 | * [Pattern Matching](PatternMatching) 8 | * [Patterns](Patterns) 9 | 10 | */ 11 | -------------------------------------------------------------------------------- /Chapter04/Playgrounds/Ch04-EnumsPatternMatching.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter05/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter05/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter05/Playgrounds/Ch05-Generics.playground/Pages/ExtendingGenericTypes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | struct Queue { 6 | var elements = [Element]() 7 | mutating func enQueue(newElement: Element) { 8 | elements.append(newElement) 9 | } 10 | 11 | mutating func deQueue() -> Element? { 12 | guard !elements.isEmpty else { 13 | return nil 14 | } 15 | return elements.remove(at: 0) 16 | } 17 | } 18 | 19 | extension Queue { 20 | func peek() -> Element? { 21 | return elements.first 22 | } 23 | } 24 | 25 | //: [Next](@next) 26 | -------------------------------------------------------------------------------- /Chapter05/Playgrounds/Ch05-Generics.playground/Pages/GenericDataStructures.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | enum GenericTree { 6 | case empty 7 | case leaf(T) 8 | indirect case node(GenericTree, GenericTree) 9 | } 10 | 11 | print(GenericTree.node(GenericTree.leaf("First"), GenericTree.node(GenericTree.leaf("Second"), GenericTree.leaf("Third")))) 12 | // prints node(GenericTree.leaf("First"), GenericTree.node(GenericTree.leaf("Second"), GenericTree.leaf("Third"))) 13 | 14 | 15 | struct Queue { 16 | private var elements = [Element]() 17 | mutating func enQueue(newElement: Element) { 18 | elements.append(newElement) 19 | } 20 | 21 | mutating func deQueue() -> Element? { 22 | guard !elements.isEmpty else { 23 | return nil 24 | } 25 | return elements.remove(at: 0) 26 | } 27 | } 28 | 29 | //: [Next](@next) 30 | -------------------------------------------------------------------------------- /Chapter05/Playgrounds/Ch05-Generics.playground/Pages/SubclassingGenericClasses.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | class Container { 6 | } 7 | 8 | // GenericContainer stays generic 9 | class GenericContainer: Container { 10 | } 11 | 12 | // SpecificContainer becomes a container of Int type 13 | class SpecificContainer: Container { 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/Playgrounds/Ch05-Generics.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: Markdown documentation 2 | 3 | ### Table of contents 4 | * [Definition](Definition) 5 | * [Type Constraints](TypeConstraints) 6 | * [Generic Data Structures](GenericDataStructures) 7 | * [Associated Type Protocols](AssociatedTypeProtocols) 8 | * [Extending Generic Types](ExtendingGenericTypes) 9 | * [Subclassing Generic Classes](SubclassingGenericClasses) 10 | */ 11 | 12 | -------------------------------------------------------------------------------- /Chapter05/Playgrounds/Ch05-Generics.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter05/Playgrounds/Ch05-Generics.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter05/Playgrounds/Ch05-Generics.playground/playground.xcworkspace/xcuserdata/nayefa.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter05/Playgrounds/Ch05-Generics.playground/playground.xcworkspace/xcuserdata/nayefa.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Chapter06/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter06/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/Apply.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func apply(fn: ([T]) -> V, args: [T]) -> V { 6 | return fn(args) 7 | } 8 | 9 | let numbers = [1, 3, 5] 10 | 11 | func incrementValues(a: [Int]) -> [Int] { 12 | return a.map { $0 + 1 } 13 | } 14 | 15 | let applied = apply(fn: incrementValues, args: numbers) 16 | 17 | //: [Next](@next) 18 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/ChainingHigherOrderFuncs.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | struct User { 6 | let name: String 7 | let age: Int 8 | } 9 | 10 | let users = [ 11 | User(name: "Fehiman", age: 60), 12 | User(name: "Neco", age: 29), 13 | User(name: "Grace", age: 1), 14 | User(name: "Tamina", age: 6), 15 | User(name: "Negar", age: 27) 16 | ] 17 | 18 | let totalAge = users.map { $0.age }.reduce(0) { $0 + $1 } 19 | totalAge 20 | 21 | //: [Next](@next) 22 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/Filter.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let numbers = [10, 30, 91, 50, 100, 39, 74] 6 | let evenNumbers = numbers.filter { $0 % 2 == 0 } 7 | 8 | func filter(elements: [Element], predicate: ((Element) -> Bool)) -> [Element] { 9 | var result = [Element]() 10 | for element in elements { 11 | if predicate(element) { 12 | result.append(element) 13 | } 14 | } 15 | return result 16 | } 17 | 18 | let filteredArray = filter(elements: numbers) { $0 % 2 == 0 } 19 | filteredArray 20 | 21 | //: [Next](@next) 22 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/FlatMap.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let twoDimArray = [[1, 3, 5], [2, 4, 6]] 6 | let oneDimArray = twoDimArray.flatMap { $0 } 7 | oneDimArray 8 | 9 | let oneDimArray2 = twoDimArray.joined().map { $0 } 10 | oneDimArray2 11 | 12 | 13 | let transofrmedOneDimArray = twoDimArray.flatMap { $0.map { $0 + 2 } } 14 | transofrmedOneDimArray 15 | 16 | 17 | let threeDimArray = [[1, [3, 5]], [2, [4, 6]]] 18 | let twoDimArray2 = threeDimArray.flatMap { $0 } 19 | twoDimArray2 20 | 21 | //: [Next](@next) 22 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/Higher-KindedTypes.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let intArray: Array = [1, 2, 3] 6 | let newArray = intArray.map { String($0) } // produces Array 7 | print(newArray) 8 | let intSet: Set = [1, 2, 3] 9 | let newSet = intSet.map { String($0) } // produces Set 10 | print(newSet) 11 | 12 | //protocol Functor { 13 | // associatedtype A 14 | // func fmap(f: A -> FB.A) -> FB 15 | //} 16 | //: [Next](@next) 17 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/Join.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func join(elements: [Element], separator: String) -> String { 6 | 7 | return elements.reduce("") { 8 | initial, element in 9 | let aSeparator = (element == elements.last) ? "" : separator 10 | return "\(initial)\(element)\(aSeparator)" 11 | } 12 | } 13 | 14 | let items = ["First", "Second", "Third"] 15 | let commaSeparatedItems = join(elements: items, separator: ", ") 16 | 17 | 18 | //: [Next](@next) 19 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/Joined.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let twoDimensionalArray = [[1, 3, 5], [2, 4, 6]] 6 | 7 | let oneDimArray2 = twoDimensionalArray.joined().map { $0 } 8 | oneDimArray2 9 | 10 | let oneDimensionalArray = twoDimensionalArray.joined().map { $0 + 2 } 11 | print(oneDimensionalArray) 12 | //: [Next](@next) 13 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/Map.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let numbers = [10, 30, 91, 50, 100, 39, 74] 6 | var formattedNumbers: [String] = [] 7 | 8 | for number in numbers { 9 | let formattedNumber = "\(number)$" 10 | formattedNumbers.append(formattedNumber) 11 | } 12 | 13 | let mappedNumbers = numbers.map { "\($0)$" } 14 | 15 | func calculate(a: T, b: T, funcA: (T, T) -> T, funcB: (T) -> T) -> T { 16 | 17 | return funcA(funcB(a), funcB(b)) 18 | } 19 | 20 | func calculate(a: T, funcA: (T) -> U) -> U { 21 | 22 | return funcA(a) 23 | } 24 | 25 | func calculate(a: [T], funcA: ([T]) -> [U]) -> [U] { 26 | 27 | return funcA(a) 28 | } 29 | 30 | func map(a: [T], transform: ([T]) -> [U]) -> [U] { 31 | return transform(a) 32 | } 33 | 34 | func map(elements: [ElementInput], transform: (ElementInput) -> ElementResult) -> [ElementResult] { 35 | 36 | var result: [ElementResult] = [] 37 | for element in elements { 38 | result.append(transform(element)) 39 | } 40 | return result 41 | } 42 | 43 | let result = map(elements: numbers, transform: { $0 + 2 }) 44 | print(result) 45 | 46 | //: [Next](@next) 47 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: Markdown documentation 2 | 3 | ### Table of contents 4 | * [Higher-Kinded Types](Higher-KindedTypes) 5 | * [map()](Map) 6 | * [flatMap()](FlatMap) 7 | * [flatten()](Flatten) 8 | * [filter()](Filter) 9 | * [reduce()](Reduce) 10 | * [apply()](Apply) 11 | * [join()](Join) 12 | * [Chaining Higher Order Functions](ChainingHigherOrderFuncs) 13 | * [zip()](Zip) 14 | * [Practical Examples](Examples) 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/Pages/Zip.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | let numbers = [3, 5, 9, 10] 6 | let alphabeticNumbers = ["Three", "Five", "Nine", "Ten"] 7 | 8 | let zipped = zip(alphabeticNumbers, numbers).map { $0 } 9 | 10 | zipped 11 | 12 | //: [Next](@next) 13 | -------------------------------------------------------------------------------- /Chapter06/Playgrounds/Ch06-MapFilterReduce.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter07/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/Pages/Definition.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | // Optional value either contains a value or contains nil 6 | var optionalString: String? = "A String literal" 7 | optionalString = nil 8 | 9 | var aString: String = "A String literal" 10 | // aString = nil // Compile error 11 | 12 | /* ObjC 13 | 14 | NSString *searchedItem = [self searchItem:@"an item"]; 15 | NSString *text = @"Found item: "; 16 | NSString *message = [text stringByAppendingString:searchedItem]; 17 | 18 | */ 19 | 20 | enum Optional { 21 | case None 22 | case Some(T) 23 | } 24 | 25 | //: [Next](@next) 26 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/Pages/ErrorHandling.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func checkForPath(path: String) -> String? { 6 | // check for the path 7 | return "path" 8 | } 9 | 10 | //func readFile(path: String) -> String? { 11 | // if let restult = checkForPath(path: path) { 12 | // return restult 13 | // } else { 14 | // return nil 15 | // } 16 | //} 17 | // 18 | //if let result = readFile(path: "path/to") { 19 | // // Do something with result 20 | //} 21 | 22 | 23 | enum Result: Error { 24 | case failure 25 | case success 26 | } 27 | 28 | func readFile(path: String) throws -> String { 29 | if let restult = checkForPath(path: path) { 30 | return restult 31 | } else { 32 | throw Result.failure 33 | } 34 | } 35 | 36 | do { 37 | let result = try readFile(path: "path/to") 38 | } catch { 39 | print(error) 40 | } 41 | 42 | let result = try! readFile(path: "path/to") 43 | 44 | let result2 = try? readFile(path: "path/to") 45 | 46 | 47 | //: [Next](@next) 48 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/Pages/Guard.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | func greet(person: [String: String]) { 6 | guard let name = person["name"] else { 7 | return 8 | } 9 | print("Hello Ms \(name)!") 10 | } 11 | 12 | greet(person: ["name": "Neco"]) // prints "Hello Ms Neco!" 13 | 14 | func extractValue(dict: [String: Int]) { 15 | guard let firstValue = dict["One"], 16 | let secondValue = dict["Two"], 17 | let thirdValue = dict["Three"] 18 | else { 19 | return 20 | } 21 | print("\(firstValue) \(secondValue) \(thirdValue)") 22 | } 23 | 24 | //: [Next](@next) 25 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/Pages/ImplicitlyUnwrappedOptionals.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | 6 | let optionalDict: Dictionary? = ["One": 1, "Two": 2, "Three": 3] 7 | let implicitlyUnwrappedDict: Dictionary! = ["One": 1, "Two": 2, "Three": 3] 8 | 9 | let firstValue = optionalDict?["One"] 10 | let implictlyUnwrappedFirstValue = implicitlyUnwrappedDict["One"] 11 | 12 | //: [Next](@next) 13 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/Pages/OptionalChaining.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | class Residence { 6 | var numberOfRooms = 1 7 | } 8 | 9 | class Person { 10 | var residence: Residence? 11 | } 12 | 13 | let residence = Residence() 14 | residence.numberOfRooms = 5 15 | 16 | let sangeeth = Person() 17 | sangeeth.residence = residence 18 | 19 | if let roomCount = sangeeth.residence?.numberOfRooms { 20 | // Use the roomCount 21 | print(roomCount) 22 | } 23 | 24 | let roomCount = sangeeth.residence!.numberOfRooms 25 | 26 | 27 | //: [Next](@next) 28 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: Markdown documentation 2 | 3 | ### Table of contents 4 | * [Definition](Definition) 5 | * [Unwrapping](Unwrapping) 6 | * [Guard](Guard) 7 | * [Implicitly Unwrapped Optionals](ImplicitlyUnwrappedOptionals) 8 | * [Error Handling to Avoid Optionals](ErrorHandlingToAvoidOptionals) 9 | * [Optional Chaining](OptionalChaining) 10 | * [Optional Mapping](OptionalMapping) 11 | */ 12 | 13 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/Pages/Unwrapping.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | var anOptional: Optional 6 | 7 | var optionalString: String? = "A String literal" 8 | 9 | // Unwrapping optionals 10 | 11 | print(optionalString) 12 | 13 | // Force unwrapping 14 | 15 | print(optionalString!) 16 | 17 | // nil checking 18 | 19 | if optionalString != nil { 20 | print(optionalString!) 21 | } 22 | 23 | // Optional binding 24 | 25 | let nilName:String? = nil 26 | if let familyName = nilName { 27 | let greetingfamilyName = "Hello, Mr. \(familyName)" 28 | } else { 29 | // Optional does not have a value 30 | } 31 | 32 | let dict = ["One": 1, "Two": 2, "Three": 3] 33 | 34 | if let firstValue = dict["One"] { 35 | if let secondValue = dict["Two"] { 36 | if let thirdValue = dict["Three"] { 37 | // Do something with three values 38 | } 39 | } 40 | } 41 | 42 | // Multiple optional binding 43 | 44 | if let firstValue = dict["One"], 45 | let secondValue = dict["Two"], 46 | let thirdValue = dict["Three"] { 47 | print("\(firstValue) \(secondValue) \(thirdValue)") // prints 1 2 3 48 | } 49 | 50 | //: [Next](@next) 51 | -------------------------------------------------------------------------------- /Chapter07/Playgrounds/Ch07-Optionals.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter08/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter08/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter08/Playgrounds/Ch08-FunctionalDataStructures.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: Markdown documentation 2 | 3 | ### Table of contents 4 | * [Semigroup](Semigroup) 5 | * [Monoid](Monoid) 6 | * [Trees](Trees) 7 | * [Linked List](LinkedList) 8 | * [Stack](Stack) 9 | * [Lazy List](LazyList) 10 | */ 11 | 12 | -------------------------------------------------------------------------------- /Chapter08/Playgrounds/Ch08-FunctionalDataStructures.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter09/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter09/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter09/Playgrounds/Ch09-ImportanceOfImmutability.playground/Pages/FunctionalExample.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | struct Producer { 6 | let name: String 7 | let address: String 8 | } 9 | 10 | struct FunctionalProduct { 11 | let name: String 12 | let price: Double 13 | let quantity: Int 14 | let producer: Producer 15 | } 16 | 17 | struct FunctionalProductTracker { 18 | let products: [FunctionalProduct] 19 | let lastModified: Date 20 | 21 | func addNewProduct(item: FunctionalProduct) -> (date: Date, products: [FunctionalProduct]) { 22 | let newProducts = self.products + [item] 23 | return (date: Date(), products: newProducts) 24 | } 25 | } 26 | 27 | 28 | 29 | //: [Next](@next) 30 | -------------------------------------------------------------------------------- /Chapter09/Playgrounds/Ch09-ImportanceOfImmutability.playground/Pages/TableOfContents.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: Markdown documentation 2 | 3 | ### Table of contents 4 | * [Definition](Definition) 5 | * [Functional Example](FunctionalExample) 6 | * [Copy Constructor](CopyConstructor) 7 | * [Lens](Lens) 8 | */ 9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter09/Playgrounds/Ch09-ImportanceOfImmutability.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Chapter10/Playgrounds/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter10/Playgrounds/.DS_Store -------------------------------------------------------------------------------- /Chapter10/Playgrounds/Ch10-BestOfBothWorlds.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter11/Ch11-Backend/.DS_Store -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter11/Ch11-Backend/vapor-example/.DS_Store -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/.gitignore: -------------------------------------------------------------------------------- 1 | Packages 2 | .build 3 | xcuserdata 4 | *.xcodeproj 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/.swift-version: -------------------------------------------------------------------------------- 1 | system -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | - osx 4 | language: generic 5 | sudo: required 6 | dist: trusty 7 | osx_image: xcode8 8 | install: 9 | - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)" 10 | script: 11 | - swift build 12 | - swift build -c release 13 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Config/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "default-key", 3 | "foo": "bar" 4 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Config/development/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "development-key" 3 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Config/production/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "$VAPOR_APP_KEY" 3 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Config/production/servers.json: -------------------------------------------------------------------------------- 1 | { 2 | "production": { 3 | "port": "$PORT" 4 | } 5 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Config/secrets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter11/Ch11-Backend/vapor-example/Config/secrets/.gitkeep -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Config/secrets/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "secret-key" 3 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Config/servers.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": { 3 | "port": 8080, 4 | "host": "0.0.0.0", 5 | "securityLayer": "none" 6 | } 7 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Tanner Nelson 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 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Localization/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": { 3 | "title": "Default Welcome Message", 4 | "body": "Default welcome body." 5 | }, 6 | "other-key": "example" 7 | } 8 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Localization/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": { 3 | "title": "Welcome to Vapor!", 4 | "body": "A web framework for Swift." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Localization/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": { 3 | "title": "¡Bienvenidos a Vapor!", 4 | "body": "Un framework web de Swift." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "VaporApp", 5 | dependencies: [ 6 | .Package(url: "https://github.com/vapor/vapor.git", majorVersion: 1, minor: 3) 7 | ], 8 | exclude: [ 9 | "Config", 10 | "Database", 11 | "Localization", 12 | "Public", 13 | "Resources", 14 | "Tests", 15 | ] 16 | ) 17 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Procfile: -------------------------------------------------------------------------------- 1 | web: App --env=production --workdir="./" 2 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Public/images/vapor-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter11/Ch11-Backend/vapor-example/Public/images/vapor-logo.png -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Public/styles/app.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body, html { 6 | padding: 0; 7 | margin: 0; 8 | height: 100%; 9 | } 10 | 11 | body { 12 | font-family: sans-serif; 13 | color: #333; 14 | position: relative; 15 | } 16 | 17 | 18 | a { 19 | color: #92A8D1; 20 | text-decoration: none; 21 | border-bottom: 1px dotted; 22 | } 23 | 24 | a:hover { 25 | color: #F7CAC9; 26 | } 27 | 28 | div.wrapper { 29 | width: 100%; 30 | max-width: 600px; 31 | margin: 0 auto; 32 | position: relative; 33 | top: 50%; 34 | transform: translateY(-50%); 35 | margin-top: -25px; //adjust eye level 36 | } 37 | 38 | h1#logo { 39 | text-indent: -9999px; 40 | background-image: url(../images/vapor-logo.png); 41 | background-size: 100%; 42 | width: 347.5px; 43 | height: 84px; 44 | margin: 0 auto; 45 | } 46 | 47 | nav.main { 48 | text-align: center; 49 | margin-top: 20px; 50 | } 51 | nav.main ul { 52 | margin: 0; 53 | padding: 0; 54 | } 55 | nav.main ul li { 56 | display: inline-block; 57 | padding: 0 5px; 58 | } 59 | 60 | 61 | footer.main { 62 | position: absolute; 63 | width: 100%; 64 | text-align: center; 65 | bottom: 10px; 66 | } 67 | 68 | footer.main p { 69 | margin: 0; 70 | padding: 0; 71 | color: #ccc; 72 | font-weight: 300; 73 | } 74 | 75 | footer.main p a { 76 | color: #ccc; 77 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Resources/Views/embeds/header.leaf: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Resources/Views/template.leaf: -------------------------------------------------------------------------------- 1 | #embed("embeds/header") 2 | 3 |

#(greeting)

4 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Resources/Views/welcome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vapor 5 | 6 | 7 | 8 | 9 |
10 |

Vapor

11 | 12 | 21 |
22 | 23 |
24 |

Powered by Swift. Built by Tanner.

25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Sources/App/Middleware/SampleMiddleware.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | import HTTP 3 | 4 | class SampleMiddleware: Middleware { 5 | 6 | func respond(to request: Request, chainingTo chain: Responder) throws -> Response { 7 | // You can manipulate the request before calling the handler 8 | // and abort early if necessary, a good injection point for 9 | // handling auth. 10 | 11 | // return Response(status: .Forbidden, text: "Permission denied") 12 | 13 | let response = try chain.respond(to: request) 14 | 15 | // You can also manipulate the response to add headers 16 | // cookies, etc. 17 | 18 | return response 19 | 20 | // Vapor Middleware is based on S4 Middleware. 21 | // This means you can share it with any other project 22 | // that uses S4 Middleware. 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/Sources/App/Models/User.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | import Fluent 3 | 4 | final class User: Model { 5 | var id: Node? 6 | var name: String 7 | 8 | init(name: String) { 9 | self.name = name 10 | } 11 | 12 | init(node: Node, in context: Context) throws { 13 | id = try node.extract("id") 14 | name = try node.extract("name") 15 | } 16 | 17 | func makeNode(context: Context) throws -> Node { 18 | return try Node(node: [ 19 | "name": name 20 | ]) 21 | } 22 | 23 | static func prepare(_ database: Database) throws { 24 | // 25 | } 26 | 27 | static func revert(_ database: Database) throws { 28 | // 29 | } 30 | } 31 | 32 | extension User { 33 | public convenience init?(from string: String) throws { 34 | self.init(name: string) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Backend/vapor-example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vapor-example", 3 | "scripts": {}, 4 | "env": {}, 5 | "formation": {}, 6 | "addons": [], 7 | "buildpacks": [ 8 | { 9 | "url": "https://github.com/kylef/heroku-buildpack-swift" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter11/Ch11-Frontend/.DS_Store -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/Chapter11/Ch11-Frontend/TodoApp/.DS_Store -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, ‘9.0’ 2 | use_frameworks! 3 | 4 | target 'TodoApp' do 5 | pod 'Alamofire', '~> 4.0' 6 | pod 'Argo' 7 | pod 'Curry' 8 | pod 'ReactiveCocoa', '~> 5.0.0' 9 | pod 'Delta', :git => "https://github.com/conqueror/Delta.git" 10 | end 11 | 12 | target 'TodoAppTests' do 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.0.1) 3 | - Argo (4.0.0): 4 | - Runes (>= 4.0.0) 5 | - Curry (3.0.0) 6 | - Delta (1.0.0) 7 | - ReactiveCocoa (5.0.0-rc.1): 8 | - ReactiveSwift (~> 1.0.0-rc.3) 9 | - ReactiveSwift (1.0.0): 10 | - Result (~> 3.1) 11 | - Result (3.1.0) 12 | - Runes (4.0.0) 13 | 14 | DEPENDENCIES: 15 | - Alamofire (~> 4.0) 16 | - Argo 17 | - Curry 18 | - Delta (from `https://github.com/conqueror/Delta.git`) 19 | - ReactiveCocoa (= 5.0.0-rc.1) 20 | 21 | EXTERNAL SOURCES: 22 | Delta: 23 | :git: https://github.com/conqueror/Delta.git 24 | 25 | CHECKOUT OPTIONS: 26 | Delta: 27 | :commit: ba1909a3f7ad7fd12f6c905e2a8fac9d4dccf7d0 28 | :git: https://github.com/conqueror/Delta.git 29 | 30 | SPEC CHECKSUMS: 31 | Alamofire: 7682d43245de14874acd142ec137b144aa1dd335 32 | Argo: e808d20ee2e95c4498276ca1812d75d3b0b00090 33 | Curry: eb3d2c75aec678b3cc7fb2729d2ad6dd121531d1 34 | Delta: 117de8f078ce0b95c6e6e0c75656f1918f9b1ce9 35 | ReactiveCocoa: 3e9cad4b77fa199d41e03f603cb55d0701ad6ad8 36 | ReactiveSwift: f391724ee318a2cfd3e37dfb041cd49ecf4e7869 37 | Result: 4e3ed5995ed94d0cd6a09be9a431fce3f3624bbf 38 | Runes: 423ee2dac4dedb4626a859c0962c934195ba8433 39 | 40 | PODFILE CHECKSUM: b327f6157f08a1ca714d505f58aa64a7eb97603b 41 | 42 | COCOAPODS: 1.1.1 43 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Alamofire/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 thoughtbot, inc. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Extensions/Dictionary.swift: -------------------------------------------------------------------------------- 1 | import Runes 2 | 3 | // pure merge for Dictionaries 4 | func + (lhs: [T: U], rhs: [T: U]) -> [T: U] { 5 | var merged = lhs 6 | for (key, val) in rhs { 7 | merged[key] = val 8 | } 9 | 10 | return merged 11 | } 12 | 13 | extension Dictionary { 14 | func map(_ f: (Value) -> T) -> [Key: T] { 15 | var accum = Dictionary(minimumCapacity: self.count) 16 | 17 | for (key, value) in self { 18 | accum[key] = f(value) 19 | } 20 | 21 | return accum 22 | } 23 | } 24 | 25 | func <^> (f: (T) -> U, x: [V: T]) -> [V: U] { 26 | return x.map(f) 27 | } 28 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Extensions/NSNumber.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension NSNumber { 4 | var isBool: Bool { 5 | return type(of: self) == type(of: NSNumber(value: true)) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Extensions/RawRepresentable.swift: -------------------------------------------------------------------------------- 1 | /** 2 | Default implementation of `Decodable` for `RawRepresentable` types using 3 | `String` as the raw value. 4 | */ 5 | public extension Decodable where Self.DecodedType == Self, Self: RawRepresentable, Self.RawValue == String { 6 | static func decode(_ json: JSON) -> Decoded { 7 | switch json { 8 | case let .string(s): 9 | return self.init(rawValue: s) 10 | .map(pure) ?? .typeMismatch(expected: "rawValue for \(self)", actual: json) 11 | default: 12 | return .typeMismatch(expected: "String", actual: json) 13 | } 14 | } 15 | } 16 | 17 | /** 18 | Default implementation of `Decodable` for `RawRepresentable` types using 19 | `Int` as the raw value. 20 | */ 21 | public extension Decodable where Self.DecodedType == Self, Self: RawRepresentable, Self.RawValue == Int { 22 | static func decode(_ json: JSON) -> Decoded { 23 | switch json { 24 | case let .number(n): 25 | return self.init(rawValue: n.intValue) 26 | .map(pure) ?? .typeMismatch(expected: "rawValue for \(self)", actual: json) 27 | default: 28 | return .typeMismatch(expected: "Int", actual: json) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Functions/flatReduce.swift: -------------------------------------------------------------------------------- 1 | import Runes 2 | 3 | /** 4 | Reduce a sequence with a combinator that returns a `Decoded` type, flattening 5 | the result. 6 | 7 | This function is a helper function to make it easier to deal with combinators 8 | that return `Decoded` types without ending up with multiple levels of nested 9 | `Decoded` values. 10 | 11 | For example, it can be used to traverse a JSON structure with an array of 12 | keys. See the implementations of `<|` and `<||` that take an array of keys for 13 | a real-world example of this use case. 14 | 15 | - parameter sequence: Any `SequenceType` of values 16 | - parameter initial: The initial value for the accumulator 17 | - parameter combine: The combinator, which returns a `Decoded` type 18 | 19 | - returns: The result of iterating the combinator over every element of the 20 | sequence and flattening the result 21 | */ 22 | public func flatReduce(_ sequence: S, initial: U, combine: (U, S.Iterator.Element) -> Decoded) -> Decoded { 23 | return sequence.reduce(pure(initial)) { accum, x in 24 | accum >>- { combine($0, x) } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Operators/Argo.swift: -------------------------------------------------------------------------------- 1 | import Runes 2 | 3 | precedencegroup ArgoDecodePrecedence { 4 | associativity: left 5 | higherThan: RunesApplicativeSequencePrecedence 6 | lowerThan: NilCoalescingPrecedence 7 | } 8 | 9 | infix operator <| : ArgoDecodePrecedence 10 | infix operator <|? : ArgoDecodePrecedence 11 | infix operator <|| : ArgoDecodePrecedence 12 | infix operator <||? : ArgoDecodePrecedence 13 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Types/Decodable.swift: -------------------------------------------------------------------------------- 1 | public protocol Decodable { 2 | /** 3 | The type of object that will be decoded. 4 | 5 | In order to work with the rest of Argo, this needs to be the same as `Self`. 6 | 7 | You will only need to worry about this if the object conforming to 8 | `Decodable` is a reference type (i.e. a `class`), and one of the following 9 | is true: 10 | 11 | - Your type is not marked as `final` 12 | - Your `decode` function is not marked as either `final` or `static` 13 | 14 | In that case, you will need to explicitly set `DecodedType` to the type you 15 | are returning in order for the compiler to be able to guarantee that this 16 | protocol is being fully conformed to. 17 | 18 | We expect the need for this typealias to be removed in a later version of Swift. 19 | */ 20 | associatedtype DecodedType = Self 21 | 22 | /** 23 | Decode an object from JSON. 24 | 25 | This is the main entry point for Argo. This function declares how the 26 | conforming type should be decoded from JSON. Since this is a failable 27 | operation, we need to return a `Decoded` type from this function. 28 | 29 | - parameter json: The `JSON` representation of this object 30 | 31 | - returns: A decoded instance of the `DecodedType` 32 | */ 33 | static func decode(_ json: JSON) -> Decoded 34 | } 35 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Types/Decoded/Alternative.swift: -------------------------------------------------------------------------------- 1 | import Runes 2 | 3 | /** 4 | Return the left `Decoded` value if it is `.Success`, otherwise return the 5 | default value on the right. 6 | 7 | - If the left hand side is `.Success`, this will return the argument on the 8 | left hand side. 9 | - If the left hand side is `.Failure`, this will return the argument on the 10 | right hand side. 11 | 12 | - parameter lhs: A value of type `Decoded` 13 | - parameter rhs: A value of type `Decoded` 14 | 15 | - returns: A value of type `Decoded` 16 | */ 17 | public func <|> (lhs: Decoded, rhs: @autoclosure () -> Decoded) -> Decoded { 18 | return lhs.or(rhs) 19 | } 20 | 21 | public extension Decoded { 22 | /** 23 | Return `self` if it is `.Success`, otherwise return the provided default 24 | value. 25 | 26 | - If `self` is `.Success`, this will return `self`. 27 | - If `self` is `.Failure`, this will return the default. 28 | 29 | - parameter other: A value of type `Decoded` 30 | 31 | - returns: A value of type `Decoded` 32 | */ 33 | func or(_ other: @autoclosure () -> Decoded) -> Decoded { 34 | switch self { 35 | case .success: return self 36 | case .failure: return other() 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Types/Decoded/FailureCoalescing.swift: -------------------------------------------------------------------------------- 1 | /** 2 | Return the unwrapped value of the `Decoded` value on the left if it is 3 | `.Success`, otherwise return the default on the right. 4 | 5 | - If the left hand side is `.Success`, this will return the unwrapped value 6 | from the left hand side argument. 7 | - If the left hand side is `.Failure`, this will return the default value on 8 | the right hand side. 9 | 10 | - parameter lhs: A value of type `Decoded` 11 | - parameter rhs: An autoclosure returning a value of type `T` 12 | 13 | - returns: A value of type `T` 14 | */ 15 | public func ?? (lhs: Decoded, rhs: @autoclosure () -> T) -> T { 16 | switch lhs { 17 | case let .success(x): return x 18 | case .failure: return rhs() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Argo/Sources/Argo/Types/Decoded/Functor.swift: -------------------------------------------------------------------------------- 1 | import Runes 2 | 3 | /** 4 | Conditionally map a function over a `Decoded` value. 5 | 6 | - If the value is `.Failure`, the function will not be evaluated and this 7 | will return `.Failure`. 8 | - If the value is `.Success`, the function will be applied to the unwrapped 9 | value. 10 | 11 | - parameter f: A transformation function from type `T` to type `U` 12 | - parameter x: A value of type `Decoded` 13 | 14 | - returns: A value of type `Decoded` 15 | */ 16 | public func <^> (f: (T) -> U, x: Decoded) -> Decoded { 17 | return x.map(f) 18 | } 19 | 20 | public extension Decoded { 21 | /** 22 | Conditionally map a function over `self`. 23 | 24 | - If `self` is `.Failure`, the function will not be evaluated and this will 25 | return `.Failure`. 26 | - If `self` is `.Success`, the function will be applied to the unwrapped 27 | value. 28 | 29 | - parameter f: A transformation function from type `T` to type `U` 30 | 31 | - returns: A value of type `Decoded` 32 | */ 33 | func map(_ f: (T) -> U) -> Decoded { 34 | switch self { 35 | case let .success(value): return .success(f(value)) 36 | case let .failure(error): return .failure(error) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Curry/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 thoughtbot, inc. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Delta/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Jake Craige and thoughtbot, inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Delta/Sources/Action.swift: -------------------------------------------------------------------------------- 1 | /** 2 | This protocol is used when you want to make modifications to the store's state. 3 | All changes to the store go through this type. 4 | 5 | Sample Action: 6 | 7 | ```swift 8 | struct UpdateIdAction: ActionType { 9 | let id: Int 10 | 11 | func reduce(state: AppState) -> AppState { 12 | state.id.value = id 13 | return state 14 | } 15 | } 16 | 17 | store.dispatch(UpdateIdAction(id: 1)) 18 | ``` 19 | */ 20 | public protocol ActionType { 21 | /** 22 | The type of the app's state. 23 | 24 | - note: This is inferred from the `reduce` method implementation. 25 | */ 26 | associatedtype StateValueType 27 | 28 | /** 29 | This method is called when this action is dispatched. Its purpose is to 30 | make modifications to the state and return a new version of it. 31 | 32 | - note: This is the only place that changes to the state are permitted. 33 | - parameter state: The current state of the store. 34 | - returns: The new state. 35 | */ 36 | func reduce(state: StateValueType) -> StateValueType 37 | } 38 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Delta/Sources/Delta.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for Delta. 4 | FOUNDATION_EXPORT double DeltaVersionNumber; 5 | 6 | //! Project version string for Delta. 7 | FOUNDATION_EXPORT const unsigned char DeltaVersionString[]; 8 | 9 | // In this header, you should import all the public headers of your framework using statements like #import 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Delta/Sources/DynamicAction.swift: -------------------------------------------------------------------------------- 1 | /** 2 | This protocol is used when you want to do some async behavior that updates the 3 | store. It is very minimal in that it's not allowed to modify the store 4 | directly. The async behavior is done within the `call` method and to make 5 | changes it should dispatch a synchronous action. 6 | 7 | Sample Action: 8 | 9 | ```swift 10 | struct FetchUsers: DynamicActionType { 11 | func call() { 12 | someApi.fetchUsers { users in 13 | store.dispatch(SetUsersAction(users: users)) 14 | } 15 | } 16 | } 17 | 18 | store.dispatch(UpdateIdAction(id: 1)) 19 | ``` 20 | */ 21 | public protocol DynamicActionType { 22 | /** 23 | The return type from the `call` method. 24 | 25 | - note: This is inferred from the `call` method implementation. 26 | */ 27 | associatedtype ResponseType 28 | 29 | /** 30 | This method is where you perform some async behavior that when completed, 31 | should dispatch a synchronous action on the store. 32 | 33 | You can optionally return an object that wraps async behavior. This might 34 | be a `Promise` from PromiseKit or `SignalProducer` from ReactiveCocoa. 35 | */ 36 | func call() -> ResponseType 37 | } 38 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Local Podspecs/Curry.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Curry", 3 | "version": "3.0.0", 4 | "summary": "Function Currying for Swift", 5 | "homepage": "https://github.com/thoughtbot/curry", 6 | "license": { 7 | "type": "MIT", 8 | "file": "LICENSE" 9 | }, 10 | "authors": { 11 | "Gordon Fontenot": "gordon@thoughtbot.com", 12 | "thoughtbot": null 13 | }, 14 | "social_media_url": "http://twitter.com/thoughtbot", 15 | "source": { 16 | "git": "https://github.com/thoughtbot/curry.git", 17 | "tag": "v3.0.0" 18 | }, 19 | "source_files": "Source/**/*.{h,swift}", 20 | "requires_arc": true, 21 | "platforms": { 22 | "ios": "8.0", 23 | "osx": "10.9", 24 | "watchos": "2.0", 25 | "tvos": "9.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Local Podspecs/Delta.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Delta", 3 | "version": "1.0.0", 4 | "summary": "Managing state is hard. Delta aims to make it simple.", 5 | "homepage": "https://github.com/conqueror/Delta", 6 | "license": { 7 | "type": "MIT", 8 | "file": "LICENSE" 9 | }, 10 | "authors": { 11 | "Jake Craige": "james.craige@gmail.com", 12 | "Giles Van Gruisen": "giles@thoughtbot.com", 13 | "thoughtbot": null 14 | }, 15 | "source": { 16 | "git": "https://github.com/conqueror/Delta.git", 17 | "tag": "v1.0.0", 18 | "submodules": true 19 | }, 20 | "source_files": "Sources/**/*.{h,swift}", 21 | "requires_arc": true, 22 | "platforms": { 23 | "ios": "8.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Local Podspecs/ReactiveCocoa.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactiveCocoa", 3 | "version": "5.0.0-alpha.2", 4 | "summary": "Streams of values over time", 5 | "description": "ReactiveCocoa (RAC) is a Cocoa framework built on top of ReactiveSwift. It provides APIs for using ReactiveSwift with Apple's Cocoa frameworks.", 6 | "homepage": "https://github.com/ReactiveCocoa/ReactiveCocoa", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE.md" 10 | }, 11 | "authors": "ReactiveCocoa", 12 | "platforms": { 13 | "osx": "10.9", 14 | "ios": "8.0", 15 | "tvos": "9.0", 16 | "watchos": "2.0" 17 | }, 18 | "source": { 19 | "git": "https://github.com/ReactiveCocoa/ReactiveCocoa.git", 20 | "tag": "5.0.0-alpha.2" 21 | }, 22 | "source_files": "ReactiveCocoa/*.{swift,h,m}", 23 | "private_header_files": "ReactiveCocoa/RACObjCRuntimeUtilities.h", 24 | "osx": { 25 | "source_files": "ReactiveCocoa/AppKit/*.{swift}" 26 | }, 27 | "ios": { 28 | "source_files": "ReactiveCocoa/UIKit/*.{swift}" 29 | }, 30 | "tvos": { 31 | "source_files": "ReactiveCocoa/UIKit/*.{swift}", 32 | "exclude_files": "ReactiveCocoa/UIKit/*{UIDatePicker,UISwitch}*" 33 | }, 34 | "module_map": "ReactiveCocoa/module.modulemap", 35 | "dependencies": { 36 | "ReactiveSwift": [ 37 | "~> 1.0.0-alpha.3" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.0.1) 3 | - Argo (4.0.0): 4 | - Runes (>= 4.0.0) 5 | - Curry (3.0.0) 6 | - Delta (1.0.0) 7 | - ReactiveCocoa (5.0.0-rc.1): 8 | - ReactiveSwift (~> 1.0.0-rc.3) 9 | - ReactiveSwift (1.0.0): 10 | - Result (~> 3.1) 11 | - Result (3.1.0) 12 | - Runes (4.0.0) 13 | 14 | DEPENDENCIES: 15 | - Alamofire (~> 4.0) 16 | - Argo 17 | - Curry 18 | - Delta (from `https://github.com/conqueror/Delta.git`) 19 | - ReactiveCocoa (= 5.0.0-rc.1) 20 | 21 | EXTERNAL SOURCES: 22 | Delta: 23 | :git: https://github.com/conqueror/Delta.git 24 | 25 | CHECKOUT OPTIONS: 26 | Delta: 27 | :commit: ba1909a3f7ad7fd12f6c905e2a8fac9d4dccf7d0 28 | :git: https://github.com/conqueror/Delta.git 29 | 30 | SPEC CHECKSUMS: 31 | Alamofire: 7682d43245de14874acd142ec137b144aa1dd335 32 | Argo: e808d20ee2e95c4498276ca1812d75d3b0b00090 33 | Curry: eb3d2c75aec678b3cc7fb2729d2ad6dd121531d1 34 | Delta: 117de8f078ce0b95c6e6e0c75656f1918f9b1ce9 35 | ReactiveCocoa: 3e9cad4b77fa199d41e03f603cb55d0701ad6ad8 36 | ReactiveSwift: f391724ee318a2cfd3e37dfb041cd49ecf4e7869 37 | Result: 4e3ed5995ed94d0cd6a09be9a431fce3f3624bbf 38 | Runes: 423ee2dac4dedb4626a859c0962c934195ba8433 39 | 40 | PODFILE CHECKSUM: b327f6157f08a1ca714d505f58aa64a7eb97603b 41 | 42 | COCOAPODS: 1.1.1 43 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/LICENSE.md: -------------------------------------------------------------------------------- 1 | **Copyright (c) 2012 - 2016, GitHub, Inc.** 2 | **All rights reserved.** 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/CocoaTarget.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import ReactiveSwift 3 | import enum Result.NoError 4 | 5 | /// A target that accepts action messages. 6 | internal final class CocoaTarget: NSObject { 7 | private let observer: Observer 8 | private let transform: (Any?) -> Value 9 | 10 | internal init(_ observer: Observer, transform: @escaping (Any?) -> Value) { 11 | self.observer = observer 12 | self.transform = transform 13 | } 14 | 15 | @objc internal func sendNext(_ receiver: Any?) { 16 | observer.send(value: transform(receiver)) 17 | } 18 | } 19 | 20 | internal protocol CocoaTargetProtocol: class { 21 | associatedtype Value 22 | init(_ observer: Observer, transform: @escaping (Any?) -> Value) 23 | } 24 | 25 | extension CocoaTarget: CocoaTargetProtocol {} 26 | 27 | extension CocoaTargetProtocol where Value == Void { 28 | internal init(_ observer: Observer<(), NoError>) { 29 | self.init(observer, transform: { _ in }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/Deprecations+Removals.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | 3 | extension Action { 4 | @available(*, unavailable, message:"Use the `CocoaAction` initializers instead.") 5 | public var unsafeCocoaAction: CocoaAction { fatalError() } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/NSObject+BindingTarget.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import ReactiveSwift 3 | 4 | extension Reactive where Base: NSObject { 5 | /// Creates a binding target which uses the lifetime of the object, and weakly 6 | /// references the object so that the supplied `action` is triggered only if 7 | /// the object has not deinitialized. 8 | /// 9 | /// - parameters: 10 | /// - scheduler: An optional scheduler that the binding target uses. If it 11 | /// is not specified, a UI scheduler would be used. 12 | /// - action: The action to consume values from the bindings. 13 | /// 14 | /// - returns: 15 | /// A binding target that holds no strong references to the object. 16 | public func makeBindingTarget(on scheduler: SchedulerProtocol = UIScheduler(), _ action: @escaping (Base, U) -> Void) -> BindingTarget { 17 | return BindingTarget(on: scheduler, lifetime: lifetime) { [weak base = self.base] value in 18 | if let base = base { 19 | action(base, value) 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/NSObject+ObjCRuntime.swift: -------------------------------------------------------------------------------- 1 | extension NSObject { 2 | /// The class of the instance reported by the ObjC `-class:` message. 3 | /// 4 | /// - note: `type(of:)` might return the runtime subclass, while this property 5 | /// always returns the original class. 6 | @nonobjc internal var objcClass: AnyClass { 7 | return (self as AnyObject).objcClass 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/NSObject+ReactiveExtensionsProvider.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import ReactiveSwift 3 | 4 | extension NSObject: ReactiveExtensionsProvider {} 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/NSObject+Synchronizing.swift: -------------------------------------------------------------------------------- 1 | extension NSObject { 2 | @nonobjc internal final func synchronized(execute: () throws -> Result) rethrows -> Result { 3 | objc_sync_enter(self) 4 | defer { objc_sync_exit(self) } 5 | return try execute() 6 | } 7 | } 8 | 9 | internal func synchronized(_ token: AnyObject, execute: () throws -> Result) rethrows -> Result { 10 | objc_sync_enter(token) 11 | defer { objc_sync_exit(token) } 12 | return try execute() 13 | } 14 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/ObjC+Constants.swift: -------------------------------------------------------------------------------- 1 | // Unavailable selectors in Swift. 2 | internal enum ObjCSelector { 3 | static let forwardInvocation = Selector((("forwardInvocation:"))) 4 | static let methodSignatureForSelector = Selector((("methodSignatureForSelector:"))) 5 | static let getClass = Selector((("class"))) 6 | } 7 | 8 | // Method encoding of the unavailable selectors. 9 | internal enum ObjCMethodEncoding { 10 | static let forwardInvocation = extract("v@:@") 11 | static let methodSignatureForSelector = extract("v@::") 12 | static let getClass = extract("#@:") 13 | 14 | private static func extract(_ string: StaticString) -> UnsafePointer { 15 | return UnsafeRawPointer(string.utf8Start).assumingMemoryBound(to: CChar.self) 16 | } 17 | } 18 | 19 | /// Objective-C type encoding. 20 | /// 21 | /// The enum does not cover all options, but only those that are expressive in 22 | /// Swift. 23 | internal enum ObjCTypeEncoding: Int8 { 24 | case char = 99 25 | case int = 105 26 | case short = 115 27 | case long = 108 28 | case longLong = 113 29 | 30 | case unsignedChar = 67 31 | case unsignedInt = 73 32 | case unsignedShort = 83 33 | case unsignedLong = 76 34 | case unsignedLongLong = 81 35 | 36 | case float = 102 37 | case double = 100 38 | 39 | case bool = 66 40 | 41 | case object = 64 42 | case type = 35 43 | case selector = 58 44 | 45 | case undefined = -1 46 | } 47 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/ObjC+Runtime.swift: -------------------------------------------------------------------------------- 1 | /// Search in `class` for any method that matches the supplied selector without 2 | /// propagating to the ancestors. 3 | /// 4 | /// - parameters: 5 | /// - class: The class to search the method in. 6 | /// - selector: The selector of the method. 7 | /// 8 | /// - returns: 9 | /// The matching method, or `nil` if none is found. 10 | internal func class_getImmediateMethod(_ `class`: AnyClass, _ selector: Selector) -> Method? { 11 | if let buffer = class_copyMethodList(`class`, nil) { 12 | defer { free(buffer) } 13 | 14 | var iterator = buffer 15 | while let method = iterator.pointee { 16 | if method_getName(method) == selector { 17 | return method 18 | } 19 | iterator = iterator.advanced(by: 1) 20 | } 21 | } 22 | 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/ObjC+Selector.swift: -------------------------------------------------------------------------------- 1 | extension Selector { 2 | /// `self` as a pointer. It is uniqued across instances, similar to 3 | /// `StaticString`. 4 | internal var utf8Start: UnsafePointer { 5 | return unsafeBitCast(self, to: UnsafePointer.self) 6 | } 7 | 8 | /// An alias of `self`, used in method interception. 9 | internal var alias: Selector { 10 | return prefixing("rac0_") 11 | } 12 | 13 | /// An alias of `self`, used in method interception specifically for 14 | /// preserving (if found) an immediate implementation of `self` in the 15 | /// runtime subclass. 16 | internal var interopAlias: Selector { 17 | return prefixing("rac1_") 18 | } 19 | 20 | internal func prefixing(_ prefix: StaticString) -> Selector { 21 | let length = Int(strlen(utf8Start)) 22 | let prefixedLength = length + prefix.utf8CodeUnitCount 23 | 24 | let asciiPrefix = UnsafeRawPointer(prefix.utf8Start).assumingMemoryBound(to: Int8.self) 25 | 26 | let cString = UnsafeMutablePointer.allocate(capacity: prefixedLength + 1) 27 | defer { 28 | cString.deinitialize() 29 | cString.deallocate(capacity: prefixedLength + 1) 30 | } 31 | 32 | cString.initialize(from: asciiPrefix, count: prefix.utf8CodeUnitCount) 33 | (cString + prefix.utf8CodeUnitCount).initialize(from: utf8Start, count: length) 34 | (cString + prefixedLength).initialize(to: Int8(UInt8(ascii: "\0"))) 35 | 36 | return sel_registerName(cString) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/ObjCRuntimeAliases.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | const IMP _rac_objc_msgForward; 7 | 8 | /// A trampoline of `objc_setAssociatedObject` that is made to circumvent the 9 | /// reference counting calls in the imported version in Swift. 10 | void _rac_objc_setAssociatedObject(const void* object, const void* key, id _Nullable value, objc_AssociationPolicy policy); 11 | 12 | NS_ASSUME_NONNULL_END 13 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/ObjCRuntimeAliases.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | const IMP _rac_objc_msgForward = _objc_msgForward; 5 | 6 | void _rac_objc_setAssociatedObject(const void* object, const void* key, id value, objc_AssociationPolicy policy) { 7 | __unsafe_unretained id obj = (__bridge typeof(obj)) object; 8 | objc_setAssociatedObject(obj, key, value, policy); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/ReactiveCocoa.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for ReactiveCocoa. 4 | FOUNDATION_EXPORT double ReactiveCocoaVersionNumber; 5 | 6 | //! Project version string for ReactiveCocoa. 7 | FOUNDATION_EXPORT const unsigned char ReactiveCocoaVersionString[]; 8 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/Shared/MKMapView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import MapKit 3 | 4 | @available(tvOS 9.2, *) 5 | extension Reactive where Base: MKMapView { 6 | 7 | /// Sets the map type. 8 | public var mapType: BindingTarget { 9 | return makeBindingTarget { $0.mapType = $1 } 10 | } 11 | 12 | /// Sets if zoom is enabled for map. 13 | public var isZoomEnabled: BindingTarget { 14 | return makeBindingTarget { $0.isZoomEnabled = $1 } 15 | } 16 | 17 | /// Sets if scroll is enabled for map. 18 | public var isScrollEnabled: BindingTarget { 19 | return makeBindingTarget { $0.isScrollEnabled = $1 } 20 | } 21 | 22 | #if !os(tvOS) 23 | /// Sets if pitch is enabled for map. 24 | public var isPitchEnabled: BindingTarget { 25 | return makeBindingTarget { $0.isPitchEnabled = $1 } 26 | } 27 | 28 | /// Sets if rotation is enabled for map. 29 | public var isRotateEnabled: BindingTarget { 30 | return makeBindingTarget { $0.isRotateEnabled = $1 } 31 | } 32 | #endif 33 | } 34 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/Shared/NSLayoutConstraint.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | 3 | #if os(macOS) 4 | import AppKit 5 | #else 6 | import UIKit 7 | #endif 8 | 9 | extension Reactive where Base: NSLayoutConstraint { 10 | 11 | /// Sets the constant. 12 | public var constant: BindingTarget { 13 | return makeBindingTarget { $0.constant = $1 } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/ReusableComponents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import ReactiveSwift 3 | import enum Result.NoError 4 | 5 | @objc public protocol Reusable: class { 6 | func prepareForReuse() 7 | } 8 | 9 | extension Reactive where Base: NSObject, Base: Reusable { 10 | public var prepareForReuse: Signal<(), NoError> { 11 | return trigger(for: #selector(base.prepareForReuse)) 12 | } 13 | } 14 | 15 | extension UITableViewCell: Reusable {} 16 | extension UITableViewHeaderFooterView: Reusable {} 17 | extension UICollectionReusableView: Reusable {} 18 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIActivityIndicatorView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIActivityIndicatorView { 5 | /// Sets whether the activity indicator should be animating. 6 | public var isAnimating: BindingTarget { 7 | return makeBindingTarget { $1 ? $0.startAnimating() : $0.stopAnimating() } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIBarButtonItem.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIBarButtonItem { 5 | /// The current associated action of `self`. 6 | private var associatedAction: Atomic<(action: CocoaAction, disposable: Disposable?)?> { 7 | return associatedValue { _ in Atomic(nil) } 8 | } 9 | 10 | /// The action to be triggered when the button is pressed. It also controls 11 | /// the enabled state of the button. 12 | public var pressed: CocoaAction? { 13 | get { 14 | return associatedAction.value?.action 15 | } 16 | 17 | nonmutating set { 18 | base.target = newValue 19 | base.action = newValue.map { _ in CocoaAction.selector } 20 | 21 | associatedAction 22 | .swap(newValue.map { action in 23 | let disposable = isEnabled <~ action.isEnabled 24 | return (action, disposable) 25 | })? 26 | .disposable?.dispose() 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIBarItem.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIBarItem { 5 | /// Sets whether the bar item is enabled. 6 | public var isEnabled: BindingTarget { 7 | return makeBindingTarget { $0.isEnabled = $1 } 8 | } 9 | 10 | /// Sets image of bar item. 11 | public var image: BindingTarget { 12 | return makeBindingTarget { $0.image = $1 } 13 | } 14 | 15 | /// Sets the title of bar item. 16 | public var title: BindingTarget { 17 | return makeBindingTarget { $0.title = $1 } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIButton.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIButton { 5 | /// The action to be triggered when the button is pressed. It also controls 6 | /// the enabled state of the button. 7 | public var pressed: CocoaAction? { 8 | get { 9 | return associatedAction.withValue { info in 10 | return info.flatMap { info in 11 | return info.controlEvents == .touchUpInside ? info.action : nil 12 | } 13 | } 14 | } 15 | 16 | nonmutating set { 17 | setAction(newValue, for: .touchUpInside) 18 | } 19 | } 20 | 21 | /// Sets the title of the button for its normal state. 22 | public var title: BindingTarget { 23 | return makeBindingTarget { $0.setTitle($1, for: .normal) } 24 | } 25 | 26 | /// Sets the title of the button for the specified state. 27 | public func title(for state: UIControlState) -> BindingTarget { 28 | return makeBindingTarget { $0.setTitle($1, for: state) } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UICollectionView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UICollectionView { 5 | public var reloadData: BindingTarget<()> { 6 | return makeBindingTarget { base, _ in base.reloadData() } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIGestureRecognizer.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | import enum Result.NoError 4 | 5 | extension Reactive where Base: UIGestureRecognizer { 6 | /// Create a signal which sends a `next` event for each gesture event 7 | /// 8 | /// - returns: 9 | /// A trigger signal. 10 | public var stateChanged: Signal { 11 | return Signal { observer in 12 | let receiver = CocoaTarget(observer) { gestureRecognizer in 13 | return gestureRecognizer as! Base 14 | } 15 | base.addTarget(receiver, action: #selector(receiver.sendNext)) 16 | 17 | let disposable = lifetime.ended.observeCompleted(observer.sendCompleted) 18 | 19 | return ActionDisposable { [weak base = self.base] in 20 | disposable?.dispose() 21 | base?.removeTarget(receiver, action: #selector(receiver.sendNext)) 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIImageView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIImageView { 5 | /// Sets the image of the image view. 6 | public var image: BindingTarget { 7 | return makeBindingTarget { $0.image = $1 } 8 | } 9 | 10 | /// Sets the image of the image view for its highlighted state. 11 | public var highlightedImage: BindingTarget { 12 | return makeBindingTarget { $0.highlightedImage = $1 } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UILabel.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UILabel { 5 | /// Sets the text of the label. 6 | public var text: BindingTarget { 7 | return makeBindingTarget { $0.text = $1 } 8 | } 9 | 10 | /// Sets the attributed text of the label. 11 | public var attributedText: BindingTarget { 12 | return makeBindingTarget { $0.attributedText = $1 } 13 | } 14 | 15 | /// Sets the color of the text of the label. 16 | public var textColor: BindingTarget { 17 | return makeBindingTarget { $0.textColor = $1 } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIProgressView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIProgressView { 5 | /// Sets the relative progress to be reflected by the progress view. 6 | public var progress: BindingTarget { 7 | return makeBindingTarget { $0.progress = $1 } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIScrollView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIScrollView { 5 | /// Sets the content inset of the scroll view. 6 | public var contentInset: BindingTarget { 7 | return makeBindingTarget { $0.contentInset = $1 } 8 | } 9 | 10 | /// Sets the scroll indicator insets of the scroll view. 11 | public var scrollIndicatorInsets: BindingTarget { 12 | return makeBindingTarget { $0.scrollIndicatorInsets = $1 } 13 | } 14 | 15 | /// Sets whether scrolling the scroll view is enabled. 16 | public var isScrollEnabled: BindingTarget { 17 | return makeBindingTarget { $0.isScrollEnabled = $1 } 18 | } 19 | 20 | /// Sets the zoom scale of the scroll view. 21 | public var zoomScale: BindingTarget { 22 | return makeBindingTarget { $0.zoomScale = $1 } 23 | } 24 | 25 | /// Sets the minimum zoom scale of the scroll view. 26 | public var minimumZoomScale: BindingTarget { 27 | return makeBindingTarget { $0.minimumZoomScale = $1 } 28 | } 29 | 30 | /// Sets the maximum zoom scale of the scroll view. 31 | public var maximumZoomScale: BindingTarget { 32 | return makeBindingTarget { $0.maximumZoomScale = $1 } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UISegmentedControl.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import enum Result.NoError 3 | import UIKit 4 | 5 | extension Reactive where Base: UISegmentedControl { 6 | /// Changes the selected segment of the segmented control. 7 | public var selectedSegmentIndex: BindingTarget { 8 | return makeBindingTarget { $0.selectedSegmentIndex = $1 } 9 | } 10 | 11 | /// A signal of indexes of selections emitted by the segmented control. 12 | public var selectedSegmentIndexes: Signal { 13 | return controlEvents(.valueChanged).map { $0.selectedSegmentIndex } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UITableView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UITableView { 5 | public var reloadData: BindingTarget<()> { 6 | return makeBindingTarget { base, _ in base.reloadData() } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/UIView.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import UIKit 3 | 4 | extension Reactive where Base: UIView { 5 | /// Sets the alpha value of the view. 6 | public var alpha: BindingTarget { 7 | return makeBindingTarget { $0.alpha = $1 } 8 | } 9 | 10 | /// Sets whether the view is hidden. 11 | public var isHidden: BindingTarget { 12 | return makeBindingTarget { $0.isHidden = $1 } 13 | } 14 | 15 | /// Sets whether the view accepts user interactions. 16 | public var isUserInteractionEnabled: BindingTarget { 17 | return makeBindingTarget { $0.isUserInteractionEnabled = $1 } 18 | } 19 | 20 | /// Sets the background color of the view. 21 | public var backgroundColor: BindingTarget { 22 | return makeBindingTarget { $0.backgroundColor = $1 } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/iOS/UIDatePicker.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import enum Result.NoError 3 | import UIKit 4 | 5 | extension Reactive where Base: UIDatePicker { 6 | /// Sets the date of the date picker. 7 | public var date: BindingTarget { 8 | return makeBindingTarget { $0.date = $1 } 9 | } 10 | 11 | /// A signal of dates emitted by the date picker. 12 | public var dates: Signal { 13 | return controlEvents(.valueChanged).map { $0.date } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/iOS/UIRefreshControl.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import enum Result.NoError 3 | import UIKit 4 | 5 | extension Reactive where Base: UIRefreshControl { 6 | /// Sets whether the refresh control should be refreshing. 7 | public var isRefreshing: BindingTarget { 8 | return makeBindingTarget { $1 ? $0.beginRefreshing() : $0.endRefreshing() } 9 | } 10 | 11 | /// Sets the attributed title of the refresh control. 12 | public var attributedTitle: BindingTarget { 13 | return makeBindingTarget { $0.attributedTitle = $1 } 14 | } 15 | 16 | /// The action to be triggered when the refresh control is refreshed. It 17 | /// also controls the enabled and refreshing states of the refresh control. 18 | public var refresh: CocoaAction? { 19 | get { 20 | return associatedAction.withValue { info in 21 | return info.flatMap { info in 22 | return info.controlEvents == .valueChanged ? info.action : nil 23 | } 24 | } 25 | } 26 | 27 | nonmutating set { 28 | let disposable = newValue.flatMap { isRefreshing <~ $0.isExecuting } 29 | setAction(newValue, for: .valueChanged, disposable: disposable) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/iOS/UISlider.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import ReactiveSwift 3 | import enum Result.NoError 4 | 5 | extension Reactive where Base: UISlider { 6 | 7 | /// Sets slider's value. 8 | public var value: BindingTarget { 9 | return makeBindingTarget { $0.value = $1 } 10 | } 11 | 12 | /// Sets slider's minimum value. 13 | public var minimumValue: BindingTarget { 14 | return makeBindingTarget { $0.minimumValue = $1 } 15 | } 16 | 17 | /// Sets slider's maximum value. 18 | public var maximumValue: BindingTarget { 19 | return makeBindingTarget { $0.maximumValue = $1 } 20 | } 21 | 22 | /// A signal of float values emitted by the slider while being dragged by 23 | /// the user. 24 | /// 25 | /// - note: If slider's `isContinuous` property is `false` then values are 26 | /// sent only when user releases the slider. 27 | public var values: Signal { 28 | return controlEvents(.valueChanged).map { $0.value } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/iOS/UIStepper.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import ReactiveSwift 3 | import enum Result.NoError 4 | 5 | extension Reactive where Base: UIStepper { 6 | 7 | /// Sets the stepper's value. 8 | public var value: BindingTarget { 9 | return makeBindingTarget { $0.value = $1 } 10 | } 11 | 12 | /// Sets stepper's minimum value. 13 | public var minimumValue: BindingTarget { 14 | return makeBindingTarget { $0.minimumValue = $1 } 15 | } 16 | 17 | /// Sets stepper's maximum value. 18 | public var maximumValue: BindingTarget { 19 | return makeBindingTarget { $0.maximumValue = $1 } 20 | } 21 | 22 | /// A signal of double values emitted by the stepper upon each user's 23 | /// interaction. 24 | public var values: Signal { 25 | return controlEvents(.valueChanged).map { $0.value } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/UIKit/iOS/UISwitch.swift: -------------------------------------------------------------------------------- 1 | import ReactiveSwift 2 | import enum Result.NoError 3 | import UIKit 4 | 5 | extension Reactive where Base: UISwitch { 6 | /// The action to be triggered when the switch is changed. It also controls 7 | /// the enabled state of the switch 8 | public var toggled: CocoaAction? { 9 | get { 10 | return associatedAction.withValue { info in 11 | return info.flatMap { info in 12 | return info.controlEvents == .valueChanged ? info.action : nil 13 | } 14 | } 15 | } 16 | 17 | nonmutating set { 18 | setAction(newValue, for: .valueChanged) 19 | } 20 | } 21 | /// Sets the on-off state of the switch. 22 | public var isOn: BindingTarget { 23 | return makeBindingTarget { $0.isOn = $1 } 24 | } 25 | 26 | /// A signal of on-off states in `Bool` emitted by the switch. 27 | public var isOnValues: Signal { 28 | return controlEvents(.valueChanged).map { $0.isOn } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveCocoa/ReactiveCocoa/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module ReactiveCocoa { 2 | umbrella header "ReactiveCocoa.h" 3 | private header "ObjCRuntimeAliases.h" 4 | 5 | export * 6 | module * { export * } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveSwift/LICENSE.md: -------------------------------------------------------------------------------- 1 | **Copyright (c) 2012 - 2016, GitHub, Inc.** 2 | **All rights reserved.** 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveSwift/Sources/Optional.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Optional.swift 3 | // ReactiveSwift 4 | // 5 | // Created by Neil Pankey on 6/24/15. 6 | // Copyright (c) 2015 GitHub. All rights reserved. 7 | // 8 | 9 | /// An optional protocol for use in type constraints. 10 | public protocol OptionalProtocol { 11 | /// The type contained in the otpional. 12 | associatedtype Wrapped 13 | 14 | init(reconstructing value: Wrapped?) 15 | 16 | /// Extracts an optional from the receiver. 17 | var optional: Wrapped? { get } 18 | } 19 | 20 | extension Optional: OptionalProtocol { 21 | public var optional: Wrapped? { 22 | return self 23 | } 24 | 25 | public init(reconstructing value: Wrapped?) { 26 | self = value 27 | } 28 | } 29 | 30 | extension SignalProtocol { 31 | /// Turns each value into an Optional. 32 | internal func optionalize() -> Signal { 33 | return map(Optional.init) 34 | } 35 | } 36 | 37 | extension SignalProducerProtocol { 38 | /// Turns each value into an Optional. 39 | internal func optionalize() -> SignalProducer { 40 | return lift { $0.optionalize() } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveSwift/Sources/Reactive.swift: -------------------------------------------------------------------------------- 1 | /// Describes a provider of reactive extensions. 2 | /// 3 | /// - note: `ReactiveExtensionsProvider` does not indicate whether a type is 4 | /// reactive. It is intended for extensions to types that are not owned 5 | /// by the module in order to avoid name collisions and return type 6 | /// ambiguities. 7 | public protocol ReactiveExtensionsProvider: class {} 8 | 9 | extension ReactiveExtensionsProvider { 10 | /// A proxy which hosts reactive extensions for `self`. 11 | public var reactive: Reactive { 12 | return Reactive(self) 13 | } 14 | 15 | /// A proxy which hosts static reactive extensions for the type of `self`. 16 | public static var reactive: Reactive.Type { 17 | return Reactive.self 18 | } 19 | } 20 | 21 | /// A proxy which hosts reactive extensions of `Base`. 22 | public struct Reactive { 23 | /// The `Base` instance the extensions would be invoked with. 24 | public let base: Base 25 | 26 | // Construct a proxy. 27 | // 28 | // - parameters: 29 | // - base: The object to be proxied. 30 | fileprivate init(_ base: Base) { 31 | self.base = base 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/ReactiveSwift/Sources/ResultExtensions.swift: -------------------------------------------------------------------------------- 1 | import Result 2 | 3 | /// Private alias of the free `materialize()` from `Result`. 4 | /// 5 | /// This exists because within a `Signal` or `SignalProducer` operator, 6 | /// `materialize()` refers to the operator with that name. 7 | /// Namespacing as `Result.materialize()` doesn't work either, 8 | /// because it tries to resolve a static member on the _type_ 9 | /// `Result`, rather than the free function in the _module_ 10 | /// of the same name. 11 | internal func materialize(_ f: () throws -> T) -> Result { 12 | return materialize(try f()) 13 | } 14 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Result/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Rob Rix 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. -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Runes/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 thoughtbot, inc. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Alamofire/Alamofire-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double AlamofireVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Alamofire/Alamofire.modulemap: -------------------------------------------------------------------------------- 1 | framework module Alamofire { 2 | umbrella header "Alamofire-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Alamofire/Alamofire.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Alamofire 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Alamofire/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.3.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Argo/Argo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Argo : NSObject 3 | @end 4 | @implementation PodsDummy_Argo 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Argo/Argo-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Argo/Argo-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double ArgoVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char ArgoVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Argo/Argo.modulemap: -------------------------------------------------------------------------------- 1 | framework module Argo { 2 | umbrella header "Argo-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Argo/Argo.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Argo 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Runes" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Argo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.1.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Curry/Curry-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Curry : NSObject 3 | @end 4 | @implementation PodsDummy_Curry 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Curry/Curry-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Curry/Curry-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double CurryVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char CurryVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Curry/Curry.modulemap: -------------------------------------------------------------------------------- 1 | framework module Curry { 2 | umbrella header "Curry-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Curry/Curry.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Curry 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Curry/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Delta/Delta-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Delta : NSObject 3 | @end 4 | @implementation PodsDummy_Delta 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Delta/Delta-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Delta/Delta-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Delta.h" 6 | 7 | FOUNDATION_EXPORT double DeltaVersionNumber; 8 | FOUNDATION_EXPORT const unsigned char DeltaVersionString[]; 9 | 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Delta/Delta.modulemap: -------------------------------------------------------------------------------- 1 | framework module Delta { 2 | umbrella header "Delta-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Delta/Delta.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Delta 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Delta/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoApp/Pods-TodoApp-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_TodoApp : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_TodoApp 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoApp/Pods-TodoApp-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double Pods_TodoAppVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char Pods_TodoAppVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoApp/Pods-TodoApp.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_TodoApp { 2 | umbrella header "Pods-TodoApp-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Pods-TodoAppTests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Pods-TodoAppTests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Pods-TodoAppTests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_TodoAppTests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_TodoAppTests 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Pods-TodoAppTests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double Pods_TodoAppTestsVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char Pods_TodoAppTestsVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Pods-TodoAppTests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | PODS_BUILD_DIR = $BUILD_DIR 5 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT}/Pods 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Pods-TodoAppTests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_TodoAppTests { 2 | umbrella header "Pods-TodoAppTests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Pods-TodoAppTests/Pods-TodoAppTests.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | PODS_BUILD_DIR = $BUILD_DIR 5 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT}/Pods 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveCocoa/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 5.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_ReactiveCocoa : NSObject 3 | @end 4 | @implementation PodsDummy_ReactiveCocoa 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa.modulemap: -------------------------------------------------------------------------------- 1 | framework module ReactiveCocoa { 2 | umbrella header "ReactiveCocoa.h" 3 | private header "ObjCRuntimeAliases.h" 4 | 5 | export * 6 | module * { export * } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveCocoa/ReactiveCocoa.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/ReactiveCocoa 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/ReactiveSwift" "$PODS_CONFIGURATION_BUILD_DIR/Result" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveSwift/ReactiveSwift-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_ReactiveSwift : NSObject 3 | @end 4 | @implementation PodsDummy_ReactiveSwift 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveSwift/ReactiveSwift-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveSwift/ReactiveSwift-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double ReactiveSwiftVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char ReactiveSwiftVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveSwift/ReactiveSwift.modulemap: -------------------------------------------------------------------------------- 1 | framework module ReactiveSwift { 2 | umbrella header "ReactiveSwift-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/ReactiveSwift/ReactiveSwift.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/ReactiveSwift 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Result" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Result/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Result/Result-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Result : NSObject 3 | @end 4 | @implementation PodsDummy_Result 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Result/Result-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Result/Result-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double ResultVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char ResultVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Result/Result.modulemap: -------------------------------------------------------------------------------- 1 | framework module Result { 2 | umbrella header "Result-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Result/Result.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Result 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | SWIFT_VERSION = 3.0 11 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Runes/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Runes/Runes-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Runes : NSObject 3 | @end 4 | @implementation PodsDummy_Runes 5 | @end 6 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Runes/Runes-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Runes/Runes-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double RunesVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char RunesVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Runes/Runes.modulemap: -------------------------------------------------------------------------------- 1 | framework module Runes { 2 | umbrella header "Runes-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/Pods/Target Support Files/Runes/Runes.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Runes 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/ClearCompletedTodosAction.swift: -------------------------------------------------------------------------------- 1 | import Delta 2 | 3 | struct ClearCompletedTodosAction: DynamicActionType { 4 | func call() { 5 | let todos = store.completedTodos.first()?.value ?? [] 6 | 7 | todos.forEach { 8 | todo in 9 | store.dispatch(DeleteTodoAction(todo: todo)) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/CreateTodoAction.swift: -------------------------------------------------------------------------------- 1 | import Delta 2 | 3 | struct CreateTodoAction: ActionType { 4 | let todoId: Int 5 | let name: String 6 | let description: String 7 | let notes: String 8 | 9 | var todo: Todo { 10 | return Todo(todoId: todoId, 11 | name: name, 12 | description: description, 13 | notes: notes, 14 | completed: false, 15 | synced: false, 16 | selected: false) 17 | } 18 | 19 | func reduce(state: State) -> State { 20 | state.todos.value = state.todos.value + [todo] 21 | 22 | return state 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/DeleteTodoAction.swift: -------------------------------------------------------------------------------- 1 | import Delta 2 | 3 | struct DeleteTodoAction: ActionType { 4 | let todo: Todo 5 | 6 | func reduce(state: State) -> State { 7 | state.todos.value = state.todos.value.filter { $0 != self.todo } 8 | 9 | return state 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/DetailsTodoAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailsTodoAction.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-29. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Delta 10 | 11 | struct DetailsTodoAction: ActionType { 12 | let todo: Todo 13 | 14 | func reduce(state: State) -> State { 15 | state.todos.value = state.todos.value.map { todo in 16 | guard todo == self.todo else { 17 | 18 | return Todo(todoId: todo.todoId, 19 | name: todo.name, 20 | description: todo.description, 21 | notes: todo.notes, 22 | completed: todo.completed, 23 | synced: todo.synced, 24 | selected: false) 25 | } 26 | 27 | return Todo(todoId: self.todo.todoId, 28 | name: self.todo.name, 29 | description: self.todo.description, 30 | notes: self.todo.notes, 31 | completed: self.todo.completed, 32 | synced: self.todo.synced, 33 | selected: true) 34 | } 35 | 36 | return state 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/LoadTodosAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // loadTodosAction.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-29. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Delta 10 | 11 | struct LoadTodosAction: ActionType { 12 | let todos: [Todo] 13 | 14 | func reduce(state: State) -> State { 15 | state.todos.value = state.todos.value + todos 16 | return state 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/SetFilterAction.swift: -------------------------------------------------------------------------------- 1 | import Delta 2 | 3 | struct SetFilterAction: ActionType { 4 | let filter: TodoFilter 5 | 6 | func reduce(state: State) -> State { 7 | state.filter.value = filter 8 | return state 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/ToggleCompletedAction.swift: -------------------------------------------------------------------------------- 1 | import Delta 2 | 3 | struct ToggleCompletedAction: ActionType { 4 | let todo: Todo 5 | 6 | func reduce(state: State) -> State { 7 | state.todos.value = state.todos.value.map { 8 | todo in 9 | guard todo == self.todo else { return todo } 10 | 11 | return Todo(todoId: todo.todoId, 12 | name: todo.name, 13 | description: todo.description, 14 | notes: todo.notes, 15 | completed: !todo.completed, 16 | synced: !todo.synced, 17 | selected: todo.selected) 18 | } 19 | 20 | return state 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Actions/UpdateTodoAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpdateTodoAction.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-29. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Delta 10 | 11 | struct UpdateTodoAction: ActionType { 12 | let todo: Todo 13 | 14 | func reduce(state: State) -> State { 15 | state.todos.value = state.todos.value.map { 16 | todo in 17 | guard todo == self.todo else { return todo } 18 | 19 | return Todo(todoId: todo.todoId, 20 | name: self.todo.name, 21 | description: self.todo.description, 22 | notes: self.todo.notes, 23 | completed: self.todo.completed, 24 | synced: !todo.synced, 25 | selected: todo.selected) 26 | } 27 | 28 | return state 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Communication/Urls.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Urls.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-25. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum Urls { 12 | case postTodo 13 | case getTodos 14 | case getTodo 15 | case deleteTodo 16 | case deleteAll 17 | case update 18 | } 19 | 20 | extension Urls { 21 | func httpMethodUrl() -> (String, String) { 22 | let baseUrl = "http://localhost:8080/" 23 | switch self { 24 | case .postTodo: 25 | return ("POST", "\(baseUrl)postTodo") 26 | case .getTodos: 27 | return ("GET", "\(baseUrl)todos") 28 | case .getTodo: 29 | return ("GET", "\(baseUrl)todo") 30 | case .deleteTodo: 31 | return ("DELETE", "\(baseUrl)deleteTodo") 32 | case .deleteAll: 33 | return ("DELETE", "\(baseUrl)deleteAll") 34 | case .update: 35 | return ("POST", "\(baseUrl)updateTodo") 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Extensions/ReactiveCocoa.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReactiveCocoa.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-25. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import ReactiveCocoa 10 | import ReactiveSwift 11 | import Delta 12 | 13 | extension MutableProperty: Delta.ObservablePropertyType { 14 | public typealias ValueType = Value 15 | } 16 | 17 | struct RAC { 18 | var target : NSObject! 19 | var keyPath : String! 20 | var nilValue : AnyObject! 21 | 22 | init(_ target: NSObject!, _ keyPath: String, nilValue: AnyObject? = nil) { 23 | self.target = target 24 | self.keyPath = keyPath 25 | self.nilValue = nilValue 26 | } 27 | } 28 | 29 | //infix operator ~> 30 | //func ~> (signal: RACSignal, rac: RAC) { 31 | // rac.assignSignal(signal) 32 | //} 33 | // 34 | //func RACObserve(_ target: NSObject!, keyPath: String) -> RACSignal { 35 | // return target.rac_valuesForKeyPath(keyPath, observer: target) 36 | //} 37 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Models/RequestProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RequestProtocol.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-24. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol RequestProtocol { 12 | subscript(key: String) -> (String?, String?) { get } 13 | } 14 | 15 | extension RequestProtocol { 16 | func getPropertyNames()-> [String] { 17 | return Mirror(reflecting: self).children.filter { $0.label != nil }.map { $0.label! } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Models/Todo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Todo.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-24. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Argo 10 | import Curry 11 | import Runes 12 | 13 | enum TodoFilter: Int { 14 | case all 15 | case active 16 | case completed 17 | case notSyncedWithBackend 18 | case selected 19 | } 20 | 21 | struct Todo { 22 | let todoId: Int 23 | let name: String 24 | let description: String 25 | let notes: String? 26 | let completed: Bool 27 | let synced: Bool 28 | let selected: Bool? 29 | } 30 | 31 | extension Todo: Decodable { 32 | static func decode(_ json: JSON) -> Decoded { 33 | return curry(Todo.init) 34 | <^> json <| "todoId" 35 | <*> json <| "name" 36 | <*> json <| "description" 37 | <*> json <|? "notes" 38 | <*> json <| "completed" 39 | <*> json <| "synced" 40 | <*> json <|? "selected" 41 | } 42 | } 43 | 44 | extension Todo: Equatable {} 45 | 46 | func == (lhs: Todo, rhs: Todo) -> Bool { 47 | return lhs.todoId == rhs.todoId 48 | } 49 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Models/TodoRequest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodoRequest.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-24. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct TodoRequest: RequestProtocol { 12 | 13 | let todoId: Int 14 | let name: String 15 | let description: String 16 | let notes: String 17 | let completed: Bool 18 | let synced: Bool 19 | 20 | subscript(key: String) -> (String?, String?) { 21 | get { 22 | switch key { 23 | case "todoId": return (String(todoId), "todoId") 24 | case "name": return (name, "name") 25 | case "description": return (description, "description") 26 | case "notes": return (notes, "notes") 27 | case "completed": return (String(completed), "completed") 28 | case "synced": return (String(synced), "synced") 29 | default: return ("Cookie","test=123") 30 | } 31 | } 32 | } 33 | } 34 | 35 | struct RequestModel: RequestProtocol { 36 | subscript(key: String) -> (String?, String?) { 37 | get { 38 | switch key { 39 | default: return ("Cookie","test=123") 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Models/TodoViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodoViewModel.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-29. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct TodoViewModel { 12 | let todo: Todo? 13 | } 14 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Models/TodosViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Todos.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-24. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import ReactiveCocoa 10 | 11 | struct TodosViewModel { 12 | let todos: [Todo] 13 | 14 | func todoForIndexPath(_ indexPath: IndexPath) -> Todo { 15 | return todos[indexPath.row] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/State/State.swift: -------------------------------------------------------------------------------- 1 | // 2 | // State.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-25. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import ReactiveSwift 10 | 11 | private let initialTodos: [Todo] = [] 12 | 13 | struct State { 14 | let todos = MutableProperty(initialTodos) 15 | let filter = MutableProperty(TodoFilter.all) 16 | let notSynced = MutableProperty(TodoFilter.notSyncedWithBackend) 17 | let selectedTodoItem = MutableProperty(TodoFilter.selected) 18 | } 19 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Stores/Store.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Store.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-25. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import ReactiveSwift 10 | import ReactiveCocoa 11 | import Delta 12 | 13 | struct Store: StoreType { 14 | var state: ObservableProperty 15 | 16 | init(state: State) { 17 | self.state = ObservableProperty(state) 18 | } 19 | } 20 | 21 | var store = Store(state: State()) 22 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoApp/Views/FooterView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FooterView.swift 3 | // TodoApp 4 | // 5 | // Created by Fatih Nayebi on 2016-04-29. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | 10 | import UIKit 11 | 12 | class FooterView: UIView { 13 | var stackView: UIStackView? { 14 | return self.subviews.first as? UIStackView 15 | } 16 | 17 | var itemsLeftLabel: UILabel? { 18 | return stackView?.subviews.first as? UILabel 19 | } 20 | 21 | var clearCompletedButton: UIButton? { 22 | return stackView?.subviews.last as? UIButton 23 | } 24 | 25 | override func awakeFromNib() { 26 | self.clearCompletedButton?.addTarget(self, action: #selector(FooterView.clearCompletedTapped), for: .touchUpInside) 27 | self.subscribeToStoreChanges() 28 | } 29 | 30 | func subscribeToStoreChanges() { 31 | store.todoStats.startWithValues { 32 | todosCount, incompleteCount in 33 | self.clearCompletedButton?.isHidden = todosCount == incompleteCount 34 | 35 | if incompleteCount == 1 { 36 | self.itemsLeftLabel?.text = "1 todo left" 37 | } else { 38 | self.itemsLeftLabel?.text = "\(incompleteCount) todos left" 39 | } 40 | } 41 | } 42 | 43 | func clearCompletedTapped() { 44 | store.dispatch(ClearCompletedTodosAction()) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Chapter11/Ch11-Frontend/TodoApp/TodoAppTests/TodoAppTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodoAppTests.swift 3 | // TodoAppTests 4 | // 5 | // Created by Fatih Nayebi on 2016-04-24. 6 | // Copyright © 2016 Fatih Nayebi. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TodoApp 11 | 12 | class TodoAppTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/._.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X  2Fx ATTRxx -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/Ch11-Backend/._.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X  2Fx ATTRxx -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/Ch11-Backend/vapor-example/._.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X  2Fx ATTRxx -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/Ch11-Frontend/._.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X  2Fx ATTRxx -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/Ch11-Frontend/TodoApp/._.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X  2Fx ATTRxx -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/Playgrounds/._.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X  2Fx ATTRxx -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/Playgrounds/Ch05-Generics.playground/Pages/._AssociatedTypeProtocols.xcplaygroundpage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/__MACOSX/SwiftFP/Playgrounds/Ch05-Generics.playground/Pages/._AssociatedTypeProtocols.xcplaygroundpage -------------------------------------------------------------------------------- /__MACOSX/SwiftFP/Playgrounds/Ch05-Generics.playground/Pages/._ExtendingGenericTypes.xcplaygroundpage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Swift-Functional-Programming/6b5ac02d385bed117b7fbf33ecd06c3461a4e7a5/__MACOSX/SwiftFP/Playgrounds/Ch05-Generics.playground/Pages/._ExtendingGenericTypes.xcplaygroundpage --------------------------------------------------------------------------------