├── .DS_Store ├── .gitattributes ├── AnimationDemo ├── AnimationDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── AnimationDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── CarAssets.xcassets ├── Contents.json ├── chevrolet_volt.imageset │ ├── Contents.json │ └── chevrolet_volt.jpg ├── nissan_leaf.imageset │ ├── Contents.json │ └── nissan_leaf.jpg ├── tesla_model_3.imageset │ ├── Contents.json │ └── tesla_model_3.jpg ├── tesla_model_s.imageset │ ├── Contents.json │ └── tesla_model_s.jpg └── toyota_prius.imageset │ ├── Contents.json │ └── toyota_prius.jpg ├── CarData └── carData.json ├── ContextMenuDemo ├── ContextMenuDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── ContextMenuDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── DrawDemo ├── DrawDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── DrawDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── GestureDemo ├── GestureDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── GestureDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── HostingControllerDemo ├── HostingControllerDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── HostingControllerDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ └── ViewController.swift └── SwiftUIView.swift ├── LearnSwift.playground ├── Pages │ ├── Live View Example.xcplaygroundpage │ │ ├── Contents.swift │ │ └── timeline.xctimeline │ ├── UIKit Examples.xcplaygroundpage │ │ ├── Contents.swift │ │ ├── Resources │ │ │ └── waterfall.png │ │ └── timeline.xctimeline │ └── Untitled Page.xcplaygroundpage │ │ ├── Contents.swift │ │ └── timeline.xctimeline ├── contents.xcplayground └── playground.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ └── neilsmyth.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── ListNavDemo ├── ListNavDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── ListNavDemo │ ├── AddNewCar.swift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── Car.swift │ ├── CarAssets.xcassets │ ├── Contents.json │ ├── chevrolet_volt.imageset │ │ ├── Contents.json │ │ └── chevrolet_volt.jpg │ ├── nissan_leaf.imageset │ │ ├── Contents.json │ │ └── nissan_leaf.jpg │ ├── tesla_model_3.imageset │ │ ├── Contents.json │ │ └── tesla_model_3.jpg │ ├── tesla_model_s.imageset │ │ ├── Contents.json │ │ └── tesla_model_s.jpg │ └── toyota_prius.imageset │ │ ├── Contents.json │ │ └── toyota_prius.jpg │ ├── CarData.swift │ ├── CarDetail.swift │ ├── CarStore.swift │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── SceneDelegate.swift │ └── carData.json ├── ObservableDemo ├── ObservableDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── ObservableDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── SceneDelegate.swift │ ├── SecondView.swift │ └── TimerData.swift ├── README.md ├── SwiftUIDemo ├── SwiftUIDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── SwiftUIDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── TabViewDemo ├── TabViewDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── TabViewDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── UIViewDemo ├── MyScrollView.swift ├── UIViewDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── UIViewDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── ViewControllerDemo ├── MyImagePicker.swift ├── ViewControllerDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── neilsmyth.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── neilsmyth.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── ViewControllerDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift └── playground_images ├── .DS_Store └── waterfall.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/AnimationDemo/AnimationDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AnimationDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // AnimationDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/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 | } -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/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 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // AnimationDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | @State private var isButtonVisible: Bool = true 14 | 15 | var body: some View { 16 | VStack { 17 | Toggle(isOn:$isButtonVisible.animation( 18 | .linear(duration: 2))) { 19 | Text("Show/Hide Button") 20 | } 21 | .padding() 22 | 23 | if isButtonVisible { 24 | Button(action: {}) { 25 | Text("Example Button") 26 | 27 | } 28 | .font(.largeTitle) 29 | .transition(.asymmetric(insertion: .scale, removal: .slide)) 30 | } 31 | } 32 | 33 | } 34 | } 35 | 36 | extension AnyTransition { 37 | static var fadeAndMove: AnyTransition { 38 | AnyTransition.opacity.combined(with: .move(edge: .top)) 39 | } 40 | } 41 | 42 | struct ContentView_Previews: PreviewProvider { 43 | static var previews: some View { 44 | ContentView() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AnimationDemo/AnimationDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // AnimationDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /CarAssets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /CarAssets.xcassets/chevrolet_volt.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "chevrolet_volt.jpg", 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 | } -------------------------------------------------------------------------------- /CarAssets.xcassets/chevrolet_volt.imageset/chevrolet_volt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/CarAssets.xcassets/chevrolet_volt.imageset/chevrolet_volt.jpg -------------------------------------------------------------------------------- /CarAssets.xcassets/nissan_leaf.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "nissan_leaf.jpg", 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 | } -------------------------------------------------------------------------------- /CarAssets.xcassets/nissan_leaf.imageset/nissan_leaf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/CarAssets.xcassets/nissan_leaf.imageset/nissan_leaf.jpg -------------------------------------------------------------------------------- /CarAssets.xcassets/tesla_model_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tesla_model_3.jpg", 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 | } -------------------------------------------------------------------------------- /CarAssets.xcassets/tesla_model_3.imageset/tesla_model_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/CarAssets.xcassets/tesla_model_3.imageset/tesla_model_3.jpg -------------------------------------------------------------------------------- /CarAssets.xcassets/tesla_model_s.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tesla_model_s.jpg", 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 | } -------------------------------------------------------------------------------- /CarAssets.xcassets/tesla_model_s.imageset/tesla_model_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/CarAssets.xcassets/tesla_model_s.imageset/tesla_model_s.jpg -------------------------------------------------------------------------------- /CarAssets.xcassets/toyota_prius.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "toyota_prius.jpg", 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 | } -------------------------------------------------------------------------------- /CarAssets.xcassets/toyota_prius.imageset/toyota_prius.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/CarAssets.xcassets/toyota_prius.imageset/toyota_prius.jpg -------------------------------------------------------------------------------- /CarData/carData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "aa32jj887hhg55", 4 | "name": "Tesla Model 3", 5 | "description": "Luxury 4-door all-electic car. Range of 310 miles. 0-60mph in 3.2 seconds", 6 | "isHybrid": false, 7 | "imageName": "tesla_model_3" 8 | }, 9 | { 10 | "id": "bb32jj887hhg77", 11 | "name": "Tesla Model S", 12 | "description": "5-door lift-back electric car. Performance model has a three-phase, four-pole AC induction 416 hp (310 kW) and 443 ft⋅lb (601 N⋅m) rear-mounted electric motor", 13 | "isHybrid": false, 14 | "imageName": "tesla_model_s" 15 | }, 16 | { 17 | "id": "cc32jj887hhg66", 18 | "name": "Toyota Prius", 19 | "description": "5-door liftback full hybrid electric automobile developed by Toyota.", 20 | "isHybrid": true, 21 | "imageName": "toyota_prius" 22 | }, 23 | { 24 | "id": "dd32jj887hhg88", 25 | "name": "Nissan Leaf", 26 | "description": "A compact five-door hatchback all-electric car manufactured by Nissan", 27 | "isHybrid": false, 28 | "imageName": "nissan_leaf" 29 | }, 30 | { 31 | "id": "ee32jj887hhg99", 32 | "name": "Chevrolet Volt", 33 | "description": "5-door hatchback plug-in hybrid car manufactured by General Motors.", 34 | "isHybrid": true, 35 | "imageName": "chevrolet_volt" 36 | } 37 | 38 | ] 39 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ContextMenuDemo/ContextMenuDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ContextMenuDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ContextMenuDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/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 | } -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/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 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ContextMenuDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | @State private var foregroundColor: Color = Color.black 14 | @State private var backgroundColor: Color = Color.white 15 | 16 | var body: some View { 17 | Text("Hello World") 18 | .font(.largeTitle) 19 | .padding() 20 | .foregroundColor(foregroundColor) 21 | .background(backgroundColor) 22 | .contextMenu { 23 | Button(action: { 24 | self.foregroundColor = .black 25 | self.backgroundColor = .white 26 | }) { 27 | Text("Normal Colors") 28 | .font(.caption) 29 | Image(systemName: "paintbrush") 30 | } 31 | 32 | Button(action: { 33 | self.foregroundColor = .white 34 | self.backgroundColor = .black 35 | }) { 36 | Text("Inverted Colors") 37 | Image(systemName: "paintbrush.fill") 38 | } 39 | } 40 | } 41 | } 42 | 43 | struct ContentView_Previews: PreviewProvider { 44 | static var previews: some View { 45 | ContentView() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ContextMenuDemo/ContextMenuDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // ContextMenuDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 88F3D77E23576A41003F0E58 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F3D77D23576A41003F0E58 /* AppDelegate.swift */; }; 11 | 88F3D78023576A41003F0E58 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F3D77F23576A41003F0E58 /* SceneDelegate.swift */; }; 12 | 88F3D78223576A41003F0E58 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F3D78123576A41003F0E58 /* ContentView.swift */; }; 13 | 88F3D78423576A45003F0E58 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88F3D78323576A45003F0E58 /* Assets.xcassets */; }; 14 | 88F3D78723576A45003F0E58 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88F3D78623576A45003F0E58 /* Preview Assets.xcassets */; }; 15 | 88F3D78A23576A45003F0E58 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F3D78823576A45003F0E58 /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 88F3D77A23576A41003F0E58 /* DrawDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DrawDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 88F3D77D23576A41003F0E58 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 21 | 88F3D77F23576A41003F0E58 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 22 | 88F3D78123576A41003F0E58 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 23 | 88F3D78323576A45003F0E58 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 24 | 88F3D78623576A45003F0E58 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 25 | 88F3D78923576A45003F0E58 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 26 | 88F3D78B23576A45003F0E58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 88F3D77723576A41003F0E58 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 88F3D77123576A41003F0E58 = { 41 | isa = PBXGroup; 42 | children = ( 43 | 88F3D77C23576A41003F0E58 /* DrawDemo */, 44 | 88F3D77B23576A41003F0E58 /* Products */, 45 | ); 46 | sourceTree = ""; 47 | }; 48 | 88F3D77B23576A41003F0E58 /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 88F3D77A23576A41003F0E58 /* DrawDemo.app */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | 88F3D77C23576A41003F0E58 /* DrawDemo */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 88F3D77D23576A41003F0E58 /* AppDelegate.swift */, 60 | 88F3D77F23576A41003F0E58 /* SceneDelegate.swift */, 61 | 88F3D78123576A41003F0E58 /* ContentView.swift */, 62 | 88F3D78323576A45003F0E58 /* Assets.xcassets */, 63 | 88F3D78823576A45003F0E58 /* LaunchScreen.storyboard */, 64 | 88F3D78B23576A45003F0E58 /* Info.plist */, 65 | 88F3D78523576A45003F0E58 /* Preview Content */, 66 | ); 67 | path = DrawDemo; 68 | sourceTree = ""; 69 | }; 70 | 88F3D78523576A45003F0E58 /* Preview Content */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 88F3D78623576A45003F0E58 /* Preview Assets.xcassets */, 74 | ); 75 | path = "Preview Content"; 76 | sourceTree = ""; 77 | }; 78 | /* End PBXGroup section */ 79 | 80 | /* Begin PBXNativeTarget section */ 81 | 88F3D77923576A41003F0E58 /* DrawDemo */ = { 82 | isa = PBXNativeTarget; 83 | buildConfigurationList = 88F3D78E23576A45003F0E58 /* Build configuration list for PBXNativeTarget "DrawDemo" */; 84 | buildPhases = ( 85 | 88F3D77623576A41003F0E58 /* Sources */, 86 | 88F3D77723576A41003F0E58 /* Frameworks */, 87 | 88F3D77823576A41003F0E58 /* Resources */, 88 | ); 89 | buildRules = ( 90 | ); 91 | dependencies = ( 92 | ); 93 | name = DrawDemo; 94 | productName = DrawDemo; 95 | productReference = 88F3D77A23576A41003F0E58 /* DrawDemo.app */; 96 | productType = "com.apple.product-type.application"; 97 | }; 98 | /* End PBXNativeTarget section */ 99 | 100 | /* Begin PBXProject section */ 101 | 88F3D77223576A41003F0E58 /* Project object */ = { 102 | isa = PBXProject; 103 | attributes = { 104 | LastSwiftUpdateCheck = 1100; 105 | LastUpgradeCheck = 1100; 106 | ORGANIZATIONNAME = eBookFrenzy; 107 | TargetAttributes = { 108 | 88F3D77923576A41003F0E58 = { 109 | CreatedOnToolsVersion = 11.0; 110 | }; 111 | }; 112 | }; 113 | buildConfigurationList = 88F3D77523576A41003F0E58 /* Build configuration list for PBXProject "DrawDemo" */; 114 | compatibilityVersion = "Xcode 9.3"; 115 | developmentRegion = en; 116 | hasScannedForEncodings = 0; 117 | knownRegions = ( 118 | en, 119 | Base, 120 | ); 121 | mainGroup = 88F3D77123576A41003F0E58; 122 | productRefGroup = 88F3D77B23576A41003F0E58 /* Products */; 123 | projectDirPath = ""; 124 | projectRoot = ""; 125 | targets = ( 126 | 88F3D77923576A41003F0E58 /* DrawDemo */, 127 | ); 128 | }; 129 | /* End PBXProject section */ 130 | 131 | /* Begin PBXResourcesBuildPhase section */ 132 | 88F3D77823576A41003F0E58 /* Resources */ = { 133 | isa = PBXResourcesBuildPhase; 134 | buildActionMask = 2147483647; 135 | files = ( 136 | 88F3D78A23576A45003F0E58 /* LaunchScreen.storyboard in Resources */, 137 | 88F3D78723576A45003F0E58 /* Preview Assets.xcassets in Resources */, 138 | 88F3D78423576A45003F0E58 /* Assets.xcassets in Resources */, 139 | ); 140 | runOnlyForDeploymentPostprocessing = 0; 141 | }; 142 | /* End PBXResourcesBuildPhase section */ 143 | 144 | /* Begin PBXSourcesBuildPhase section */ 145 | 88F3D77623576A41003F0E58 /* Sources */ = { 146 | isa = PBXSourcesBuildPhase; 147 | buildActionMask = 2147483647; 148 | files = ( 149 | 88F3D77E23576A41003F0E58 /* AppDelegate.swift in Sources */, 150 | 88F3D78023576A41003F0E58 /* SceneDelegate.swift in Sources */, 151 | 88F3D78223576A41003F0E58 /* ContentView.swift in Sources */, 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | /* End PBXSourcesBuildPhase section */ 156 | 157 | /* Begin PBXVariantGroup section */ 158 | 88F3D78823576A45003F0E58 /* LaunchScreen.storyboard */ = { 159 | isa = PBXVariantGroup; 160 | children = ( 161 | 88F3D78923576A45003F0E58 /* Base */, 162 | ); 163 | name = LaunchScreen.storyboard; 164 | sourceTree = ""; 165 | }; 166 | /* End PBXVariantGroup section */ 167 | 168 | /* Begin XCBuildConfiguration section */ 169 | 88F3D78C23576A45003F0E58 /* Debug */ = { 170 | isa = XCBuildConfiguration; 171 | buildSettings = { 172 | ALWAYS_SEARCH_USER_PATHS = NO; 173 | CLANG_ANALYZER_NONNULL = YES; 174 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 175 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 176 | CLANG_CXX_LIBRARY = "libc++"; 177 | CLANG_ENABLE_MODULES = YES; 178 | CLANG_ENABLE_OBJC_ARC = YES; 179 | CLANG_ENABLE_OBJC_WEAK = YES; 180 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 181 | CLANG_WARN_BOOL_CONVERSION = YES; 182 | CLANG_WARN_COMMA = YES; 183 | CLANG_WARN_CONSTANT_CONVERSION = YES; 184 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 185 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 186 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 187 | CLANG_WARN_EMPTY_BODY = YES; 188 | CLANG_WARN_ENUM_CONVERSION = YES; 189 | CLANG_WARN_INFINITE_RECURSION = YES; 190 | CLANG_WARN_INT_CONVERSION = YES; 191 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 192 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 193 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 194 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 195 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 196 | CLANG_WARN_STRICT_PROTOTYPES = YES; 197 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 198 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 199 | CLANG_WARN_UNREACHABLE_CODE = YES; 200 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 201 | COPY_PHASE_STRIP = NO; 202 | DEBUG_INFORMATION_FORMAT = dwarf; 203 | ENABLE_STRICT_OBJC_MSGSEND = YES; 204 | ENABLE_TESTABILITY = YES; 205 | GCC_C_LANGUAGE_STANDARD = gnu11; 206 | GCC_DYNAMIC_NO_PIC = NO; 207 | GCC_NO_COMMON_BLOCKS = YES; 208 | GCC_OPTIMIZATION_LEVEL = 0; 209 | GCC_PREPROCESSOR_DEFINITIONS = ( 210 | "DEBUG=1", 211 | "$(inherited)", 212 | ); 213 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 214 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 215 | GCC_WARN_UNDECLARED_SELECTOR = YES; 216 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 217 | GCC_WARN_UNUSED_FUNCTION = YES; 218 | GCC_WARN_UNUSED_VARIABLE = YES; 219 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 220 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 221 | MTL_FAST_MATH = YES; 222 | ONLY_ACTIVE_ARCH = YES; 223 | SDKROOT = iphoneos; 224 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 225 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 226 | }; 227 | name = Debug; 228 | }; 229 | 88F3D78D23576A45003F0E58 /* Release */ = { 230 | isa = XCBuildConfiguration; 231 | buildSettings = { 232 | ALWAYS_SEARCH_USER_PATHS = NO; 233 | CLANG_ANALYZER_NONNULL = YES; 234 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 235 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 236 | CLANG_CXX_LIBRARY = "libc++"; 237 | CLANG_ENABLE_MODULES = YES; 238 | CLANG_ENABLE_OBJC_ARC = YES; 239 | CLANG_ENABLE_OBJC_WEAK = YES; 240 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 241 | CLANG_WARN_BOOL_CONVERSION = YES; 242 | CLANG_WARN_COMMA = YES; 243 | CLANG_WARN_CONSTANT_CONVERSION = YES; 244 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 245 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 246 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 247 | CLANG_WARN_EMPTY_BODY = YES; 248 | CLANG_WARN_ENUM_CONVERSION = YES; 249 | CLANG_WARN_INFINITE_RECURSION = YES; 250 | CLANG_WARN_INT_CONVERSION = YES; 251 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 252 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 253 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 255 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 256 | CLANG_WARN_STRICT_PROTOTYPES = YES; 257 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 258 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 259 | CLANG_WARN_UNREACHABLE_CODE = YES; 260 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 261 | COPY_PHASE_STRIP = NO; 262 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 263 | ENABLE_NS_ASSERTIONS = NO; 264 | ENABLE_STRICT_OBJC_MSGSEND = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu11; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 274 | MTL_ENABLE_DEBUG_INFO = NO; 275 | MTL_FAST_MATH = YES; 276 | SDKROOT = iphoneos; 277 | SWIFT_COMPILATION_MODE = wholemodule; 278 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 279 | VALIDATE_PRODUCT = YES; 280 | }; 281 | name = Release; 282 | }; 283 | 88F3D78F23576A45003F0E58 /* Debug */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 287 | CODE_SIGN_STYLE = Automatic; 288 | DEVELOPMENT_ASSET_PATHS = "\"DrawDemo/Preview Content\""; 289 | DEVELOPMENT_TEAM = 2UTH99GSB7; 290 | ENABLE_PREVIEWS = YES; 291 | INFOPLIST_FILE = DrawDemo/Info.plist; 292 | LD_RUNPATH_SEARCH_PATHS = ( 293 | "$(inherited)", 294 | "@executable_path/Frameworks", 295 | ); 296 | PRODUCT_BUNDLE_IDENTIFIER = com.ebookfrenzy.DrawDemo; 297 | PRODUCT_NAME = "$(TARGET_NAME)"; 298 | SWIFT_VERSION = 5.0; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Debug; 302 | }; 303 | 88F3D79023576A45003F0E58 /* Release */ = { 304 | isa = XCBuildConfiguration; 305 | buildSettings = { 306 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 307 | CODE_SIGN_STYLE = Automatic; 308 | DEVELOPMENT_ASSET_PATHS = "\"DrawDemo/Preview Content\""; 309 | DEVELOPMENT_TEAM = 2UTH99GSB7; 310 | ENABLE_PREVIEWS = YES; 311 | INFOPLIST_FILE = DrawDemo/Info.plist; 312 | LD_RUNPATH_SEARCH_PATHS = ( 313 | "$(inherited)", 314 | "@executable_path/Frameworks", 315 | ); 316 | PRODUCT_BUNDLE_IDENTIFIER = com.ebookfrenzy.DrawDemo; 317 | PRODUCT_NAME = "$(TARGET_NAME)"; 318 | SWIFT_VERSION = 5.0; 319 | TARGETED_DEVICE_FAMILY = "1,2"; 320 | }; 321 | name = Release; 322 | }; 323 | /* End XCBuildConfiguration section */ 324 | 325 | /* Begin XCConfigurationList section */ 326 | 88F3D77523576A41003F0E58 /* Build configuration list for PBXProject "DrawDemo" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | 88F3D78C23576A45003F0E58 /* Debug */, 330 | 88F3D78D23576A45003F0E58 /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | 88F3D78E23576A45003F0E58 /* Build configuration list for PBXNativeTarget "DrawDemo" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | 88F3D78F23576A45003F0E58 /* Debug */, 339 | 88F3D79023576A45003F0E58 /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | /* End XCConfigurationList section */ 345 | }; 346 | rootObject = 88F3D77223576A41003F0E58 /* Project object */; 347 | } 348 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/DrawDemo/DrawDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /DrawDemo/DrawDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DrawDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DrawDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/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 | } -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/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 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // DrawDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | let colors = Gradient(colors: [Color.red, Color.yellow, 14 | Color.green, Color.blue, Color.purple]) 15 | 16 | var body: some View { 17 | 18 | MyShape() 19 | .fill(RadialGradient(gradient: colors, 20 | center: .center, 21 | startRadius: CGFloat(0), 22 | endRadius: CGFloat(300))) 23 | .background(LinearGradient(gradient: Gradient(colors: 24 | [Color.black, Color.white]), 25 | startPoint: .topLeading, 26 | endPoint: .bottomTrailing)) 27 | .frame(width: 360, height: 350) 28 | } 29 | } 30 | 31 | 32 | struct MyShape: Shape { 33 | func path(in rect: CGRect) -> Path { 34 | var path = Path() 35 | 36 | path.move(to: CGPoint(x: rect.minX, y: rect.minY)) 37 | path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY), 38 | control: CGPoint(x: rect.midX, y: rect.midY)) 39 | path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) 40 | path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) 41 | path.closeSubpath() 42 | return path 43 | } 44 | } 45 | 46 | struct ContentView_Previews: PreviewProvider { 47 | static var previews: some View { 48 | ContentView() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /DrawDemo/DrawDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // DrawDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/GestureDemo/GestureDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /GestureDemo/GestureDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | GestureDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // GestureDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/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 | } -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/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 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // GestureDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | @GestureState private var offset: CGSize = .zero 14 | @State private var dragEnabled: Bool = false 15 | 16 | var body: some View { 17 | 18 | let longPressBeforeDrag = LongPressGesture(minimumDuration: 2.0) 19 | .onEnded( { _ in 20 | self.dragEnabled = true 21 | }) 22 | .sequenced(before: DragGesture()) 23 | .updating($offset) { value, state, transaction in 24 | 25 | switch value { 26 | 27 | case .first(true): 28 | print("Long press in progress") 29 | 30 | case .second(true, let drag): 31 | state = drag?.translation ?? .zero 32 | 33 | default: break 34 | } 35 | } 36 | .onEnded { value in 37 | self.dragEnabled = false 38 | } 39 | 40 | 41 | return Image(systemName: "hand.point.right.fill") 42 | .foregroundColor(dragEnabled ? Color.green : Color.blue) 43 | .font(.largeTitle) 44 | .offset(offset) 45 | .gesture(longPressBeforeDrag) 46 | } 47 | } 48 | 49 | 50 | 51 | struct ContentView_Previews: PreviewProvider { 52 | static var previews: some View { 53 | ContentView() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /GestureDemo/GestureDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // GestureDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/HostingControllerDemo/HostingControllerDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HostingControllerDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // HostingControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/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 | } -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/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 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/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 | 26 | 33 | 34 | 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 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // HostingControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /HostingControllerDemo/HostingControllerDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // HostingControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class ViewController: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | let swiftUIController = UIHostingController(rootView: SwiftUIView(text: "Integration Three")) 18 | 19 | addChild(swiftUIController) 20 | swiftUIController.view.translatesAutoresizingMaskIntoConstraints = false 21 | 22 | view.addSubview(swiftUIController.view) 23 | 24 | swiftUIController.view.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 25 | swiftUIController.view.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 26 | 27 | swiftUIController.didMove(toParent: self) 28 | 29 | } 30 | 31 | @IBSegueAction func showSwiftUIView(_ coder: NSCoder) -> UIViewController? { 32 | return UIHostingController(coder: coder, 33 | rootView: SwiftUIView(text: "Integration One")) 34 | } 35 | 36 | @IBSegueAction func embedSwiftUIView(_ coder: NSCoder) -> UIViewController? { 37 | return UIHostingController(coder: coder, rootView: SwiftUIView(text: "Integration Two")) 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /HostingControllerDemo/SwiftUIView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIView.swift 3 | // HostingControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SwiftUIView: View { 12 | 13 | var text: String 14 | 15 | var body: some View { 16 | VStack { 17 | Text(text) 18 | HStack { 19 | Image(systemName: "smiley") 20 | Text("This is a SwiftUI View") 21 | } 22 | } 23 | .font(.largeTitle) 24 | } 25 | } 26 | 27 | struct SwiftUIView_Previews: PreviewProvider { 28 | static var previews: some View { 29 | SwiftUIView(text: "Sample Text") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LearnSwift.playground/Pages/Live View Example.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import UIKit 4 | import PlaygroundSupport 5 | 6 | let container = UIView(frame: CGRect(x: 0,y: 0,width: 200,height: 200)) 7 | 8 | PlaygroundPage.current.liveView = container 9 | 10 | container.backgroundColor = UIColor.white 11 | let square = UIView(frame: CGRect(x: 50,y: 50,width: 100,height: 100)) 12 | square.backgroundColor = UIColor.red 13 | 14 | container.addSubview(square) 15 | 16 | UIView.animate(withDuration: 5.0, animations: { 17 | square.backgroundColor = UIColor.blue 18 | let rotation = CGAffineTransform(rotationAngle: 3.14) 19 | square.transform = rotation 20 | }) 21 | 22 | 23 | //: [Next](@next) 24 | -------------------------------------------------------------------------------- /LearnSwift.playground/Pages/Live View Example.xcplaygroundpage/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LearnSwift.playground/Pages/UIKit Examples.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import UIKit 4 | 5 | let myLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 50)) 6 | 7 | myLabel.backgroundColor = UIColor.red 8 | myLabel.text = "Hello Swift" 9 | myLabel.textAlignment = .center 10 | myLabel.font = UIFont(name: "Georgia", size: 24) 11 | myLabel 12 | 13 | let image = UIImage(named: "waterfall") 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | //: [Next](@next) 23 | -------------------------------------------------------------------------------- /LearnSwift.playground/Pages/UIKit Examples.xcplaygroundpage/Resources/waterfall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/LearnSwift.playground/Pages/UIKit Examples.xcplaygroundpage/Resources/waterfall.png -------------------------------------------------------------------------------- /LearnSwift.playground/Pages/UIKit Examples.xcplaygroundpage/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /LearnSwift.playground/Pages/Untitled Page.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | var str = "Hello , playground" 4 | 5 | print("Welcome to Swift") 6 | 7 | /*: 8 | # Welcome to Playgrounds 9 | This is your *first* playground which is intended to demonstrate: 10 | * The use of **Quick Look** 11 | * Placing results **in-line** with the code 12 | */ 13 | 14 | var x = 10 15 | 16 | for index in 1...20 { 17 | let y = index * x 18 | x -= 1 19 | print(y) 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /LearnSwift.playground/Pages/Untitled Page.xcplaygroundpage/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /LearnSwift.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LearnSwift.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LearnSwift.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LearnSwift.playground/playground.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/LearnSwift.playground/playground.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ListNavDemo/ListNavDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ListNavDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/AddNewCar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddNewCar.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct AddNewCar: View { 12 | 13 | @ObservedObject var carStore : CarStore 14 | 15 | @State var isHybrid = false 16 | @State var name: String = "" 17 | @State var description: String = "" 18 | 19 | var body: some View { 20 | 21 | Form { 22 | Section(header: Text("Car Details")) { 23 | Image(systemName: "car.fill") 24 | .resizable() 25 | .aspectRatio(contentMode: .fit) 26 | .padding() 27 | 28 | DataInput(title: "Model", userInput: $name) 29 | DataInput(title: "Description", userInput: $description) 30 | 31 | Toggle(isOn: $isHybrid) { 32 | Text("Hybrid").font(.headline) 33 | }.padding() 34 | } 35 | 36 | Button(action: addNewCar) { 37 | Text("Add Car") 38 | } 39 | } 40 | 41 | } 42 | 43 | func addNewCar() { 44 | let newCar = Car(id: UUID().uuidString, 45 | name: name, description: description, 46 | isHybrid: isHybrid, imageName: "tesla_model_3" ) 47 | 48 | carStore.cars.append(newCar) 49 | } 50 | } 51 | 52 | 53 | struct DataInput: View { 54 | 55 | var title: String 56 | @Binding var userInput: String 57 | 58 | var body: some View { 59 | VStack(alignment: HorizontalAlignment.leading) { 60 | Text(title) 61 | .font(.headline) 62 | TextField("Enter \(title)", text: $userInput) 63 | .textFieldStyle(RoundedBorderTextFieldStyle()) 64 | } 65 | .padding() 66 | } 67 | } 68 | 69 | struct AddNewCar_Previews: PreviewProvider { 70 | static var previews: some View { 71 | AddNewCar(carStore: CarStore(cars: carData)) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/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 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/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 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/Car.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Car.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Car : Codable, Identifiable { 12 | var id: String 13 | var name: String 14 | 15 | var description: String 16 | var isHybrid: Bool 17 | 18 | var imageName: String 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/chevrolet_volt.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "chevrolet_volt.jpg", 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 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/chevrolet_volt.imageset/chevrolet_volt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ListNavDemo/ListNavDemo/CarAssets.xcassets/chevrolet_volt.imageset/chevrolet_volt.jpg -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/nissan_leaf.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "nissan_leaf.jpg", 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 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/nissan_leaf.imageset/nissan_leaf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ListNavDemo/ListNavDemo/CarAssets.xcassets/nissan_leaf.imageset/nissan_leaf.jpg -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/tesla_model_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tesla_model_3.jpg", 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 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/tesla_model_3.imageset/tesla_model_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ListNavDemo/ListNavDemo/CarAssets.xcassets/tesla_model_3.imageset/tesla_model_3.jpg -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/tesla_model_s.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tesla_model_s.jpg", 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 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/tesla_model_s.imageset/tesla_model_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ListNavDemo/ListNavDemo/CarAssets.xcassets/tesla_model_s.imageset/tesla_model_s.jpg -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/toyota_prius.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "toyota_prius.jpg", 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 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarAssets.xcassets/toyota_prius.imageset/toyota_prius.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ListNavDemo/ListNavDemo/CarAssets.xcassets/toyota_prius.imageset/toyota_prius.jpg -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CarData.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | var carData: [Car] = loadJson("carData.json") 13 | 14 | func loadJson(_ filename: String) -> T { 15 | let data: Data 16 | 17 | guard let file = Bundle.main.url(forResource: filename, 18 | withExtension: nil) 19 | else { 20 | fatalError("\(filename) not found.") 21 | } 22 | 23 | do { 24 | data = try Data(contentsOf: file) 25 | } catch { 26 | fatalError("Could not load \(filename): (error)") 27 | } 28 | 29 | do { 30 | return try JSONDecoder().decode(T.self, from: data) 31 | } catch { 32 | fatalError("Unable to parse \(filename): (error)") 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarDetail.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CarDetail.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CarDetail: View { 12 | 13 | let selectedCar: Car 14 | 15 | var body: some View { 16 | Form { 17 | Section(header: Text("Car Details")) { 18 | Image(selectedCar.imageName) 19 | .resizable() 20 | .cornerRadius(12.0) 21 | .aspectRatio(contentMode: .fit) 22 | .padding() 23 | 24 | Text(selectedCar.name) 25 | .font(.headline) 26 | 27 | Text(selectedCar.description) 28 | .font(.body) 29 | 30 | HStack { 31 | Text("Hybrid").font(.headline) 32 | Spacer() 33 | Image(systemName: selectedCar.isHybrid ? 34 | "checkmark.circle" : "xmark.circle" ) 35 | } 36 | 37 | 38 | } 39 | } 40 | 41 | } 42 | } 43 | 44 | struct CarDetail_Previews: PreviewProvider { 45 | static var previews: some View { 46 | CarDetail(selectedCar: carData[0]) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/CarStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CarStore.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | 12 | class CarStore : ObservableObject { 13 | 14 | @Published var cars: [Car] 15 | 16 | init (cars: [Car] = []) { 17 | self.cars = cars 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | @ObservedObject var carStore : CarStore = CarStore(cars: carData) 14 | 15 | var body: some View { 16 | 17 | NavigationView { 18 | List { 19 | ForEach(carStore.cars) { car in 20 | ListCell(car: car) 21 | } 22 | .onDelete(perform: deleteItems) 23 | .onMove(perform: moveItems) 24 | 25 | } 26 | .navigationBarTitle(Text("EV Cars")) 27 | .navigationBarItems(leading: NavigationLink(destination: 28 | AddNewCar(carStore: self.carStore)) { 29 | Text("Add") 30 | .foregroundColor(.blue) 31 | }, trailing: EditButton()) 32 | 33 | } 34 | } 35 | 36 | func deleteItems(at offets: IndexSet) { 37 | carStore.cars.remove(atOffsets: offets) 38 | print("Item moved") 39 | } 40 | 41 | func moveItems(from source: IndexSet, to destination: Int) { 42 | carStore.cars.move(fromOffsets: source, toOffset: destination) 43 | print("Item deleted") 44 | } 45 | 46 | } 47 | 48 | struct ContentView_Previews: PreviewProvider { 49 | static var previews: some View { 50 | ContentView() 51 | } 52 | } 53 | 54 | struct ListCell: View { 55 | 56 | var car: Car 57 | 58 | var body: some View { 59 | NavigationLink(destination: CarDetail(selectedCar: car)) { 60 | HStack { 61 | Image(car.imageName) 62 | .resizable() 63 | .aspectRatio(contentMode: .fit) 64 | .frame(width: 100, height: 60) 65 | Text(car.name) 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // ListNavDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /ListNavDemo/ListNavDemo/carData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "aa32jj887hhg55", 4 | "name": "Tesla Model 3", 5 | "description": "Luxury 4-door all-electic car. Range of 310 miles. 0-60mph in 3.2 seconds", 6 | "isHybrid": false, 7 | "imageName": "tesla_model_3" 8 | }, 9 | { 10 | "id": "bb32jj887hhg77", 11 | "name": "Tesla Model S", 12 | "description": "5-door lift-back electric car. Performance model has a three-phase, four-pole AC induction 416 hp (310 kW) and 443 ft⋅lb (601 N⋅m) rear-mounted electric motor", 13 | "isHybrid": false, 14 | "imageName": "tesla_model_s" 15 | }, 16 | { 17 | "id": "cc32jj887hhg66", 18 | "name": "Toyota Prius", 19 | "description": "5-door liftback full hybrid electric automobile developed by Toyota.", 20 | "isHybrid": true, 21 | "imageName": "toyota_prius" 22 | }, 23 | { 24 | "id": "dd32jj887hhg88", 25 | "name": "Nissan Leaf", 26 | "description": "A compact five-door hatchback all-electric car manufactured by Nissan", 27 | "isHybrid": false, 28 | "imageName": "nissan_leaf" 29 | }, 30 | { 31 | "id": "ee32jj887hhg99", 32 | "name": "Chevrolet Volt", 33 | "description": "5-door hatchback plug-in hybrid car manufactured by General Motors.", 34 | "isHybrid": true, 35 | "imageName": "chevrolet_volt" 36 | } 37 | 38 | ] 39 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ObservableDemo/ObservableDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ObservableDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ObservableDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/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 | } -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/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 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ObservableDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | @EnvironmentObject var timerData: TimerData 14 | 15 | var body: some View { 16 | NavigationView { 17 | VStack { 18 | Text("Timer count = \(timerData.timeCount)") 19 | 20 | .font(.largeTitle) 21 | .fontWeight(.bold) 22 | .padding() 23 | 24 | Button(action: resetCount) { 25 | Text("Reset Counter") 26 | } 27 | 28 | NavigationLink(destination: 29 | SecondView(timerData: timerData)) { 30 | Text("Next Screen") 31 | } 32 | .padding() 33 | 34 | } 35 | } 36 | } 37 | 38 | func resetCount() { 39 | timerData.resetCount() 40 | } 41 | 42 | } 43 | 44 | struct ContentView_Previews: PreviewProvider { 45 | static var previews: some View { 46 | ContentView().environmentObject(TimerData()) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // ObservableDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | let timerData = TimerData() 26 | 27 | // Use a UIHostingController as window root view controller. 28 | if let windowScene = scene as? UIWindowScene { 29 | let window = UIWindow(windowScene: windowScene) 30 | window.rootViewController = UIHostingController(rootView: contentView.environmentObject(timerData)) 31 | self.window = window 32 | window.makeKeyAndVisible() 33 | } 34 | } 35 | 36 | func sceneDidDisconnect(_ scene: UIScene) { 37 | // Called as the scene is being released by the system. 38 | // This occurs shortly after the scene enters the background, or when its session is discarded. 39 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 40 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 41 | } 42 | 43 | func sceneDidBecomeActive(_ scene: UIScene) { 44 | // Called when the scene has moved from an inactive state to an active state. 45 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 46 | } 47 | 48 | func sceneWillResignActive(_ scene: UIScene) { 49 | // Called when the scene will move from an active state to an inactive state. 50 | // This may occur due to temporary interruptions (ex. an incoming phone call). 51 | } 52 | 53 | func sceneWillEnterForeground(_ scene: UIScene) { 54 | // Called as the scene transitions from the background to the foreground. 55 | // Use this method to undo the changes made on entering the background. 56 | } 57 | 58 | func sceneDidEnterBackground(_ scene: UIScene) { 59 | // Called as the scene transitions from the foreground to the background. 60 | // Use this method to save data, release shared resources, and store enough scene-specific state information 61 | // to restore the scene back to its current state. 62 | } 63 | 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/SecondView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondView.swift 3 | // ObservableDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SecondView: View { 12 | 13 | @EnvironmentObject var timerData: TimerData 14 | 15 | var body: some View { 16 | VStack { 17 | Text("Second View") 18 | .font(.largeTitle) 19 | Text("Timer Count = \(timerData.timeCount)") 20 | .font(.headline) 21 | }.padding() 22 | 23 | } 24 | } 25 | 26 | struct SecondView_Previews: PreviewProvider { 27 | static var previews: some View { 28 | SecondView().environmentObject(TimerData()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ObservableDemo/ObservableDemo/TimerData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimerData.swift 3 | // ObservableDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Combine 11 | 12 | class TimerData : ObservableObject { 13 | 14 | @Published var timeCount = 0 15 | var timer : Timer? 16 | 17 | init() { 18 | timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerDidFire), userInfo: nil, repeats: true) 19 | } 20 | 21 | @objc func timerDidFire() { 22 | timeCount += 1 23 | } 24 | 25 | func resetCount() { 26 | timeCount = 0 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 핵심만 골라 배우는 Swift 기반의 iOS 프로그래밍 2 | 3 | ![핵심만 골라 배우는 Swift 기반의 iOS 프로그래밍](http://image.kyobobook.co.kr/images/book/xlarge/025/x9791190665025.jpg) 4 | 5 | **출판사** 제이펍 6 | **원서명** SwiftUI Essentials: iOS Edition(원서 ISBN: 9781951442057) 7 | **저자명** 닐 스미스 8 | **역자명** 황반석 9 | **출판일** 2019년 월 16일 10 | **페이지** 392쪽 11 | **시리즈** I♥Mobile 38(아이러브 모바일 시리즈 38)) 12 | **ISBN** 979-11-90665-02-5 (93000) 13 | 14 | [### 도서 소개 페이지 바로 가기 ###](https://jpub.tistory.com/1023) -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/SwiftUIDemo/SwiftUIDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftUIDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftUIDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/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 | } -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/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 | -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftUIDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | var colors: [Color] = [.black, .red, .green, .blue] 14 | var colornames = ["Black", "Red", "Green", "Blue"] 15 | 16 | @State private var colorIndex = 0 17 | @State private var rotation: Double = 0 18 | @State private var text: String = "Welcome to SwiftUI" 19 | 20 | var body: some View { 21 | VStack { 22 | Spacer() 23 | Text(text) 24 | .font(/*@START_MENU_TOKEN@*/.largeTitle/*@END_MENU_TOKEN@*/) 25 | .fontWeight(.heavy) 26 | .rotationEffect(.degrees(self.rotation)) 27 | .animation(.easeInOut(duration: 5)) 28 | .foregroundColor(self.colors[self.colorIndex]) 29 | Spacer() 30 | Divider() 31 | Slider(value: $rotation, in: 0 ... 360, step: 0.1) 32 | .padding() 33 | TextField("Enter text here", text: $text) 34 | .textFieldStyle(RoundedBorderTextFieldStyle()) 35 | .padding() 36 | Picker(selection: $colorIndex, label: Text("Color")) { 37 | ForEach(0 ..< colornames.count) { 38 | Text(self.colornames[$0]) 39 | .foregroundColor(self.colors[$0]) 40 | } 41 | } 42 | .padding() 43 | } 44 | } 45 | } 46 | 47 | struct ContentView_Previews: PreviewProvider { 48 | static var previews: some View { 49 | ContentView() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SwiftUIDemo/SwiftUIDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // SwiftUIDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/TabViewDemo/TabViewDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TabViewDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TabViewDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/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 | } -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/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 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // TabViewDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | @State private var selection = 1 14 | 15 | var body: some View { 16 | 17 | TabView(selection: $selection) { 18 | Text("First Content View") 19 | .tabItem { 20 | Image(systemName: "1.circle") 21 | Text("Screen One") 22 | }.tag(1) 23 | 24 | Text("Second Content View") 25 | .tabItem { 26 | Image(systemName: "2.circle") 27 | Text("Screen Two") 28 | }.tag(2) 29 | 30 | Text("Third Content View") 31 | .tabItem { 32 | Image(systemName: "3.circle") 33 | Text("Screen Three") 34 | }.tag(3) 35 | 36 | } 37 | .font(.largeTitle) 38 | } 39 | } 40 | 41 | struct ContentView_Previews: PreviewProvider { 42 | static var previews: some View { 43 | ContentView() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TabViewDemo/TabViewDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // TabViewDemo 4 | // 5 | // Created by Neil Smyth on 10/15/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /UIViewDemo/MyScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyScrollView.swift 3 | // UIViewDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct MyScrollView: UIViewRepresentable { 12 | 13 | var text: String 14 | 15 | func makeUIView(context: UIViewRepresentableContext) -> UIScrollView { 16 | let scrollView = UIScrollView() 17 | scrollView.delegate = context.coordinator 18 | 19 | scrollView.refreshControl = UIRefreshControl() 20 | scrollView.refreshControl?.addTarget(context.coordinator, action: 21 | #selector(Coordinator.handleRefresh), 22 | for: .valueChanged) 23 | 24 | let myLabel = UILabel(frame: 25 | CGRect(x: 0, y: 0, width: 300, height: 50)) 26 | myLabel.text = text 27 | scrollView.addSubview(myLabel) 28 | return scrollView 29 | } 30 | 31 | func updateUIView(_ uiView: UIScrollView, 32 | context: UIViewRepresentableContext) { 33 | 34 | } 35 | 36 | func makeCoordinator() -> Coordinator { 37 | Coordinator(self) 38 | } 39 | 40 | class Coordinator: NSObject, UIScrollViewDelegate { 41 | var control: MyScrollView 42 | 43 | init(_ control: MyScrollView) { 44 | self.control = control 45 | } 46 | 47 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 48 | print("View is Scrolling") 49 | } 50 | 51 | @objc func handleRefresh(sender: UIRefreshControl) { 52 | sender.endRefreshing() 53 | } 54 | } 55 | 56 | } 57 | 58 | struct MyScrollView_Previews: PreviewProvider { 59 | static var previews: some View { 60 | MyScrollView(text: "Hello World") 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/UIViewDemo/UIViewDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | UIViewDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UIViewDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/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 | } -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/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 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // UIViewDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | var body: some View { 13 | MyScrollView(text: "UIView in SwiftUI") 14 | } 15 | } 16 | 17 | struct ContentView_Previews: PreviewProvider { 18 | static var previews: some View { 19 | ContentView() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /UIViewDemo/UIViewDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // UIViewDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /ViewControllerDemo/MyImagePicker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyImagePicker.swift 3 | // ViewControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct MyImagePicker: UIViewControllerRepresentable { 12 | 13 | @Binding var imagePickerVisible: Bool 14 | @Binding var selectedImage: Image? 15 | 16 | func makeUIViewController(context: 17 | UIViewControllerRepresentableContext) -> 18 | UIImagePickerController { 19 | let picker = UIImagePickerController() 20 | picker.delegate = context.coordinator 21 | return picker 22 | } 23 | 24 | func updateUIViewController(_ uiViewController: 25 | UIImagePickerController, context: 26 | UIViewControllerRepresentableContext) { 27 | 28 | } 29 | 30 | func makeCoordinator() -> Coordinator { 31 | return Coordinator(imagePickerVisible: $imagePickerVisible, 32 | selectedImage: $selectedImage) 33 | } 34 | 35 | 36 | class Coordinator: NSObject, UINavigationControllerDelegate, 37 | UIImagePickerControllerDelegate { 38 | 39 | @Binding var imagePickerVisible: Bool 40 | @Binding var selectedImage: Image? 41 | 42 | init(imagePickerVisible: Binding, 43 | selectedImage: Binding) { 44 | _imagePickerVisible = imagePickerVisible 45 | _selectedImage = selectedImage 46 | } 47 | 48 | func imagePickerController(_ picker: UIImagePickerController, 49 | didFinishPickingMediaWithInfo 50 | info: [UIImagePickerController.InfoKey : Any]) { 51 | let uiImage = 52 | info[UIImagePickerController.InfoKey.originalImage] as! 53 | UIImage 54 | selectedImage = Image(uiImage: uiImage) 55 | imagePickerVisible = false 56 | } 57 | 58 | func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { 59 | imagePickerVisible = false 60 | } 61 | } 62 | 63 | } 64 | /* 65 | struct MyImagePicker_Previews: PreviewProvider { 66 | static var previews: some View { 67 | MyImagePicker() 68 | } 69 | } 70 | */ 71 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/ViewControllerDemo/ViewControllerDemo.xcodeproj/project.xcworkspace/xcuserdata/neilsmyth.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo.xcodeproj/xcuserdata/neilsmyth.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ViewControllerDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ViewControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/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 | } -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/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 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ViewControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | @State var imagePickerVisible: Bool = false 14 | @State var selectedImage: Image? = Image(systemName: "photo") 15 | 16 | var body: some View { 17 | ZStack { 18 | VStack { 19 | 20 | selectedImage? 21 | .resizable() 22 | .aspectRatio(contentMode: .fit) 23 | 24 | Button(action: { 25 | withAnimation { 26 | self.imagePickerVisible.toggle() 27 | } 28 | }) { 29 | Text("Select an Image") 30 | } 31 | 32 | }.padding() 33 | 34 | if (imagePickerVisible) { 35 | MyImagePicker(imagePickerVisible: 36 | $imagePickerVisible, 37 | selectedImage: $selectedImage) 38 | } 39 | } 40 | 41 | } 42 | } 43 | 44 | struct ContentView_Previews: PreviewProvider { 45 | static var previews: some View { 46 | ContentView() 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ViewControllerDemo/ViewControllerDemo/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // ViewControllerDemo 4 | // 5 | // Created by Neil Smyth on 10/16/19. 6 | // Copyright © 2019 eBookFrenzy. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /playground_images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/playground_images/.DS_Store -------------------------------------------------------------------------------- /playground_images/waterfall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/SwiftUI/defbcdd40638ec4d8d55e6693e7c878a00b1d135/playground_images/waterfall.png --------------------------------------------------------------------------------