├── CODEOWNERS ├── software-design-principles ├── dry-principle │ ├── starter │ │ └── DRY │ │ │ ├── DRY │ │ │ ├── Assets.xcassets │ │ │ │ ├── Contents.json │ │ │ │ ├── profile_photo.imageset │ │ │ │ │ ├── profile_photo.png │ │ │ │ │ └── Contents.json │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ ├── User.swift │ │ │ ├── ProfileViewController.swift │ │ │ ├── WelcomeViewController.swift │ │ │ ├── Info.plist │ │ │ ├── Base.lproj │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ └── AppDelegate.swift │ │ │ └── DRY.xcodeproj │ │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── solution │ │ └── DRY │ │ ├── DRY │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ ├── profile_photo.imageset │ │ │ │ ├── profile_photo.png │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── User.swift │ │ ├── ProfileViewController.swift │ │ ├── WelcomeViewController.swift │ │ ├── Info.plist │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ └── AppDelegate.swift │ │ └── DRY.xcodeproj │ │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── dependency-inversion-principle │ ├── solution │ │ └── ImageCache.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── ImageCache.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── liskov-substitution-principle │ ├── starter │ │ └── RectangleArea.playground │ │ │ ├── contents.xcplayground │ │ │ └── Contents.swift │ └── solution │ │ └── RectangleArea.playground │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── Contents.swift ├── interface-segregation-principle │ ├── solution │ │ └── InterfaceSegregationPlayground.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── InterfaceSegregationPlayground.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── open-closed-principle │ ├── starter │ │ └── AreaCalculator │ │ │ ├── AreaCalculator.xcodeproj │ │ │ └── project.xcworkspace │ │ │ │ └── contents.xcworkspacedata │ │ │ └── AreaCalculator │ │ │ ├── AreaCalculator.swift │ │ │ ├── ViewController.swift │ │ │ ├── Info.plist │ │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── AppDelegate.swift │ └── solution │ │ └── AreaCalculator │ │ ├── AreaCalculator.xcodeproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── AreaCalculator │ │ ├── ViewController.swift │ │ ├── AreaCalculator.swift │ │ ├── Info.plist │ │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── AppDelegate.swift └── single-responsibility-principle │ ├── starter │ └── SingleResponsibilityPrinciple │ │ ├── SingleResponsibilityPrinciple.xcodeproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── SingleResponsibilityPrinciple │ │ ├── ViewController.swift │ │ ├── Game.swift │ │ ├── Info.plist │ │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── AppDelegate.swift │ └── solution │ └── SingleResponsibilityPrinciple │ ├── SingleResponsibilityPrinciple.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── SingleResponsibilityPrinciple │ ├── ViewController.swift │ ├── Game.swift │ ├── Info.plist │ ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ └── AppDelegate.swift ├── creational-design-patterns ├── object-pool │ ├── solution │ │ └── ObjectPool │ │ │ ├── ObjectPool │ │ │ ├── Assets.xcassets │ │ │ │ ├── Contents.json │ │ │ │ ├── snowflake.imageset │ │ │ │ │ ├── snowflake.png │ │ │ │ │ └── Contents.json │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── Base.lproj │ │ │ │ ├── Main.storyboard │ │ │ │ └── LaunchScreen.storyboard │ │ │ ├── AppDelegate.swift │ │ │ └── ViewController.swift │ │ │ └── ObjectPool.xcodeproj │ │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── project.pbxproj │ └── starter │ │ └── ObjectPool │ │ ├── ObjectPool │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ ├── snowflake.imageset │ │ │ │ ├── snowflake.png │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ ├── AppDelegate.swift │ │ └── ViewController.swift │ │ └── ObjectPool.xcodeproj │ │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── project.pbxproj ├── builder │ ├── solution │ │ └── FormSubmission.playground │ │ │ ├── contents.xcplayground │ │ │ └── Contents.swift │ └── starter │ │ └── FormSubmission.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── factory-methods │ ├── solution │ │ └── Music.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── Music.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── singleton │ ├── solution │ │ └── Singleton.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── Singleton.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── dependency-injection │ ├── solution │ │ └── ImageCache.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── ImageCache.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift └── builder-exercise │ └── SignUpApp │ ├── SignUpApp.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── SignUpApp │ ├── SignUpForm.swift │ ├── EmailVIewController.swift │ ├── PasswordViewController.swift │ ├── UsernameViewController.swift │ ├── Info.plist │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ └── AppDelegate.swift ├── anti-patterns ├── god-object-exercise │ └── GodObjectExercise.playground │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── Contents.swift └── deep-inheritance-exercise │ └── DeepInheritanceExercise.playground │ ├── contents.xcplayground │ └── Contents.swift ├── structural-design-patterns ├── adapter │ ├── solution │ │ └── Adapter.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── Adapter.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── facade │ ├── starter │ │ └── OrderFacade.playground │ │ │ ├── contents.xcplayground │ │ │ └── Contents.swift │ └── solution │ │ └── OrderFacade.playground │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── Contents.swift └── decorator │ ├── solution │ └── Decorators.playground │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── Contents.swift │ └── starter │ └── Decorators.playground │ ├── contents.xcplayground │ └── Contents.swift ├── behavioral-design-patterns ├── command │ ├── solution │ │ └── MusicPlayer.playground │ │ │ ├── contents.xcplayground │ │ │ └── Contents.swift │ └── starter │ │ └── MusicPlayer.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── mediator │ ├── solution │ │ └── EmailSender.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── EmailSender.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift ├── observer │ ├── solution │ │ └── LocationPlayground.playground │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ │ └── Contents.swift │ └── starter │ │ └── LocationPlayground.playground │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── Contents.swift └── chain-of-responsibility │ ├── solution │ └── ImageProcessing.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift │ └── starter │ └── ImageProcessing.playground │ ├── contents.xcplayground │ └── Contents.swift ├── .gitignore ├── .github └── workflows │ └── manual.yml └── README.md /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @udacity/active-public-content -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /anti-patterns/god-object-exercise/GodObjectExercise.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /structural-design-patterns/adapter/solution/Adapter.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /structural-design-patterns/adapter/starter/Adapter.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /structural-design-patterns/facade/starter/OrderFacade.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /behavioral-design-patterns/command/solution/MusicPlayer.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /behavioral-design-patterns/command/starter/MusicPlayer.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /behavioral-design-patterns/mediator/solution/EmailSender.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /behavioral-design-patterns/mediator/starter/EmailSender.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/builder/solution/FormSubmission.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/builder/starter/FormSubmission.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/factory-methods/solution/Music.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/factory-methods/starter/Music.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/singleton/solution/Singleton.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/singleton/starter/Singleton.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /structural-design-patterns/decorator/solution/Decorators.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /structural-design-patterns/decorator/starter/Decorators.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /structural-design-patterns/facade/solution/OrderFacade.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /anti-patterns/deep-inheritance-exercise/DeepInheritanceExercise.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /anti-patterns/god-object-exercise/GodObjectExercise.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /behavioral-design-patterns/observer/solution/LocationPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /behavioral-design-patterns/observer/starter/LocationPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /structural-design-patterns/adapter/solution/Adapter.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /behavioral-design-patterns/mediator/solution/EmailSender.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /creational-design-patterns/dependency-injection/solution/ImageCache.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/dependency-injection/starter/ImageCache.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/singleton/solution/Singleton.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /structural-design-patterns/decorator/solution/Decorators.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /structural-design-patterns/facade/solution/OrderFacade.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /creational-design-patterns/factory-methods/solution/Music.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /behavioral-design-patterns/chain-of-responsibility/solution/ImageProcessing.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /behavioral-design-patterns/chain-of-responsibility/starter/ImageProcessing.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /behavioral-design-patterns/observer/solution/LocationPlayground.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /behavioral-design-patterns/observer/starter/LocationPlayground.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/dependency-inversion-principle/solution/ImageCache.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /software-design-principles/dependency-inversion-principle/starter/ImageCache.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/liskov-substitution-principle/starter/RectangleArea.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/dependency-injection/solution/ImageCache.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/Assets.xcassets/profile_photo.imageset/profile_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/iosnd-design-patterns/HEAD/software-design-principles/dry-principle/solution/DRY/DRY/Assets.xcassets/profile_photo.imageset/profile_photo.png -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/Assets.xcassets/profile_photo.imageset/profile_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/iosnd-design-patterns/HEAD/software-design-principles/dry-principle/starter/DRY/DRY/Assets.xcassets/profile_photo.imageset/profile_photo.png -------------------------------------------------------------------------------- /software-design-principles/liskov-substitution-principle/solution/RectangleArea.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /creational-design-patterns/builder/starter/FormSubmission.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | struct SignUpSubmission { 6 | let username: String 7 | let email: String 8 | let phoneNumber: String 9 | } 10 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Assets.xcassets/snowflake.imageset/snowflake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/iosnd-design-patterns/HEAD/creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Assets.xcassets/snowflake.imageset/snowflake.png -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Assets.xcassets/snowflake.imageset/snowflake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/iosnd-design-patterns/HEAD/creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Assets.xcassets/snowflake.imageset/snowflake.png -------------------------------------------------------------------------------- /software-design-principles/dependency-inversion-principle/solution/ImageCache.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/liskov-substitution-principle/solution/RectangleArea.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/interface-segregation-principle/solution/InterfaceSegregationPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /software-design-principles/interface-segregation-principle/starter/InterfaceSegregationPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /software-design-principles/interface-segregation-principle/solution/InterfaceSegregationPlayground.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct User { 12 | let id: Int 13 | let firstName: String 14 | let lastName: String 15 | } 16 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /creational-design-patterns/singleton/starter/Singleton.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | class NetworkClient { 6 | func fetchUsers() { 7 | // Performs network call and fetches users 8 | } 9 | 10 | func fetchMessages() { 11 | // Performs network call and fetches messages 12 | } 13 | 14 | // ...more methods here 15 | } 16 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/SignUpForm.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SignUpForm.swift 3 | // SignUpApp 4 | // 5 | // Created by Christopher Arriola on 2/23/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct SignUpForm { 12 | let email: String 13 | let password: String 14 | let username: String 15 | 16 | // TODO: Create builder class 17 | } 18 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct User { 12 | let id: Int 13 | let firstName: String 14 | let lastName: String 15 | 16 | var displayName: String { 17 | return "\(self.firstName) \(Array(self.lastName)[0])" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/Assets.xcassets/profile_photo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "profile_photo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/Assets.xcassets/profile_photo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "profile_photo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Assets.xcassets/snowflake.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "snowflake.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Assets.xcassets/snowflake.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "snowflake.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /anti-patterns/deep-inheritance-exercise/DeepInheritanceExercise.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | class Person { 6 | var name: String? 7 | } 8 | 9 | class Musician: Person { 10 | var yearsTrained: Int? 11 | } 12 | 13 | class Guitarist: Musician { 14 | enum GuitarType { 15 | case acoustic, electric 16 | } 17 | 18 | var preferredGuitarType: GuitarType? 19 | } 20 | 21 | class LeadGuitarist: Guitarist { 22 | } 23 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/EmailVIewController.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // EmailVIewController.swift 4 | // SignUpApp 5 | // 6 | // Created by Christopher Arriola on 2/22/18. 7 | // Copyright © 2018 Udacity. All rights reserved. 8 | // 9 | 10 | import UIKit 11 | 12 | class EmailViewController: UIViewController { 13 | @IBOutlet weak var textFieldEmail: UITextField! 14 | 15 | @IBAction func onSubmitTapped(_ sender: Any) { 16 | // TODO Build form object here 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /creational-design-patterns/dependency-injection/starter/ImageCache.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | protocol Cache { 6 | func cache(object: NSObject) 7 | } 8 | 9 | class InMemoryCache: Cache { 10 | func cache(object: NSObject) { 11 | // Cache object in-memory 12 | } 13 | } 14 | 15 | class ImageCache { 16 | let objectCache: Cache 17 | 18 | init() { 19 | objectCache = InMemoryCache() 20 | } 21 | } 22 | 23 | let imageCache = ImageCache() 24 | 25 | -------------------------------------------------------------------------------- /structural-design-patterns/adapter/starter/Adapter.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | class MessageSender { 6 | func send(message: Message) { 7 | for recipient in message.recipients { 8 | // Send message to recipient 9 | } 10 | } 11 | } 12 | 13 | struct Message { 14 | let id: String 15 | let text: String 16 | let recipients: [String] 17 | } 18 | 19 | struct LegacyMessage { 20 | let id: String 21 | let text: String 22 | let recipient: String 23 | } 24 | -------------------------------------------------------------------------------- /creational-design-patterns/singleton/solution/Singleton.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | class NetworkClient { 6 | static let shared = NetworkClient() 7 | 8 | private init() { 9 | } 10 | 11 | func fetchUsers() { 12 | // Performs network call and fetches users 13 | } 14 | 15 | func fetchMessages() { 16 | // Performs network call and fetches messages 17 | } 18 | 19 | // ...more methods here 20 | } 21 | 22 | NetworkClient.shared.fetchMessages() 23 | -------------------------------------------------------------------------------- /structural-design-patterns/decorator/starter/Decorators.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | enum Instrument { 4 | case guitar 5 | case drums 6 | case bass 7 | // ... 8 | } 9 | 10 | protocol Musician { 11 | var instrument: Instrument { get } 12 | func play() 13 | } 14 | 15 | extension Musician { 16 | func play() { 17 | print("plays the \(instrument)") 18 | } 19 | } 20 | 21 | class Guitarist: Musician { 22 | var instrument: Instrument { return .guitar } 23 | } 24 | 25 | class Drummer: Musician { 26 | var instrument: Instrument { return .drums } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /creational-design-patterns/dependency-injection/solution/ImageCache.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | protocol Cache { 6 | func cache(object: NSObject) 7 | } 8 | 9 | class InMemoryCache: Cache { 10 | func cache(object: NSObject) { 11 | // Cache object in-memory 12 | } 13 | } 14 | 15 | class DiskCache: Cache { 16 | func cache(object: NSObject) { 17 | // cache object to disk 18 | } 19 | } 20 | 21 | class ImageCache { 22 | let objectCache: Cache 23 | 24 | init(objectCache: Cache) { 25 | self.objectCache = objectCache 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | Icon 6 | ._* 7 | .Spotlight-V100 8 | .Trashes 9 | 10 | # Xcode 11 | build/ 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata 21 | *.xcuserdatad 22 | *.xccheckout 23 | *.moved-aside 24 | DerivedData 25 | *.xcuserstate 26 | *.DS_Store 27 | xcshareddata 28 | 29 | # Project 30 | *.xcworkspace 31 | !default.xcworkspace 32 | xcuserdatad/ 33 | 34 | # Carthage 35 | Carthage/Build 36 | Carthage/Checkouts 37 | 38 | # Cocoapods 39 | Pods/ 40 | 41 | # secret 42 | pancit-firebase-key.json 43 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/ProfileViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileViewController.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class ProfileViewController: UIViewController { 13 | @IBOutlet weak var label: UILabel! 14 | 15 | var user: User! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | label.text = user.displayName 20 | } 21 | 22 | @IBAction func onBackPressed(_ sender: Any) { 23 | dismiss(animated: true) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator/AreaCalculator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AreaCalculator.swift 3 | // AreaCalculator 4 | // 5 | // Created by Christopher Arriola on 1/24/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol Shape { 12 | } 13 | 14 | struct Rectangle: Shape { 15 | let width: Int 16 | let height: Int 17 | } 18 | 19 | class AreaCalculator { 20 | func computeArea(shape: Shape) -> Double { 21 | if let rectangle = shape as? Rectangle { 22 | return Double(rectangle.width * rectangle.height) 23 | } 24 | return 0 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/ProfileViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileViewController.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class ProfileViewController: UIViewController { 13 | @IBOutlet weak var label: UILabel! 14 | 15 | var user: User! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | label.text = "\(user.firstName) \(Array(user.lastName)[0])" 20 | } 21 | 22 | @IBAction func onBackPressed(_ sender: Any) { 23 | dismiss(animated: true) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // AreaCalculator 4 | // 5 | // Created by Christopher Arriola on 1/24/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // AreaCalculator 4 | // 5 | // Created by Christopher Arriola on 1/24/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/PasswordViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasswordViewController.swift 3 | // SignUpApp 4 | // 5 | // Created by Christopher Arriola on 2/22/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PasswordViewController: UIViewController { 12 | @IBOutlet weak var textFieldPassword: UITextField! 13 | 14 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 15 | if segue.identifier == "goToEmailViewSegue" { 16 | let emailViewController = segue.destination as! EmailViewController 17 | // TODO Pass builder object to emailViewController 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /structural-design-patterns/facade/starter/OrderFacade.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | // An order for a ticket to a concert 6 | struct Order { 7 | let userId: String 8 | let payment: PaymentInformation 9 | let concert: Concert 10 | } 11 | 12 | // A user's payment information 13 | struct PaymentInformation { 14 | let creditCardNumber: String 15 | // ...other fields 16 | } 17 | 18 | // A concert 19 | struct Concert { 20 | let id: String 21 | // ...other fields 22 | } 23 | 24 | // A class for interacting with different concerts 25 | class ConcertManager { 26 | } 27 | 28 | // A class for processing payments 29 | class PaymentProcessor { 30 | } 31 | 32 | -------------------------------------------------------------------------------- /software-design-principles/dependency-inversion-principle/starter/ImageCache.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import Foundation 4 | 5 | class Message { 6 | let id: String 7 | let text: String 8 | 9 | init(id: String, text: String) { 10 | self.id = id 11 | self.text = text 12 | } 13 | } 14 | 15 | class MessageCacher { 16 | let cache: InMemoryCache 17 | 18 | init(cache: InMemoryCache) { 19 | self.cache = cache 20 | } 21 | 22 | func store(message: Message) { 23 | cache.cache(object: message) 24 | } 25 | } 26 | 27 | class InMemoryCache { 28 | func cache(object: AnyObject) { 29 | // caches object 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/UsernameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SignUpApp 4 | // 5 | // Created by Christopher Arriola on 2/9/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class UsernameViewController: UIViewController { 12 | 13 | @IBOutlet weak var textFieldUsername: UITextField! 14 | 15 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 16 | if segue.identifier == "goToPasswordViewSegue" { 17 | let passwordViewController = segue.destination as! PasswordViewController 18 | // TODO Create builder object and pass it to passwordViewController 19 | } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /creational-design-patterns/builder/solution/FormSubmission.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | struct SignUpSubmission { 6 | let username: String 7 | let email: String 8 | let phoneNumber: String 9 | // ... 10 | 11 | class Builder { 12 | var username: String? 13 | var email: String? 14 | var phoneNumber: String? 15 | 16 | func build() -> SignUpSubmission? { 17 | guard let username = username, let email = email, let phoneNumber = phoneNumber else { 18 | return nil 19 | } 20 | return SignUpSubmission(username: username, email: email, phoneNumber: phoneNumber) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SingleResponsibilityPrinciple 4 | // 5 | // Created by Christopher Arriola on 1/22/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SingleResponsibilityPrinciple 4 | // 5 | // Created by Christopher Arriola on 1/22/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /software-design-principles/dependency-inversion-principle/solution/ImageCache.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import Foundation 4 | 5 | class Message { 6 | let id: String 7 | let text: String 8 | 9 | init(id: String, text: String) { 10 | self.id = id 11 | self.text = text 12 | } 13 | } 14 | 15 | protocol ObjectCache { 16 | func cache(object: AnyObject) 17 | } 18 | 19 | class MessageCacher { 20 | let cache: ObjectCache 21 | 22 | init(cache: ObjectCache) { 23 | self.cache = cache 24 | } 25 | 26 | func store(message: Message) { 27 | cache.cache(object: message) 28 | } 29 | } 30 | 31 | class InMemoryCache: ObjectCache { 32 | func cache(object: AnyObject) { 33 | // caches object 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator/AreaCalculator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AreaCalculator.swift 3 | // AreaCalculator 4 | // 5 | // Created by Christopher Arriola on 1/24/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol Shape { 12 | var area: Double { get } 13 | } 14 | 15 | struct Circle: Shape { 16 | let radius: Int 17 | 18 | var area: Double { 19 | return Double(radius * radius) * Double.pi 20 | } 21 | } 22 | 23 | struct Rectangle: Shape { 24 | let width: Int 25 | let height: Int 26 | 27 | var area: Double { 28 | return Double(width * height) 29 | } 30 | } 31 | 32 | class AreaCalculator { 33 | func computeArea(shape: Shape) -> Double { 34 | return shape.area 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /anti-patterns/god-object-exercise/GodObjectExercise.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | class AppSettings { 6 | 7 | private let defaults = UserDefaults.standard 8 | 9 | var userId: String { 10 | return defaults.string(forKey: "user_id") ?? "" 11 | } 12 | 13 | // MARK: User preferences 14 | 15 | var userPreference1: Bool { 16 | return defaults.bool(forKey: "user_preference_1") 17 | } 18 | 19 | var userPreference2: Bool { 20 | return defaults.bool(forKey: "user_preference_2") 21 | } 22 | 23 | // MARK: Onboarding 24 | 25 | var hasSeenFeature1: Bool { 26 | return defaults.bool(forKey: "has_seen_feature_1") 27 | } 28 | 29 | var hasSeenFeature2: Bool { 30 | return defaults.bool(forKey: "has_seen_feature_2") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/WelcomeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WelcomeViewController.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class WelcomeViewController: UIViewController { 13 | @IBOutlet weak var label: UILabel! 14 | 15 | private var user: User! 16 | 17 | override func viewDidLoad() { 18 | user = User(id: 1, firstName: "Steve", lastName: "Jobs") 19 | label.text = user.displayName 20 | } 21 | 22 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 23 | if segue.identifier == "showProfileSegue" { 24 | let profileViewController = segue.destination as! ProfileViewController 25 | profileViewController.user = user 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/WelcomeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WelcomeViewController.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class WelcomeViewController: UIViewController { 13 | @IBOutlet weak var label: UILabel! 14 | 15 | private var user: User! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | user = User(id: 1, firstName: "Steve", lastName: "Jobs") 20 | label.text = "\(user.firstName) \(Array(user.lastName)[0])" 21 | } 22 | 23 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 24 | if segue.identifier == "showProfileSegue" { 25 | let profileViewController = segue.destination as! ProfileViewController 26 | profileViewController.user = user 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /software-design-principles/interface-segregation-principle/starter/InterfaceSegregationPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | /** 6 | * Protocol for a Game. 7 | */ 8 | protocol Game { 9 | func start() 10 | func pause() 11 | func stop() 12 | func save() 13 | func restore() 14 | func setDifficulty(to difficulty: Int) 15 | } 16 | 17 | class RPGGame: Game { 18 | // All methods used! 19 | func start() { } 20 | func pause() { } 21 | func stop() { } 22 | func save() { } 23 | func restore() { } 24 | func setDifficulty(to difficulty: Int) { } 25 | } 26 | 27 | class TapBasedGame: Game { 28 | // Only these methods are used 29 | func start() { } 30 | func pause() { } 31 | func stop() { } 32 | 33 | // These methods not used 34 | func save() { } 35 | func restore() { } 36 | func setDifficulty(to difficulty: Int) { } 37 | } 38 | -------------------------------------------------------------------------------- /software-design-principles/liskov-substitution-principle/solution/RectangleArea.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | import Foundation 5 | 6 | protocol Shape { 7 | var area: Int { get } 8 | } 9 | 10 | class Rectangle: Shape { 11 | var width: Int 12 | var height: Int 13 | 14 | var area: Int { 15 | return width * height 16 | } 17 | 18 | init(width: Int, height: Int) { 19 | self.width = width 20 | self.height = height 21 | } 22 | } 23 | 24 | class Square: Shape { 25 | var side: Int 26 | 27 | var area: Int { 28 | return side * side 29 | } 30 | 31 | init(side: Int) { 32 | self.side = side 33 | } 34 | } 35 | 36 | 37 | func printArea(shape: Shape) { 38 | print(shape.area) 39 | } 40 | 41 | let rectangle = Rectangle(width: 3, height: 4) 42 | printArea(shape: rectangle) 43 | 44 | let square = Square(side: 3) 45 | printArea(shape: square) 46 | -------------------------------------------------------------------------------- /software-design-principles/interface-segregation-principle/solution/InterfaceSegregationPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | /** 6 | * A game that can be saved. 7 | */ 8 | protocol Saveable { 9 | func save() 10 | func restore() 11 | } 12 | 13 | /** 14 | * A game with which the difficulty can be adjusted 15 | */ 16 | protocol VariablyDifficultGame { 17 | func setDifficulty(to difficulty: Int) 18 | } 19 | 20 | /** 21 | * Protocol for a Game. 22 | */ 23 | protocol Game { 24 | func start() 25 | func pause() 26 | func stop() 27 | } 28 | 29 | class RPGGame: Game, Saveable, VariablyDifficultGame { 30 | // All methods used! 31 | func start() { } 32 | func pause() { } 33 | func stop() { } 34 | 35 | func save() { } 36 | func restore() { } 37 | 38 | func setDifficulty(to difficulty: Int) { } 39 | } 40 | 41 | class TapBasedGame: Game { 42 | // Only these methods are used 43 | func start() { } 44 | func pause() { } 45 | func stop() { } 46 | } 47 | -------------------------------------------------------------------------------- /structural-design-patterns/adapter/solution/Adapter.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | class MessageSender { 6 | func send(message: Message) { 7 | for recipient in message.recipients { 8 | // Send message to recipient 9 | } 10 | } 11 | } 12 | 13 | struct Message { 14 | let id: String 15 | let text: String 16 | let recipients: [String] 17 | } 18 | 19 | struct LegacyMessage { 20 | let id: String 21 | let text: String 22 | let recipient: String 23 | } 24 | 25 | struct LegacyMessageAdapter { 26 | let legacyMessage: LegacyMessage 27 | 28 | var message: Message { 29 | return Message(id: legacyMessage.id, text: legacyMessage.text, recipients: [legacyMessage.recipient]) 30 | } 31 | } 32 | 33 | // Usage 34 | let messageSender = MessageSender() 35 | let legacyMessage = LegacyMessage(id: "abc", text: "hello", recipient: "john") 36 | let legacyMessageAdapter = LegacyMessageAdapter(legacyMessage: legacyMessage) 37 | messageSender.send(message: legacyMessageAdapter.message) 38 | 39 | -------------------------------------------------------------------------------- /structural-design-patterns/facade/solution/OrderFacade.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | // An order for a ticket to a concert 6 | struct Order { 7 | let userId: String 8 | let payment: PaymentInformation 9 | let concert: Concert 10 | } 11 | 12 | // A user's payment information 13 | struct PaymentInformation { 14 | let creditCardNumber: String 15 | // ...other fields 16 | } 17 | 18 | // A concert 19 | struct Concert { 20 | let id: String 21 | // ...other fields 22 | } 23 | 24 | // A class for interacting with different concerts 25 | class ConcertManager { 26 | } 27 | 28 | // A class for processing payments 29 | class PaymentProcessor { 30 | } 31 | 32 | class OrderFacade { 33 | let concertManager: ConcertManager 34 | let paymentProcessor: PaymentProcessor 35 | 36 | init(concertManager: ConcertManager, paymentProcessor: PaymentProcessor) { 37 | self.concertManager = concertManager 38 | self.paymentProcessor = paymentProcessor 39 | } 40 | 41 | func process(order: Order) { 42 | // process order 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /behavioral-design-patterns/observer/starter/LocationPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | import CoreLocation 3 | 4 | /// An observer that is notified of changes whenever the user’s location changes. 5 | protocol LocationObserver: class { 6 | func didLocationChange(location: CLLocation) 7 | } 8 | 9 | /// A service (i.e. the “subject”) that listens to changes to a user’s location and reports those changes to its observers. 10 | class LocationService: NSObject, CLLocationManagerDelegate { 11 | 12 | private lazy var locationManager: CLLocationManager = { 13 | let locationManager = CLLocationManager() 14 | locationManager.delegate = self 15 | locationManager.desiredAccuracy = kCLLocationAccuracyBest 16 | return locationManager 17 | }() 18 | 19 | func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 20 | // TODO 21 | } 22 | 23 | func startUpdates() { 24 | locationManager.startUpdatingLocation() 25 | } 26 | 27 | func stopUpdates() { 28 | locationManager.stopUpdatingLocation() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Game.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Game.swift 3 | // SingleResponsibilityPrinciple 4 | // 5 | // Created by Christopher Arriola on 1/22/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class Game { 13 | private var score: Int 14 | private var difficulty: Int 15 | private var level: Int 16 | 17 | init(score: Int, difficulty: Int, level: Int) { 18 | self.score = score 19 | self.difficulty = difficulty 20 | self.level = level 21 | } 22 | 23 | func backgroundColor() -> UIColor { 24 | switch self.level { 25 | case 1...10: return UIColor.black 26 | case 11...20: return UIColor.blue 27 | default: return UIColor.red 28 | } 29 | } 30 | 31 | func incrementScore() { 32 | self.score += 10 * difficulty 33 | } 34 | 35 | func updateLevel(to level: Int) { 36 | self.level = level 37 | } 38 | 39 | func changeDifficulty(to difficulty: Int) { 40 | self.difficulty = difficulty 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /behavioral-design-patterns/chain-of-responsibility/starter/ImageProcessing.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | struct Image { 6 | let data: Data 7 | } 8 | 9 | /// Protocol to be implemented by a handler or image processing unit. 10 | protocol ImageHandler { 11 | func handle(image: Image) 12 | } 13 | 14 | /// Image handler that creates a gray scale image from the input image 15 | class GrayscaleConverter: ImageHandler { 16 | func handle(image: Image) { 17 | // create grayscale image 18 | } 19 | } 20 | 21 | /// Image handler that creates a thumbnail image from the input image 22 | class ThumbnailCreator: ImageHandler { 23 | func handle(image: Image) { 24 | // create thumbnail image 25 | } 26 | } 27 | 28 | /// A class that processes an image 29 | class ImageProcessor { 30 | private var handlers: [ImageHandler] = [] 31 | 32 | init() { 33 | handlers = [ 34 | GrayscaleConverter(), 35 | ThumbnailCreator() 36 | ] 37 | } 38 | 39 | func process(image: Image) { 40 | for handler in handlers { 41 | handler.handle(image: image) 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /creational-design-patterns/factory-methods/starter/Music.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | protocol Band { 6 | var name: String { get } 7 | 8 | func playMusic() 9 | } 10 | 11 | class JazzBand: Band { 12 | var name: String { 13 | return "Jazz Vibes" 14 | } 15 | 16 | func playMusic() { 17 | // Play jazz music 18 | } 19 | } 20 | 21 | class ElectronicBand: Band { 22 | var name: String { 23 | return "Above and Beyond" 24 | } 25 | 26 | func playMusic() { 27 | // Play electronic music 28 | } 29 | } 30 | 31 | class PostRockBand: Band { 32 | var name: String { 33 | return "Balmorhea" 34 | } 35 | 36 | func playMusic() { 37 | // Play post-rock music 38 | } 39 | } 40 | 41 | enum Mood { 42 | case classy, focus, dance 43 | } 44 | 45 | class MusicClient { 46 | func playMusic(for mood: Mood) { 47 | let band: Band 48 | switch mood { 49 | case .classy: 50 | band = JazzBand() 51 | case .dance: 52 | band = ElectronicBand() 53 | case .focus: 54 | band = PostRockBand() 55 | } 56 | band.playMusic() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /software-design-principles/liskov-substitution-principle/starter/RectangleArea.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | import Foundation 5 | 6 | class Rectangle { 7 | var width: Int 8 | var height: Int 9 | 10 | var area: Int { 11 | return width * height 12 | } 13 | 14 | init(width: Int, height: Int) { 15 | self.width = width 16 | self.height = height 17 | } 18 | } 19 | 20 | class Square: Rectangle { 21 | 22 | init(side: Int) { 23 | super.init(width: side, height: side) 24 | } 25 | 26 | override var width: Int { 27 | didSet { 28 | guard oldValue != width else { return } 29 | height = width 30 | } 31 | } 32 | 33 | override var height: Int { 34 | didSet { 35 | guard oldValue != height else { return } 36 | width = height 37 | } 38 | } 39 | } 40 | 41 | 42 | func printArea(rectangle: Rectangle) { 43 | rectangle.width = 3 44 | rectangle.height = 4 45 | print(rectangle.area) // Should print 12 (4 * 3) 46 | } 47 | 48 | let rectangle = Rectangle(width: 1, height: 1) 49 | printArea(rectangle: rectangle) 50 | 51 | let square = Square(side: 1) 52 | printArea(rectangle: square) 53 | -------------------------------------------------------------------------------- /behavioral-design-patterns/mediator/starter/EmailSender.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | /// 1. Consumer 6 | struct User { 7 | let name: String 8 | let emailAddress: String 9 | } 10 | 11 | /// 2. Producer 12 | class CustomerRepresentative { 13 | func sendPromotionEmail() { 14 | let email = Email(body: "Get 50% off your next purchase!", subject: "Promo") 15 | let demographics = EmailDemographics(isActiveUser: true, madePurchaseRecently: true) 16 | 17 | let mediator = EmailMediator() 18 | mediator.send(email: email, toUsersWith: demographics) 19 | } 20 | } 21 | 22 | struct Email { 23 | let body: String 24 | let subject: String 25 | } 26 | 27 | struct EmailDemographics { 28 | let isActiveUser: Bool 29 | let madePurchaseRecently: Bool 30 | } 31 | 32 | /// 3. Mediator 33 | class EmailMediator { 34 | 35 | private var users: [User] = [ 36 | User(name: "John", emailAddress: "john@emailprovider.com"), 37 | User(name: "Mary", emailAddress: "mary@emailprovider.com"), 38 | User(name: "Bob", emailAddress: "bob@emailprovider.com") 39 | ] 40 | 41 | func send(email: Email, toUsersWith demographic: EmailDemographics) { 42 | // TODO 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /behavioral-design-patterns/chain-of-responsibility/solution/ImageProcessing.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | struct Image { 6 | let data: Data 7 | } 8 | 9 | /// Protocol to be implemented by a handler or image processing unit. 10 | protocol ImageHandler { 11 | func handle(image: Image) 12 | } 13 | 14 | /// Image handler that creates a gray scale image from the input image 15 | class GrayscaleCreator: ImageHandler { 16 | func handle(image: Image) { 17 | // create grayscale image 18 | } 19 | } 20 | 21 | /// Image handler that creates a thumbnail image from the input image 22 | class ThumbnailCreator: ImageHandler { 23 | func handle(image: Image) { 24 | // create thumbnail image 25 | } 26 | } 27 | 28 | class ImagePersister: ImageHandler { 29 | func handle(image: Image) { 30 | 31 | } 32 | } 33 | 34 | /// A class that processes an image 35 | class ImageProcessor { 36 | private var handlers: [ImageHandler] = [] 37 | 38 | init() { 39 | handlers = [ 40 | GrayscaleCreator(), 41 | ThumbnailCreator(), 42 | ImagePersister() 43 | ] 44 | } 45 | 46 | func process(image: Image) { 47 | for handler in handlers { 48 | handler.handle(image: image) 49 | } 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /behavioral-design-patterns/command/starter/MusicPlayer.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | import Foundation 3 | 4 | /// A protocol that defines a command to play a song. 5 | protocol PlaySongCommand { 6 | func play() 7 | } 8 | 9 | /// A command to play a song that needs to be fetched over the network first 10 | class RemoteSongCommand: PlaySongCommand { 11 | let songURL: URL 12 | 13 | init(songURL: URL) { 14 | self.songURL = songURL 15 | } 16 | 17 | func play() { 18 | // Fetch song file over the network 19 | // Play song file after fetching from the network 20 | } 21 | } 22 | 23 | /// A command to play a song that is available in disk. 24 | class LocalSongCommand: PlaySongCommand { 25 | let songURL: URL 26 | 27 | init(songURL: URL) { 28 | self.songURL = songURL 29 | } 30 | 31 | func play() { 32 | // Fetch song file from disk 33 | // Play song file after fetching from disk 34 | } 35 | } 36 | 37 | /** 38 | The music player which can execute and queue PlaySongCommands. 39 | */ 40 | class MusicPlayer { 41 | 42 | func play(command: PlaySongCommand) { 43 | // TODO 44 | } 45 | 46 | func addToQueue(command: PlaySongCommand) { 47 | // TODO 48 | } 49 | 50 | func playNext() { 51 | // TODO 52 | } 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /behavioral-design-patterns/observer/solution/LocationPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import CoreLocation 4 | 5 | /// An observer that is notified of changes whenever the user’s location changes. 6 | protocol LocationObserver: class { 7 | func didLocationChange(location: CLLocation) 8 | } 9 | 10 | /// A service (i.e. the “subject”) that listens to changes to a user’s location and reports those changes to its observers. 11 | class LocationService: NSObject, CLLocationManagerDelegate { 12 | 13 | var observers = [LocationObserver]() 14 | 15 | private lazy var locationManager: CLLocationManager = { 16 | let locationManager = CLLocationManager() 17 | locationManager.delegate = self 18 | locationManager.desiredAccuracy = kCLLocationAccuracyBest 19 | return locationManager 20 | }() 21 | 22 | func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 23 | for observer in observers { 24 | observer.didLocationChange(location: locations[0]) 25 | } 26 | } 27 | 28 | func subscribe(observer: LocationObserver) { 29 | observers.append(observer) 30 | } 31 | 32 | func startUpdates() { 33 | locationManager.startUpdatingLocation() 34 | } 35 | 36 | func stopUpdates() { 37 | locationManager.stopUpdatingLocation() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /creational-design-patterns/factory-methods/solution/Music.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | protocol Band { 6 | var name: String { get } 7 | 8 | func playMusic() 9 | } 10 | 11 | class JazzBand: Band { 12 | var name: String { 13 | return "Jazz Vibes" 14 | } 15 | 16 | func playMusic() { 17 | // Play jazz music 18 | } 19 | } 20 | 21 | class ElectronicBand: Band { 22 | var name: String { 23 | return "Above and Beyond" 24 | } 25 | 26 | func playMusic() { 27 | // Play electronic music 28 | } 29 | } 30 | 31 | class PostRockBand: Band { 32 | var name: String { 33 | return "Balmorhea" 34 | } 35 | 36 | func playMusic() { 37 | // Play post-rock music 38 | } 39 | } 40 | 41 | enum Mood { 42 | case classy, focus, dance 43 | } 44 | 45 | class BandFactory { 46 | func createBand(forMood mood: Mood) -> Band { 47 | let band: Band 48 | switch mood { 49 | case .classy: 50 | band = JazzBand() 51 | case .dance: 52 | band = ElectronicBand() 53 | case .focus: 54 | band = PostRockBand() 55 | } 56 | return band 57 | } 58 | } 59 | 60 | class MusicClient { 61 | func playMusic(for mood: Mood) { 62 | let band = BandFactory().createBand(forMood: mood) 63 | band.playMusic() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /structural-design-patterns/decorator/solution/Decorators.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | enum Instrument { 4 | case guitar 5 | case drums 6 | case bass 7 | // ... 8 | } 9 | 10 | protocol Musician { 11 | var instrument: Instrument { get } 12 | func play() 13 | } 14 | 15 | extension Musician { 16 | func play() { 17 | print("plays the \(instrument)") 18 | } 19 | } 20 | 21 | class Guitarist: Musician { 22 | var instrument: Instrument { return .guitar } 23 | } 24 | 25 | class Drummer: Musician { 26 | var instrument: Instrument { return .drums } 27 | } 28 | 29 | class MusicianDecorator: Musician { 30 | var instrument: Instrument { return decoratedMusician.instrument } 31 | 32 | private let decoratedMusician: Musician 33 | 34 | init(_ decoratedMusician: Musician) { 35 | self.decoratedMusician = decoratedMusician 36 | } 37 | 38 | func play() { 39 | decoratedMusician.play() 40 | } 41 | } 42 | 43 | class GuitarDecorator: MusicianDecorator { 44 | override func play() { 45 | super.play() 46 | print(" and play the \(Instrument.guitar)") 47 | } 48 | } 49 | 50 | class DrummerDecorator: MusicianDecorator { 51 | override func play() { 52 | super.play() 53 | print(" and play the \(Instrument.drums)") 54 | } 55 | } 56 | 57 | let drummerAndGuitarist = DrummerDecorator(Guitarist()) 58 | drummerAndGuitarist.play() 59 | 60 | -------------------------------------------------------------------------------- /behavioral-design-patterns/command/solution/MusicPlayer.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | import Foundation 3 | 4 | /// A protocol that defines a command to play a song. 5 | protocol PlaySongCommand { 6 | func play() 7 | } 8 | 9 | /// A command to play a song that needs to be fetched over the network first 10 | class RemoteSongCommand: PlaySongCommand { 11 | let songURL: URL 12 | 13 | init(songURL: URL) { 14 | self.songURL = songURL 15 | } 16 | 17 | func play() { 18 | // Fetch song file over the network 19 | // Play song file after fetching from the network 20 | } 21 | } 22 | 23 | /// A command to play a song that is available in disk. 24 | class LocalSongCommand: PlaySongCommand { 25 | let songURL: URL 26 | 27 | init(songURL: URL) { 28 | self.songURL = songURL 29 | } 30 | 31 | func play() { 32 | // Fetch song file from disk 33 | // Play song file after fetching from disk 34 | } 35 | } 36 | 37 | /** 38 | The music player which can execute and queue PlaySongCommands. 39 | */ 40 | class MusicPlayer { 41 | 42 | private var queue: [PlaySongCommand] = [] 43 | 44 | func play(command: PlaySongCommand) { 45 | command.play() 46 | } 47 | 48 | func addToQueue(command: PlaySongCommand) { 49 | queue.append(command) 50 | } 51 | 52 | func playNext() { 53 | guard !queue.isEmpty else { return } 54 | let command = queue.removeFirst() 55 | play(command: command) 56 | } 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /behavioral-design-patterns/mediator/solution/EmailSender.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | /// 1. Consumer 6 | struct User { 7 | let name: String 8 | let emailAddress: String 9 | } 10 | 11 | /// 2. Producer 12 | class CustomerRepresentative { 13 | func sendPromotionEmail() { 14 | let email = Email(body: "Get 50% off your next purchase!", subject: "Promo") 15 | let demographics = EmailDemographics(isActiveUser: true, madePurchaseRecently: true) 16 | 17 | let mediator = EmailMediator() 18 | mediator.send(email: email, toUsersWith: demographics) 19 | } 20 | } 21 | 22 | struct Email { 23 | let body: String 24 | let subject: String 25 | } 26 | 27 | struct EmailDemographics { 28 | let isActiveUser: Bool 29 | let madePurchaseRecently: Bool 30 | } 31 | 32 | /// 3. Mediator 33 | class EmailMediator { 34 | 35 | private var users: [User] = [ 36 | User(name: "John", emailAddress: "john@emailprovider.com"), 37 | User(name: "Mary", emailAddress: "mary@emailprovider.com"), 38 | User(name: "Bob", emailAddress: "bob@emailprovider.com") 39 | ] 40 | 41 | func send(email: Email, toUsersWith demographic: EmailDemographics) { 42 | for user in users { 43 | if user.satisfies(demographic: demographic) { 44 | send(email: email, to: user) 45 | } 46 | } 47 | } 48 | 49 | private func send(email: Email, to user: User) { 50 | // Send email 51 | } 52 | } 53 | 54 | extension User { 55 | func satisfies(demographic: EmailDemographics) -> Bool { 56 | return true 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Game.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Game.swift 3 | // SingleResponsibilityPrinciple 4 | // 5 | // Created by Christopher Arriola on 1/22/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class GameViewState { 13 | func backgroundColor(level: Int) -> UIColor { 14 | switch level { 15 | case 1...10: return UIColor.black 16 | case 11...20: return UIColor.blue 17 | default: return UIColor.red 18 | } 19 | } 20 | } 21 | 22 | class ScoreTracker { 23 | 24 | private var score: Int 25 | 26 | init(score: Int) { 27 | self.score = score 28 | } 29 | 30 | func incrementScore(difficulty: Int) { 31 | self.score += 10 * difficulty 32 | } 33 | } 34 | 35 | class Game { 36 | private var difficulty: Int 37 | private var level: Int 38 | private var scoreTracker: ScoreTracker 39 | private var viewState = GameViewState() 40 | 41 | init(score: Int, difficulty: Int, level: Int) { 42 | self.scoreTracker = ScoreTracker(score: score) 43 | self.difficulty = difficulty 44 | self.level = level 45 | } 46 | 47 | func incrementScore() { 48 | scoreTracker.incrementScore(difficulty: difficulty) 49 | } 50 | 51 | func backgroundColor() -> UIColor { 52 | return viewState.backgroundColor(level: level) 53 | } 54 | 55 | func updateLevel(to level: Int) { 56 | self.level = level 57 | } 58 | 59 | func changeDifficulty(to difficulty: Int) { 60 | self.difficulty = difficulty 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /.github/workflows/manual.yml: -------------------------------------------------------------------------------- 1 | # Workflow to ensure whenever a Github PR is submitted, 2 | # a JIRA ticket gets created automatically. 3 | name: Manual Workflow 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on pull request events but only for the master branch 8 | pull_request_target: 9 | types: [opened, reopened] 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | jobs: 15 | test-transition-issue: 16 | name: Convert Github Issue to Jira Issue 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@master 21 | 22 | - name: Login 23 | uses: atlassian/gajira-login@master 24 | env: 25 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} 26 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} 27 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} 28 | 29 | - name: Create NEW JIRA ticket 30 | id: create 31 | uses: atlassian/gajira-create@master 32 | with: 33 | project: CONUPDATE 34 | issuetype: Task 35 | summary: | 36 | Github PR [Assign the ND component] | Repo: ${{ github.repository }} | PR# ${{github.event.number}} 37 | description: | 38 | Repo link: https://github.com/${{ github.repository }} 39 | PR no. ${{ github.event.pull_request.number }} 40 | PR title: ${{ github.event.pull_request.title }} 41 | PR description: ${{ github.event.pull_request.description }} 42 | In addition, please resolve other issues, if any. 43 | fields: '{"components": [{"name":"Github PR"}], "customfield_16449":"https://classroom.udacity.com/", "customfield_16450":"Resolve the PR", "labels": ["github"], "priority":{"id": "4"}}' 44 | 45 | - name: Log created issue 46 | run: echo "Issue ${{ steps.create.outputs.issue }} was created" 47 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DRY 4 | // 5 | // Created by Christopher Arriola on 1/21/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /creational-design-patterns/builder-exercise/SignUpApp/SignUpApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SignUpApp 4 | // 5 | // Created by Christopher Arriola on 2/9/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ObjectPool 4 | // 5 | // Created by Christopher Arriola on 2/5/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ObjectPool 4 | // 5 | // Created by Christopher Arriola on 2/5/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/solution/AreaCalculator/AreaCalculator/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // AreaCalculator 4 | // 5 | // Created by Christopher Arriola on 1/24/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /software-design-principles/open-closed-principle/starter/AreaCalculator/AreaCalculator/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // AreaCalculator 4 | // 5 | // Created by Christopher Arriola on 1/24/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ObjectPool 4 | // 5 | // Created by Christopher Arriola on 2/5/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | private var timer: Timer? 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | // Do any additional setup after loading the view, typically from a nib. 18 | } 19 | 20 | override func viewWillAppear(_ animated: Bool) { 21 | super.viewWillAppear(animated) 22 | 23 | // 1. Create a timer that will add snowflakes at regular intervals 24 | timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { _ in 25 | 26 | // 2. When the timer is triggered, add a snowflake 27 | let snowflake = SnowflakeView() 28 | snowflake.animateFallingSnowflake(to: self.view) 29 | } 30 | } 31 | 32 | override func viewWillDisappear(_ animated: Bool) { 33 | timer?.invalidate() 34 | timer = nil 35 | super.viewWillDisappear(animated) 36 | } 37 | } 38 | 39 | class SnowflakeView: UIImageView { 40 | 41 | private var randomXPosition: CGFloat { 42 | get { 43 | let maxX = self.superview?.frame.width ?? self.frame.width 44 | return CGFloat(arc4random_uniform(UInt32(maxX))) 45 | } 46 | } 47 | 48 | init() { 49 | super.init(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) 50 | sharedInit() 51 | } 52 | 53 | required init?(coder aDecoder: NSCoder) { 54 | super.init(coder: aDecoder) 55 | sharedInit() 56 | } 57 | 58 | private func sharedInit() { 59 | image = UIImage(named: "snowflake") 60 | contentMode = .scaleAspectFit 61 | } 62 | 63 | func animateFallingSnowflake(to view: UIView) { 64 | view.addSubview(self) 65 | 66 | frame = CGRect(x: randomXPosition, y: -self.frame.height, width: self.frame.width, height: self.frame.height) 67 | 68 | UIView.animate(withDuration: 3, animations: { 69 | self.frame = CGRect(x: self.randomXPosition, y: self.superview!.frame.height + self.frame.height, width: self.frame.width, height: self.frame.height) 70 | }) { _ in 71 | // Animation complete 72 | } 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/solution/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SingleResponsibilityPrinciple 4 | // 5 | // Created by Christopher Arriola on 1/22/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /software-design-principles/single-responsibility-principle/starter/SingleResponsibilityPrinciple/SingleResponsibilityPrinciple/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SingleResponsibilityPrinciple 4 | // 5 | // Created by Christopher Arriola on 1/22/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS - Mobile Design Patterns 2 | This repository contains applications, and Xcode Playground files, to demonstrate concepts taught in Udacity's "iOS - Mobile Design Patterns". Each project contains a starter, and corresponding solution, to be used to follow along the videos throughout the course. 3 | 4 | The concepts with projects/playground files are: 5 | 6 | ### Software Design Principles 7 | * [Keep it DRY](https://github.com/udacity/iosnd-design-patterns/tree/master/software-design-principles/dry-principle) 8 | * [Single Responsibility Principle](https://github.com/udacity/iosnd-design-patterns/tree/master/software-design-principles/single-responsibility-principle) 9 | * [Open/Closed Principle](https://github.com/udacity/iosnd-design-patterns/tree/master/software-design-principles/open-closed-principle) 10 | * [Liskov Substitution Principle](https://github.com/udacity/iosnd-design-patterns/tree/master/software-design-principles/liskov-substitution-principle) 11 | * [Interface Segregation Principle](https://github.com/udacity/iosnd-design-patterns/tree/master/software-design-principles/interface-segregation-principle) 12 | * [Dependency Inversion Principle](https://github.com/udacity/iosnd-design-patterns/tree/master/software-design-principles/dependency-inversion-principle) 13 | 14 | ### Creational Design Patterns 15 | * [Factory Methods](https://github.com/udacity/iosnd-design-patterns/tree/master/creational-design-patterns/factory-methods) 16 | * [Singleton](https://github.com/udacity/iosnd-design-patterns/tree/master/creational-design-patterns/singleton) 17 | * [Dependency Injection](https://github.com/udacity/iosnd-design-patterns/tree/master/creational-design-patterns/dependency-injection) 18 | * [Object Pool](https://github.com/udacity/iosnd-design-patterns/tree/master/creational-design-patterns/object-pool) 19 | * [Builder](https://github.com/udacity/iosnd-design-patterns/tree/master/creational-design-patterns/builder) 20 | * [Builder Exercise](https://github.com/udacity/iosnd-design-patterns/tree/master/creational-design-patterns/builder-exercise/SignUpApp) 21 | 22 | ### Structural Design Patterns 23 | * [Adapter](https://github.com/udacity/iosnd-design-patterns/tree/master/structural-design-patterns/adapter) 24 | * [Facade](https://github.com/udacity/iosnd-design-patterns/tree/master/structural-design-patterns/facade) 25 | * [Decorator](https://github.com/udacity/iosnd-design-patterns/tree/master/structural-design-patterns/decorator) 26 | 27 | ### Behavioral Design Patterns 28 | * [Observer](https://github.com/udacity/iosnd-design-patterns/tree/master/behavioral-design-patterns/observer) 29 | * [Command](https://github.com/udacity/iosnd-design-patterns/tree/master/behavioral-design-patterns/command) 30 | * [Chain of Responsibility](https://github.com/udacity/iosnd-design-patterns/tree/master/behavioral-design-patterns/chain-of-responsibility) 31 | * [Mediator](https://github.com/udacity/iosnd-design-patterns/tree/master/behavioral-design-patterns/mediator) -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ObjectPool 4 | // 5 | // Created by Christopher Arriola on 2/5/18. 6 | // Copyright © 2018 Udacity. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | private var timer: Timer? 14 | private var snowflakePool: [SnowflakeView] = [] 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | // Do any additional setup after loading the view, typically from a nib. 19 | for _ in 1...100 { 20 | let snowflake = SnowflakeView() 21 | snowflakePool.append(snowflake) 22 | } 23 | } 24 | 25 | override func viewWillAppear(_ animated: Bool) { 26 | super.viewWillAppear(animated) 27 | 28 | // 1. Create a timer that will add snowflakes at regular intervals 29 | timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { _ in 30 | 31 | // 2. When the timer is triggered, add a snowflake 32 | guard let snowflake = self.snowflakePool.popLast() else { 33 | print("No more snowflakes in the pool!") 34 | return 35 | } 36 | snowflake.animateFallingSnowflake(to: self.view) { 37 | self.snowflakePool.append(snowflake) 38 | } 39 | } 40 | } 41 | 42 | override func viewWillDisappear(_ animated: Bool) { 43 | timer?.invalidate() 44 | timer = nil 45 | super.viewWillDisappear(animated) 46 | } 47 | } 48 | 49 | class SnowflakeView: UIImageView { 50 | 51 | private var randomXPosition: CGFloat { 52 | get { 53 | let maxX = self.superview?.frame.width ?? self.frame.width 54 | return CGFloat(arc4random_uniform(UInt32(maxX))) 55 | } 56 | } 57 | 58 | init() { 59 | super.init(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) 60 | sharedInit() 61 | } 62 | 63 | required init?(coder aDecoder: NSCoder) { 64 | super.init(coder: aDecoder) 65 | sharedInit() 66 | } 67 | 68 | private func sharedInit() { 69 | image = UIImage(named: "snowflake") 70 | contentMode = .scaleAspectFit 71 | } 72 | 73 | func animateFallingSnowflake(to view: UIView, completion: @escaping (() -> Void)) { 74 | view.addSubview(self) 75 | 76 | frame = CGRect(x: randomXPosition, y: -self.frame.height, width: self.frame.width, height: self.frame.height) 77 | 78 | UIView.animate(withDuration: 3, animations: { 79 | self.frame = CGRect(x: self.randomXPosition, y: self.superview!.frame.height + self.frame.height, width: self.frame.width, height: self.frame.height) 80 | }) { _ in 81 | // Animation complete 82 | completion() 83 | } 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/solution/DRY/DRY/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /software-design-principles/dry-principle/starter/DRY/DRY/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/solution/ObjectPool/ObjectPool.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8399925A2029114B00C76A1E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839992592029114B00C76A1E /* AppDelegate.swift */; }; 11 | 8399925C2029114B00C76A1E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8399925B2029114B00C76A1E /* ViewController.swift */; }; 12 | 8399925F2029114B00C76A1E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8399925D2029114B00C76A1E /* Main.storyboard */; }; 13 | 839992612029114B00C76A1E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 839992602029114B00C76A1E /* Assets.xcassets */; }; 14 | 839992642029114B00C76A1E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 839992622029114B00C76A1E /* LaunchScreen.storyboard */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 839992562029114B00C76A1E /* ObjectPool.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ObjectPool.app; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 839992592029114B00C76A1E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 20 | 8399925B2029114B00C76A1E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 21 | 8399925E2029114B00C76A1E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 22 | 839992602029114B00C76A1E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 23 | 839992632029114B00C76A1E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 24 | 839992652029114B00C76A1E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 25 | /* End PBXFileReference section */ 26 | 27 | /* Begin PBXFrameworksBuildPhase section */ 28 | 839992532029114B00C76A1E /* Frameworks */ = { 29 | isa = PBXFrameworksBuildPhase; 30 | buildActionMask = 2147483647; 31 | files = ( 32 | ); 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXFrameworksBuildPhase section */ 36 | 37 | /* Begin PBXGroup section */ 38 | 8399924D2029114B00C76A1E = { 39 | isa = PBXGroup; 40 | children = ( 41 | 839992582029114B00C76A1E /* ObjectPool */, 42 | 839992572029114B00C76A1E /* Products */, 43 | ); 44 | sourceTree = ""; 45 | }; 46 | 839992572029114B00C76A1E /* Products */ = { 47 | isa = PBXGroup; 48 | children = ( 49 | 839992562029114B00C76A1E /* ObjectPool.app */, 50 | ); 51 | name = Products; 52 | sourceTree = ""; 53 | }; 54 | 839992582029114B00C76A1E /* ObjectPool */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | 839992592029114B00C76A1E /* AppDelegate.swift */, 58 | 8399925B2029114B00C76A1E /* ViewController.swift */, 59 | 8399925D2029114B00C76A1E /* Main.storyboard */, 60 | 839992602029114B00C76A1E /* Assets.xcassets */, 61 | 839992622029114B00C76A1E /* LaunchScreen.storyboard */, 62 | 839992652029114B00C76A1E /* Info.plist */, 63 | ); 64 | path = ObjectPool; 65 | sourceTree = ""; 66 | }; 67 | /* End PBXGroup section */ 68 | 69 | /* Begin PBXNativeTarget section */ 70 | 839992552029114B00C76A1E /* ObjectPool */ = { 71 | isa = PBXNativeTarget; 72 | buildConfigurationList = 839992682029114B00C76A1E /* Build configuration list for PBXNativeTarget "ObjectPool" */; 73 | buildPhases = ( 74 | 839992522029114B00C76A1E /* Sources */, 75 | 839992532029114B00C76A1E /* Frameworks */, 76 | 839992542029114B00C76A1E /* Resources */, 77 | ); 78 | buildRules = ( 79 | ); 80 | dependencies = ( 81 | ); 82 | name = ObjectPool; 83 | productName = ObjectPool; 84 | productReference = 839992562029114B00C76A1E /* ObjectPool.app */; 85 | productType = "com.apple.product-type.application"; 86 | }; 87 | /* End PBXNativeTarget section */ 88 | 89 | /* Begin PBXProject section */ 90 | 8399924E2029114B00C76A1E /* Project object */ = { 91 | isa = PBXProject; 92 | attributes = { 93 | LastSwiftUpdateCheck = 0920; 94 | LastUpgradeCheck = 0920; 95 | ORGANIZATIONNAME = Udacity; 96 | TargetAttributes = { 97 | 839992552029114B00C76A1E = { 98 | CreatedOnToolsVersion = 9.2; 99 | ProvisioningStyle = Automatic; 100 | }; 101 | }; 102 | }; 103 | buildConfigurationList = 839992512029114B00C76A1E /* Build configuration list for PBXProject "ObjectPool" */; 104 | compatibilityVersion = "Xcode 8.0"; 105 | developmentRegion = en; 106 | hasScannedForEncodings = 0; 107 | knownRegions = ( 108 | en, 109 | Base, 110 | ); 111 | mainGroup = 8399924D2029114B00C76A1E; 112 | productRefGroup = 839992572029114B00C76A1E /* Products */; 113 | projectDirPath = ""; 114 | projectRoot = ""; 115 | targets = ( 116 | 839992552029114B00C76A1E /* ObjectPool */, 117 | ); 118 | }; 119 | /* End PBXProject section */ 120 | 121 | /* Begin PBXResourcesBuildPhase section */ 122 | 839992542029114B00C76A1E /* Resources */ = { 123 | isa = PBXResourcesBuildPhase; 124 | buildActionMask = 2147483647; 125 | files = ( 126 | 839992642029114B00C76A1E /* LaunchScreen.storyboard in Resources */, 127 | 839992612029114B00C76A1E /* Assets.xcassets in Resources */, 128 | 8399925F2029114B00C76A1E /* Main.storyboard in Resources */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXResourcesBuildPhase section */ 133 | 134 | /* Begin PBXSourcesBuildPhase section */ 135 | 839992522029114B00C76A1E /* Sources */ = { 136 | isa = PBXSourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | 8399925C2029114B00C76A1E /* ViewController.swift in Sources */, 140 | 8399925A2029114B00C76A1E /* AppDelegate.swift in Sources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXSourcesBuildPhase section */ 145 | 146 | /* Begin PBXVariantGroup section */ 147 | 8399925D2029114B00C76A1E /* Main.storyboard */ = { 148 | isa = PBXVariantGroup; 149 | children = ( 150 | 8399925E2029114B00C76A1E /* Base */, 151 | ); 152 | name = Main.storyboard; 153 | sourceTree = ""; 154 | }; 155 | 839992622029114B00C76A1E /* LaunchScreen.storyboard */ = { 156 | isa = PBXVariantGroup; 157 | children = ( 158 | 839992632029114B00C76A1E /* Base */, 159 | ); 160 | name = LaunchScreen.storyboard; 161 | sourceTree = ""; 162 | }; 163 | /* End PBXVariantGroup section */ 164 | 165 | /* Begin XCBuildConfiguration section */ 166 | 839992662029114B00C76A1E /* Debug */ = { 167 | isa = XCBuildConfiguration; 168 | buildSettings = { 169 | ALWAYS_SEARCH_USER_PATHS = NO; 170 | CLANG_ANALYZER_NONNULL = YES; 171 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 172 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 173 | CLANG_CXX_LIBRARY = "libc++"; 174 | CLANG_ENABLE_MODULES = YES; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 177 | CLANG_WARN_BOOL_CONVERSION = YES; 178 | CLANG_WARN_COMMA = YES; 179 | CLANG_WARN_CONSTANT_CONVERSION = YES; 180 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 181 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 182 | CLANG_WARN_EMPTY_BODY = YES; 183 | CLANG_WARN_ENUM_CONVERSION = YES; 184 | CLANG_WARN_INFINITE_RECURSION = YES; 185 | CLANG_WARN_INT_CONVERSION = YES; 186 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 187 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 188 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 189 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 190 | CLANG_WARN_STRICT_PROTOTYPES = YES; 191 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 192 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 193 | CLANG_WARN_UNREACHABLE_CODE = YES; 194 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 195 | CODE_SIGN_IDENTITY = "iPhone Developer"; 196 | COPY_PHASE_STRIP = NO; 197 | DEBUG_INFORMATION_FORMAT = dwarf; 198 | ENABLE_STRICT_OBJC_MSGSEND = YES; 199 | ENABLE_TESTABILITY = YES; 200 | GCC_C_LANGUAGE_STANDARD = gnu11; 201 | GCC_DYNAMIC_NO_PIC = NO; 202 | GCC_NO_COMMON_BLOCKS = YES; 203 | GCC_OPTIMIZATION_LEVEL = 0; 204 | GCC_PREPROCESSOR_DEFINITIONS = ( 205 | "DEBUG=1", 206 | "$(inherited)", 207 | ); 208 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 209 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 210 | GCC_WARN_UNDECLARED_SELECTOR = YES; 211 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 212 | GCC_WARN_UNUSED_FUNCTION = YES; 213 | GCC_WARN_UNUSED_VARIABLE = YES; 214 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 215 | MTL_ENABLE_DEBUG_INFO = YES; 216 | ONLY_ACTIVE_ARCH = YES; 217 | SDKROOT = iphoneos; 218 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 219 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 220 | }; 221 | name = Debug; 222 | }; 223 | 839992672029114B00C76A1E /* Release */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | ALWAYS_SEARCH_USER_PATHS = NO; 227 | CLANG_ANALYZER_NONNULL = YES; 228 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 230 | CLANG_CXX_LIBRARY = "libc++"; 231 | CLANG_ENABLE_MODULES = YES; 232 | CLANG_ENABLE_OBJC_ARC = YES; 233 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_COMMA = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 238 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 239 | CLANG_WARN_EMPTY_BODY = YES; 240 | CLANG_WARN_ENUM_CONVERSION = YES; 241 | CLANG_WARN_INFINITE_RECURSION = YES; 242 | CLANG_WARN_INT_CONVERSION = YES; 243 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 244 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 245 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 246 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 247 | CLANG_WARN_STRICT_PROTOTYPES = YES; 248 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 249 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 250 | CLANG_WARN_UNREACHABLE_CODE = YES; 251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 252 | CODE_SIGN_IDENTITY = "iPhone Developer"; 253 | COPY_PHASE_STRIP = NO; 254 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 255 | ENABLE_NS_ASSERTIONS = NO; 256 | ENABLE_STRICT_OBJC_MSGSEND = YES; 257 | GCC_C_LANGUAGE_STANDARD = gnu11; 258 | GCC_NO_COMMON_BLOCKS = YES; 259 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 260 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 261 | GCC_WARN_UNDECLARED_SELECTOR = YES; 262 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 263 | GCC_WARN_UNUSED_FUNCTION = YES; 264 | GCC_WARN_UNUSED_VARIABLE = YES; 265 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 266 | MTL_ENABLE_DEBUG_INFO = NO; 267 | SDKROOT = iphoneos; 268 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 269 | VALIDATE_PRODUCT = YES; 270 | }; 271 | name = Release; 272 | }; 273 | 839992692029114B00C76A1E /* Debug */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 277 | CODE_SIGN_STYLE = Automatic; 278 | DEVELOPMENT_TEAM = 3K82E7YE87; 279 | INFOPLIST_FILE = ObjectPool/Info.plist; 280 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 281 | PRODUCT_BUNDLE_IDENTIFIER = udacity.ObjectPool; 282 | PRODUCT_NAME = "$(TARGET_NAME)"; 283 | SWIFT_VERSION = 4.0; 284 | TARGETED_DEVICE_FAMILY = "1,2"; 285 | }; 286 | name = Debug; 287 | }; 288 | 8399926A2029114B00C76A1E /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 292 | CODE_SIGN_STYLE = Automatic; 293 | DEVELOPMENT_TEAM = 3K82E7YE87; 294 | INFOPLIST_FILE = ObjectPool/Info.plist; 295 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 296 | PRODUCT_BUNDLE_IDENTIFIER = udacity.ObjectPool; 297 | PRODUCT_NAME = "$(TARGET_NAME)"; 298 | SWIFT_VERSION = 4.0; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | 839992512029114B00C76A1E /* Build configuration list for PBXProject "ObjectPool" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | 839992662029114B00C76A1E /* Debug */, 310 | 839992672029114B00C76A1E /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | 839992682029114B00C76A1E /* Build configuration list for PBXNativeTarget "ObjectPool" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | 839992692029114B00C76A1E /* Debug */, 319 | 8399926A2029114B00C76A1E /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = 8399924E2029114B00C76A1E /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /creational-design-patterns/object-pool/starter/ObjectPool/ObjectPool.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8399925A2029114B00C76A1E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839992592029114B00C76A1E /* AppDelegate.swift */; }; 11 | 8399925C2029114B00C76A1E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8399925B2029114B00C76A1E /* ViewController.swift */; }; 12 | 8399925F2029114B00C76A1E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8399925D2029114B00C76A1E /* Main.storyboard */; }; 13 | 839992612029114B00C76A1E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 839992602029114B00C76A1E /* Assets.xcassets */; }; 14 | 839992642029114B00C76A1E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 839992622029114B00C76A1E /* LaunchScreen.storyboard */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 839992562029114B00C76A1E /* ObjectPool.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ObjectPool.app; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 839992592029114B00C76A1E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 20 | 8399925B2029114B00C76A1E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 21 | 8399925E2029114B00C76A1E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 22 | 839992602029114B00C76A1E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 23 | 839992632029114B00C76A1E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 24 | 839992652029114B00C76A1E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 25 | /* End PBXFileReference section */ 26 | 27 | /* Begin PBXFrameworksBuildPhase section */ 28 | 839992532029114B00C76A1E /* Frameworks */ = { 29 | isa = PBXFrameworksBuildPhase; 30 | buildActionMask = 2147483647; 31 | files = ( 32 | ); 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXFrameworksBuildPhase section */ 36 | 37 | /* Begin PBXGroup section */ 38 | 8399924D2029114B00C76A1E = { 39 | isa = PBXGroup; 40 | children = ( 41 | 839992582029114B00C76A1E /* ObjectPool */, 42 | 839992572029114B00C76A1E /* Products */, 43 | ); 44 | sourceTree = ""; 45 | }; 46 | 839992572029114B00C76A1E /* Products */ = { 47 | isa = PBXGroup; 48 | children = ( 49 | 839992562029114B00C76A1E /* ObjectPool.app */, 50 | ); 51 | name = Products; 52 | sourceTree = ""; 53 | }; 54 | 839992582029114B00C76A1E /* ObjectPool */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | 839992592029114B00C76A1E /* AppDelegate.swift */, 58 | 8399925B2029114B00C76A1E /* ViewController.swift */, 59 | 8399925D2029114B00C76A1E /* Main.storyboard */, 60 | 839992602029114B00C76A1E /* Assets.xcassets */, 61 | 839992622029114B00C76A1E /* LaunchScreen.storyboard */, 62 | 839992652029114B00C76A1E /* Info.plist */, 63 | ); 64 | path = ObjectPool; 65 | sourceTree = ""; 66 | }; 67 | /* End PBXGroup section */ 68 | 69 | /* Begin PBXNativeTarget section */ 70 | 839992552029114B00C76A1E /* ObjectPool */ = { 71 | isa = PBXNativeTarget; 72 | buildConfigurationList = 839992682029114B00C76A1E /* Build configuration list for PBXNativeTarget "ObjectPool" */; 73 | buildPhases = ( 74 | 839992522029114B00C76A1E /* Sources */, 75 | 839992532029114B00C76A1E /* Frameworks */, 76 | 839992542029114B00C76A1E /* Resources */, 77 | ); 78 | buildRules = ( 79 | ); 80 | dependencies = ( 81 | ); 82 | name = ObjectPool; 83 | productName = ObjectPool; 84 | productReference = 839992562029114B00C76A1E /* ObjectPool.app */; 85 | productType = "com.apple.product-type.application"; 86 | }; 87 | /* End PBXNativeTarget section */ 88 | 89 | /* Begin PBXProject section */ 90 | 8399924E2029114B00C76A1E /* Project object */ = { 91 | isa = PBXProject; 92 | attributes = { 93 | LastSwiftUpdateCheck = 0920; 94 | LastUpgradeCheck = 0920; 95 | ORGANIZATIONNAME = Udacity; 96 | TargetAttributes = { 97 | 839992552029114B00C76A1E = { 98 | CreatedOnToolsVersion = 9.2; 99 | ProvisioningStyle = Automatic; 100 | }; 101 | }; 102 | }; 103 | buildConfigurationList = 839992512029114B00C76A1E /* Build configuration list for PBXProject "ObjectPool" */; 104 | compatibilityVersion = "Xcode 8.0"; 105 | developmentRegion = en; 106 | hasScannedForEncodings = 0; 107 | knownRegions = ( 108 | en, 109 | Base, 110 | ); 111 | mainGroup = 8399924D2029114B00C76A1E; 112 | productRefGroup = 839992572029114B00C76A1E /* Products */; 113 | projectDirPath = ""; 114 | projectRoot = ""; 115 | targets = ( 116 | 839992552029114B00C76A1E /* ObjectPool */, 117 | ); 118 | }; 119 | /* End PBXProject section */ 120 | 121 | /* Begin PBXResourcesBuildPhase section */ 122 | 839992542029114B00C76A1E /* Resources */ = { 123 | isa = PBXResourcesBuildPhase; 124 | buildActionMask = 2147483647; 125 | files = ( 126 | 839992642029114B00C76A1E /* LaunchScreen.storyboard in Resources */, 127 | 839992612029114B00C76A1E /* Assets.xcassets in Resources */, 128 | 8399925F2029114B00C76A1E /* Main.storyboard in Resources */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXResourcesBuildPhase section */ 133 | 134 | /* Begin PBXSourcesBuildPhase section */ 135 | 839992522029114B00C76A1E /* Sources */ = { 136 | isa = PBXSourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | 8399925C2029114B00C76A1E /* ViewController.swift in Sources */, 140 | 8399925A2029114B00C76A1E /* AppDelegate.swift in Sources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXSourcesBuildPhase section */ 145 | 146 | /* Begin PBXVariantGroup section */ 147 | 8399925D2029114B00C76A1E /* Main.storyboard */ = { 148 | isa = PBXVariantGroup; 149 | children = ( 150 | 8399925E2029114B00C76A1E /* Base */, 151 | ); 152 | name = Main.storyboard; 153 | sourceTree = ""; 154 | }; 155 | 839992622029114B00C76A1E /* LaunchScreen.storyboard */ = { 156 | isa = PBXVariantGroup; 157 | children = ( 158 | 839992632029114B00C76A1E /* Base */, 159 | ); 160 | name = LaunchScreen.storyboard; 161 | sourceTree = ""; 162 | }; 163 | /* End PBXVariantGroup section */ 164 | 165 | /* Begin XCBuildConfiguration section */ 166 | 839992662029114B00C76A1E /* Debug */ = { 167 | isa = XCBuildConfiguration; 168 | buildSettings = { 169 | ALWAYS_SEARCH_USER_PATHS = NO; 170 | CLANG_ANALYZER_NONNULL = YES; 171 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 172 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 173 | CLANG_CXX_LIBRARY = "libc++"; 174 | CLANG_ENABLE_MODULES = YES; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 177 | CLANG_WARN_BOOL_CONVERSION = YES; 178 | CLANG_WARN_COMMA = YES; 179 | CLANG_WARN_CONSTANT_CONVERSION = YES; 180 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 181 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 182 | CLANG_WARN_EMPTY_BODY = YES; 183 | CLANG_WARN_ENUM_CONVERSION = YES; 184 | CLANG_WARN_INFINITE_RECURSION = YES; 185 | CLANG_WARN_INT_CONVERSION = YES; 186 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 187 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 188 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 189 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 190 | CLANG_WARN_STRICT_PROTOTYPES = YES; 191 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 192 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 193 | CLANG_WARN_UNREACHABLE_CODE = YES; 194 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 195 | CODE_SIGN_IDENTITY = "iPhone Developer"; 196 | COPY_PHASE_STRIP = NO; 197 | DEBUG_INFORMATION_FORMAT = dwarf; 198 | ENABLE_STRICT_OBJC_MSGSEND = YES; 199 | ENABLE_TESTABILITY = YES; 200 | GCC_C_LANGUAGE_STANDARD = gnu11; 201 | GCC_DYNAMIC_NO_PIC = NO; 202 | GCC_NO_COMMON_BLOCKS = YES; 203 | GCC_OPTIMIZATION_LEVEL = 0; 204 | GCC_PREPROCESSOR_DEFINITIONS = ( 205 | "DEBUG=1", 206 | "$(inherited)", 207 | ); 208 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 209 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 210 | GCC_WARN_UNDECLARED_SELECTOR = YES; 211 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 212 | GCC_WARN_UNUSED_FUNCTION = YES; 213 | GCC_WARN_UNUSED_VARIABLE = YES; 214 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 215 | MTL_ENABLE_DEBUG_INFO = YES; 216 | ONLY_ACTIVE_ARCH = YES; 217 | SDKROOT = iphoneos; 218 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 219 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 220 | }; 221 | name = Debug; 222 | }; 223 | 839992672029114B00C76A1E /* Release */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | ALWAYS_SEARCH_USER_PATHS = NO; 227 | CLANG_ANALYZER_NONNULL = YES; 228 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 230 | CLANG_CXX_LIBRARY = "libc++"; 231 | CLANG_ENABLE_MODULES = YES; 232 | CLANG_ENABLE_OBJC_ARC = YES; 233 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_COMMA = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 238 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 239 | CLANG_WARN_EMPTY_BODY = YES; 240 | CLANG_WARN_ENUM_CONVERSION = YES; 241 | CLANG_WARN_INFINITE_RECURSION = YES; 242 | CLANG_WARN_INT_CONVERSION = YES; 243 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 244 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 245 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 246 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 247 | CLANG_WARN_STRICT_PROTOTYPES = YES; 248 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 249 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 250 | CLANG_WARN_UNREACHABLE_CODE = YES; 251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 252 | CODE_SIGN_IDENTITY = "iPhone Developer"; 253 | COPY_PHASE_STRIP = NO; 254 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 255 | ENABLE_NS_ASSERTIONS = NO; 256 | ENABLE_STRICT_OBJC_MSGSEND = YES; 257 | GCC_C_LANGUAGE_STANDARD = gnu11; 258 | GCC_NO_COMMON_BLOCKS = YES; 259 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 260 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 261 | GCC_WARN_UNDECLARED_SELECTOR = YES; 262 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 263 | GCC_WARN_UNUSED_FUNCTION = YES; 264 | GCC_WARN_UNUSED_VARIABLE = YES; 265 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 266 | MTL_ENABLE_DEBUG_INFO = NO; 267 | SDKROOT = iphoneos; 268 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 269 | VALIDATE_PRODUCT = YES; 270 | }; 271 | name = Release; 272 | }; 273 | 839992692029114B00C76A1E /* Debug */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 277 | CODE_SIGN_STYLE = Automatic; 278 | DEVELOPMENT_TEAM = 3K82E7YE87; 279 | INFOPLIST_FILE = ObjectPool/Info.plist; 280 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 281 | PRODUCT_BUNDLE_IDENTIFIER = udacity.ObjectPool; 282 | PRODUCT_NAME = "$(TARGET_NAME)"; 283 | SWIFT_VERSION = 4.0; 284 | TARGETED_DEVICE_FAMILY = "1,2"; 285 | }; 286 | name = Debug; 287 | }; 288 | 8399926A2029114B00C76A1E /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 292 | CODE_SIGN_STYLE = Automatic; 293 | DEVELOPMENT_TEAM = 3K82E7YE87; 294 | INFOPLIST_FILE = ObjectPool/Info.plist; 295 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 296 | PRODUCT_BUNDLE_IDENTIFIER = udacity.ObjectPool; 297 | PRODUCT_NAME = "$(TARGET_NAME)"; 298 | SWIFT_VERSION = 4.0; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | 839992512029114B00C76A1E /* Build configuration list for PBXProject "ObjectPool" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | 839992662029114B00C76A1E /* Debug */, 310 | 839992672029114B00C76A1E /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | 839992682029114B00C76A1E /* Build configuration list for PBXNativeTarget "ObjectPool" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | 839992692029114B00C76A1E /* Debug */, 319 | 8399926A2029114B00C76A1E /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = 8399924E2029114B00C76A1E /* Project object */; 327 | } 328 | --------------------------------------------------------------------------------