├── .DS_Store ├── .gitignore ├── README.md ├── SwiftBeta-Curso-SwiftUI-Introduccion.xcodeproj └── project.pbxproj ├── SwiftBeta-Curso-SwiftUI-Introduccion ├── .DS_Store ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── youtube.imageset │ │ ├── Contents.json │ │ └── youtube.pdf ├── ContentView.swift ├── Info.plist ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift └── Videos │ ├── 10-TextEditorView.swift │ ├── 11-DatePickerView.swift │ ├── 12-ColorPickerView.swift │ ├── 13-ProgressViewView.swift │ ├── 14-LinkView.swift │ ├── 15-ToggleView.swift │ ├── 16-StepperView.swift │ ├── 17-SliderView.swift │ ├── 18-LazyVGrid_LazyHGridView.swift │ ├── 19-FormView.swift │ ├── 2-StacksView.swift │ ├── 20-ListView.swift │ ├── 21-NavigationView_NavigationLink.swift │ ├── 22-TabView.swift │ ├── 23-fullScreenCover_sheet.swift │ ├── 24-AlertView.swift │ ├── 25-ActionSheetView.swift │ ├── 26-ContextMenuView.swift │ ├── 27-Tap_Gesture.swift │ ├── 28-Drag_Gesture.swift │ ├── 29-StateVsBinding.swift │ ├── 3-Image.swift │ ├── 30-ObservedObjectVsStateObject.swift │ ├── 31-PropertyWrapperEnvironmentObject.swift │ ├── 32-PropertyWrapperAppStorage.swift │ ├── 33-PropertyWrapperSceneStorage.swift │ ├── 34-AsyncImageView.swift │ ├── 35-swipeActionsAndRefreshable.swift │ ├── 36-GeometryReaderView.swift │ ├── 37-View_Modifier.swift │ ├── 38-PropertyWrapperPreferenceKey.swift │ ├── 39-ReduxView.swift │ ├── 4-IconsAndSymbols.swift │ ├── 40-Calculadora │ ├── 40-CalculadoraView.swift │ ├── CalculadoraViewModel.swift │ ├── Colors.swift │ ├── Matrix.swift │ ├── Model.swift │ └── VerticalButtonStack.swift │ ├── 5-PropertyWrapperState.swift │ ├── 6-LabelView.swift │ ├── 7-TextView.swift │ ├── 8-ButtonView.swift │ └── 9-TextFieldView.swift ├── curso-swiftui.json └── resources ├── .DS_Store ├── all-videos.png └── logo.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftBeta/Curso-SwiftUI-Introduccion/2756487a7734f410dcdc30691283de3fd4adb398/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/swift,xcode 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=swift,xcode 4 | 5 | ### Swift ### 6 | # Xcode 7 | # 8 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 9 | 10 | ## User settings 11 | xcuserdata/ 12 | 13 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 14 | *.xcscmblueprint 15 | *.xccheckout 16 | 17 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 18 | build/ 19 | DerivedData/ 20 | *.moved-aside 21 | *.pbxuser 22 | !default.pbxuser 23 | *.mode1v3 24 | !default.mode1v3 25 | *.mode2v3 26 | !default.mode2v3 27 | *.perspectivev3 28 | !default.perspectivev3 29 | 30 | ## Obj-C/Swift specific 31 | *.hmap 32 | 33 | ## App packaging 34 | *.ipa 35 | *.dSYM.zip 36 | *.dSYM 37 | 38 | ## Playgrounds 39 | timeline.xctimeline 40 | playground.xcworkspace 41 | 42 | # Swift Package Manager 43 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 44 | # Packages/ 45 | # Package.pins 46 | # Package.resolved 47 | # *.xcodeproj 48 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 49 | # hence it is not needed unless you have added a package configuration file to your project 50 | # .swiftpm 51 | 52 | .build/ 53 | 54 | # CocoaPods 55 | # We recommend against adding the Pods directory to your .gitignore. However 56 | # you should judge for yourself, the pros and cons are mentioned at: 57 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 58 | # Pods/ 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 64 | # Carthage/Checkouts 65 | 66 | Carthage/Build/ 67 | 68 | # Accio dependency management 69 | Dependencies/ 70 | .accio/ 71 | 72 | # fastlane 73 | # It is recommended to not store the screenshots in the git repo. 74 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 75 | # For more information about the recommended setup visit: 76 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 77 | 78 | fastlane/report.xml 79 | fastlane/Preview.html 80 | fastlane/screenshots/**/*.png 81 | fastlane/test_output 82 | 83 | # Code Injection 84 | # After new code Injection tools there's a generated folder /iOSInjectionProject 85 | # https://github.com/johnno1962/injectionforxcode 86 | 87 | iOSInjectionProject/ 88 | 89 | ### Xcode ### 90 | # Xcode 91 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 92 | 93 | 94 | 95 | 96 | ## Gcc Patch 97 | /*.gcno 98 | 99 | ### Xcode Patch ### 100 | *.xcodeproj/* 101 | !*.xcodeproj/project.pbxproj 102 | !*.xcodeproj/xcshareddata/ 103 | !*.xcworkspace/contents.xcworkspacedata 104 | **/xcshareddata/WorkspaceSettings.xcsettings 105 | 106 | # End of https://www.toptal.com/developers/gitignore/api/swift,xcode 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![https://www.swiftbeta.com](https://github.com/swiftbeta/Curso-SwiftUI-Introduccion/raw/main/resources/logo.png) 👋 Hola, mi nombre es SwiftBeta 2 | ### 👨🏻‍💻 iOS Tech Lead de día - Creador de contenido iOS de noche 3 | 4 | [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UC2MAP8k0bzwq_OAA_zQw27A?style=social)](https://youtube.com/swiftbeta?sub_confirmation=1) 5 | ![GitHub Followers](https://img.shields.io/github/followers/swiftbeta?style=social) 6 | 7 | # 40 videos GRATIS - Curso de SWIFTUI Introducción en Español. 8 | 9 | # ![https://www.swiftbeta.com](https://github.com/swiftbeta/Curso-SwiftUI-Introduccion/raw/main/resources/all-videos.png) 10 | # 📱 CURSO de PROGRAMACIÓN SwiftUI y Xcode (Introducción a SwiftUI | Aprende SwiftUI desde cero) 11 | ## Selecciona el video que quieras y se abrirá en Youtube 12 | 13 | 14 | --- 15 | 16 | 17 | 18 | 23 | 28 | 33 | 34 | 35 | 40 | 45 | 50 | 51 | 52 | 57 | 62 | 67 | 68 | 69 | 75 | 80 | 85 | 86 | 87 | 93 | 98 | 103 | 104 | 105 | 111 | 116 | 121 | 122 | 123 | 129 | 134 | 139 | 140 | 141 | 147 | 152 | 157 | 158 | 159 | 165 | 170 | 175 | 176 | 177 | 183 | 188 | 193 | 194 | 195 | 201 | 206 | 211 | 212 | 213 | 219 | 224 | 229 | 230 | 231 | 237 | 242 | 247 | 248 | 249 | 255 | 256 |
19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 |
36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 |
53 | 54 | 55 | 56 | 58 | 59 | 60 | 61 | 63 | 64 | 65 | 66 |
70 | 71 | 72 | 73 | 74 | 76 | 77 | 78 | 79 | 81 | 82 | 83 | 84 |
88 | 89 | 90 | 91 | 92 | 94 | 95 | 96 | 97 | 99 | 100 | 101 | 102 |
106 | 107 | 108 | 109 | 110 | 112 | 113 | 114 | 115 | 117 | 118 | 119 | 120 |
124 | 125 | 126 | 127 | 128 | 130 | 131 | 132 | 133 | 135 | 136 | 137 | 138 |
142 | 143 | 144 | 145 | 146 | 148 | 149 | 150 | 151 | 153 | 154 | 155 | 156 |
160 | 161 | 162 | 163 | 164 | 166 | 167 | 168 | 169 | 171 | 172 | 173 | 174 |
178 | 179 | 180 | 181 | 182 | 184 | 185 | 186 | 187 | 189 | 190 | 191 | 192 |
196 | 197 | 198 | 199 | 200 | 202 | 203 | 204 | 205 | 207 | 208 | 209 | 210 |
214 | 215 | 216 | 217 | 218 | 220 | 221 | 222 | 223 | 225 | 226 | 227 | 228 |
232 | 233 | 234 | 235 | 236 | 238 | 239 | 240 | 241 | 243 | 244 | 245 | 246 |
250 | 251 | 252 | 253 | 254 |
257 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F432558426EFB13300C8D212 /* 38-PropertyWrapperPreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432558326EFB13300C8D212 /* 38-PropertyWrapperPreferenceKey.swift */; }; 11 | F432558626EFB25A00C8D212 /* 39-ReduxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432558526EFB25A00C8D212 /* 39-ReduxView.swift */; }; 12 | F432558926EFB29E00C8D212 /* 40-CalculadoraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432558826EFB29E00C8D212 /* 40-CalculadoraView.swift */; }; 13 | F432558B26EFB2BD00C8D212 /* CalculadoraViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432558A26EFB2BD00C8D212 /* CalculadoraViewModel.swift */; }; 14 | F432558D26EFB2D100C8D212 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432558C26EFB2D100C8D212 /* Model.swift */; }; 15 | F432558F26EFB2DF00C8D212 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432558E26EFB2DF00C8D212 /* Colors.swift */; }; 16 | F432559126EFB2ED00C8D212 /* Matrix.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432559026EFB2ED00C8D212 /* Matrix.swift */; }; 17 | F432559326EFB2FE00C8D212 /* VerticalButtonStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = F432559226EFB2FE00C8D212 /* VerticalButtonStack.swift */; }; 18 | F43BB10726EFAA220098D42C /* SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB10626EFAA220098D42C /* SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift */; }; 19 | F43BB10926EFAA220098D42C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB10826EFAA220098D42C /* ContentView.swift */; }; 20 | F43BB10B26EFAA230098D42C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F43BB10A26EFAA230098D42C /* Assets.xcassets */; }; 21 | F43BB10E26EFAA230098D42C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F43BB10D26EFAA230098D42C /* Preview Assets.xcassets */; }; 22 | F43BB12826EFAA2B0098D42C /* 19-FormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11626EFAA2B0098D42C /* 19-FormView.swift */; }; 23 | F43BB12926EFAA2B0098D42C /* 6-LabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11726EFAA2B0098D42C /* 6-LabelView.swift */; }; 24 | F43BB12A26EFAA2B0098D42C /* 14-LinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11826EFAA2B0098D42C /* 14-LinkView.swift */; }; 25 | F43BB12B26EFAA2B0098D42C /* 13-ProgressViewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11926EFAA2B0098D42C /* 13-ProgressViewView.swift */; }; 26 | F43BB12C26EFAA2B0098D42C /* 18-LazyVGrid_LazyHGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11A26EFAA2B0098D42C /* 18-LazyVGrid_LazyHGridView.swift */; }; 27 | F43BB12D26EFAA2B0098D42C /* 5-PropertyWrapperState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11B26EFAA2B0098D42C /* 5-PropertyWrapperState.swift */; }; 28 | F43BB12E26EFAA2B0098D42C /* 16-StepperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11C26EFAA2B0098D42C /* 16-StepperView.swift */; }; 29 | F43BB12F26EFAA2B0098D42C /* 2-StacksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11D26EFAA2B0098D42C /* 2-StacksView.swift */; }; 30 | F43BB13026EFAA2B0098D42C /* 3-Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11E26EFAA2B0098D42C /* 3-Image.swift */; }; 31 | F43BB13126EFAA2B0098D42C /* 4-IconsAndSymbols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB11F26EFAA2B0098D42C /* 4-IconsAndSymbols.swift */; }; 32 | F43BB13226EFAA2B0098D42C /* 9-TextFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12026EFAA2B0098D42C /* 9-TextFieldView.swift */; }; 33 | F43BB13326EFAA2B0098D42C /* 12-ColorPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12126EFAA2B0098D42C /* 12-ColorPickerView.swift */; }; 34 | F43BB13426EFAA2B0098D42C /* 17-SliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12226EFAA2B0098D42C /* 17-SliderView.swift */; }; 35 | F43BB13526EFAA2B0098D42C /* 11-DatePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12326EFAA2B0098D42C /* 11-DatePickerView.swift */; }; 36 | F43BB13626EFAA2B0098D42C /* 15-ToggleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12426EFAA2B0098D42C /* 15-ToggleView.swift */; }; 37 | F43BB13726EFAA2B0098D42C /* 10-TextEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12526EFAA2B0098D42C /* 10-TextEditorView.swift */; }; 38 | F43BB13826EFAA2B0098D42C /* 7-TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12626EFAA2B0098D42C /* 7-TextView.swift */; }; 39 | F43BB13926EFAA2B0098D42C /* 8-ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB12726EFAA2B0098D42C /* 8-ButtonView.swift */; }; 40 | F43BB13B26EFAA920098D42C /* 20-ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB13A26EFAA920098D42C /* 20-ListView.swift */; }; 41 | F43BB13D26EFAB090098D42C /* 21-NavigationView_NavigationLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB13C26EFAB090098D42C /* 21-NavigationView_NavigationLink.swift */; }; 42 | F43BB13F26EFAB500098D42C /* 22-TabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB13E26EFAB500098D42C /* 22-TabView.swift */; }; 43 | F43BB14126EFABB70098D42C /* 23-fullScreenCover_sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14026EFABB70098D42C /* 23-fullScreenCover_sheet.swift */; }; 44 | F43BB14326EFABDE0098D42C /* 24-AlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14226EFABDE0098D42C /* 24-AlertView.swift */; }; 45 | F43BB14526EFAC000098D42C /* 25-ActionSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14426EFAC000098D42C /* 25-ActionSheetView.swift */; }; 46 | F43BB14726EFAC2D0098D42C /* 26-ContextMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14626EFAC2D0098D42C /* 26-ContextMenuView.swift */; }; 47 | F43BB14926EFAC5B0098D42C /* 27-Tap_Gesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14826EFAC5B0098D42C /* 27-Tap_Gesture.swift */; }; 48 | F43BB14B26EFAC8B0098D42C /* 28-Drag_Gesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14A26EFAC8B0098D42C /* 28-Drag_Gesture.swift */; }; 49 | F43BB14D26EFACB60098D42C /* 29-StateVsBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14C26EFACB60098D42C /* 29-StateVsBinding.swift */; }; 50 | F43BB14F26EFACF90098D42C /* 30-ObservedObjectVsStateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB14E26EFACF90098D42C /* 30-ObservedObjectVsStateObject.swift */; }; 51 | F43BB15126EFAE4D0098D42C /* 31-PropertyWrapperEnvironmentObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB15026EFAE4D0098D42C /* 31-PropertyWrapperEnvironmentObject.swift */; }; 52 | F43BB15326EFAEB70098D42C /* 32-PropertyWrapperAppStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB15226EFAEB70098D42C /* 32-PropertyWrapperAppStorage.swift */; }; 53 | F43BB15526EFAECC0098D42C /* 33-PropertyWrapperSceneStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43BB15426EFAECC0098D42C /* 33-PropertyWrapperSceneStorage.swift */; }; 54 | F45B8FCF26EFAF9E00BE2C15 /* 34-AsyncImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45B8FCE26EFAF9E00BE2C15 /* 34-AsyncImageView.swift */; }; 55 | F45B8FD126EFB01000BE2C15 /* 35-swipeActionsAndRefreshable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45B8FD026EFB01000BE2C15 /* 35-swipeActionsAndRefreshable.swift */; }; 56 | F45B8FD326EFB0BF00BE2C15 /* 36-GeometryReaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45B8FD226EFB0BF00BE2C15 /* 36-GeometryReaderView.swift */; }; 57 | F45B8FD526EFB0F100BE2C15 /* 37-View_Modifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45B8FD426EFB0F100BE2C15 /* 37-View_Modifier.swift */; }; 58 | /* End PBXBuildFile section */ 59 | 60 | /* Begin PBXFileReference section */ 61 | F432558326EFB13300C8D212 /* 38-PropertyWrapperPreferenceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "38-PropertyWrapperPreferenceKey.swift"; sourceTree = ""; }; 62 | F432558526EFB25A00C8D212 /* 39-ReduxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "39-ReduxView.swift"; sourceTree = ""; }; 63 | F432558826EFB29E00C8D212 /* 40-CalculadoraView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "40-CalculadoraView.swift"; sourceTree = ""; }; 64 | F432558A26EFB2BD00C8D212 /* CalculadoraViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalculadoraViewModel.swift; sourceTree = ""; }; 65 | F432558C26EFB2D100C8D212 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = ""; }; 66 | F432558E26EFB2DF00C8D212 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; 67 | F432559026EFB2ED00C8D212 /* Matrix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Matrix.swift; sourceTree = ""; }; 68 | F432559226EFB2FE00C8D212 /* VerticalButtonStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalButtonStack.swift; sourceTree = ""; }; 69 | F43BB10326EFAA220098D42C /* SwiftBeta-Curso-SwiftUI-Introduccion.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SwiftBeta-Curso-SwiftUI-Introduccion.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 70 | F43BB10626EFAA220098D42C /* SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift; sourceTree = ""; }; 71 | F43BB10826EFAA220098D42C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 72 | F43BB10A26EFAA230098D42C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 73 | F43BB10D26EFAA230098D42C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 74 | F43BB10F26EFAA230098D42C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 75 | F43BB11626EFAA2B0098D42C /* 19-FormView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "19-FormView.swift"; sourceTree = ""; }; 76 | F43BB11726EFAA2B0098D42C /* 6-LabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "6-LabelView.swift"; sourceTree = ""; }; 77 | F43BB11826EFAA2B0098D42C /* 14-LinkView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "14-LinkView.swift"; sourceTree = ""; }; 78 | F43BB11926EFAA2B0098D42C /* 13-ProgressViewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "13-ProgressViewView.swift"; sourceTree = ""; }; 79 | F43BB11A26EFAA2B0098D42C /* 18-LazyVGrid_LazyHGridView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "18-LazyVGrid_LazyHGridView.swift"; sourceTree = ""; }; 80 | F43BB11B26EFAA2B0098D42C /* 5-PropertyWrapperState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "5-PropertyWrapperState.swift"; sourceTree = ""; }; 81 | F43BB11C26EFAA2B0098D42C /* 16-StepperView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "16-StepperView.swift"; sourceTree = ""; }; 82 | F43BB11D26EFAA2B0098D42C /* 2-StacksView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "2-StacksView.swift"; sourceTree = ""; }; 83 | F43BB11E26EFAA2B0098D42C /* 3-Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "3-Image.swift"; sourceTree = ""; }; 84 | F43BB11F26EFAA2B0098D42C /* 4-IconsAndSymbols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "4-IconsAndSymbols.swift"; sourceTree = ""; }; 85 | F43BB12026EFAA2B0098D42C /* 9-TextFieldView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "9-TextFieldView.swift"; sourceTree = ""; }; 86 | F43BB12126EFAA2B0098D42C /* 12-ColorPickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "12-ColorPickerView.swift"; sourceTree = ""; }; 87 | F43BB12226EFAA2B0098D42C /* 17-SliderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "17-SliderView.swift"; sourceTree = ""; }; 88 | F43BB12326EFAA2B0098D42C /* 11-DatePickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "11-DatePickerView.swift"; sourceTree = ""; }; 89 | F43BB12426EFAA2B0098D42C /* 15-ToggleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "15-ToggleView.swift"; sourceTree = ""; }; 90 | F43BB12526EFAA2B0098D42C /* 10-TextEditorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "10-TextEditorView.swift"; sourceTree = ""; }; 91 | F43BB12626EFAA2B0098D42C /* 7-TextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "7-TextView.swift"; sourceTree = ""; }; 92 | F43BB12726EFAA2B0098D42C /* 8-ButtonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "8-ButtonView.swift"; sourceTree = ""; }; 93 | F43BB13A26EFAA920098D42C /* 20-ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "20-ListView.swift"; sourceTree = ""; }; 94 | F43BB13C26EFAB090098D42C /* 21-NavigationView_NavigationLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "21-NavigationView_NavigationLink.swift"; sourceTree = ""; }; 95 | F43BB13E26EFAB500098D42C /* 22-TabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "22-TabView.swift"; sourceTree = ""; }; 96 | F43BB14026EFABB70098D42C /* 23-fullScreenCover_sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "23-fullScreenCover_sheet.swift"; sourceTree = ""; }; 97 | F43BB14226EFABDE0098D42C /* 24-AlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "24-AlertView.swift"; sourceTree = ""; }; 98 | F43BB14426EFAC000098D42C /* 25-ActionSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "25-ActionSheetView.swift"; sourceTree = ""; }; 99 | F43BB14626EFAC2D0098D42C /* 26-ContextMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "26-ContextMenuView.swift"; sourceTree = ""; }; 100 | F43BB14826EFAC5B0098D42C /* 27-Tap_Gesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "27-Tap_Gesture.swift"; sourceTree = ""; }; 101 | F43BB14A26EFAC8B0098D42C /* 28-Drag_Gesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "28-Drag_Gesture.swift"; sourceTree = ""; }; 102 | F43BB14C26EFACB60098D42C /* 29-StateVsBinding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "29-StateVsBinding.swift"; sourceTree = ""; }; 103 | F43BB14E26EFACF90098D42C /* 30-ObservedObjectVsStateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "30-ObservedObjectVsStateObject.swift"; sourceTree = ""; }; 104 | F43BB15026EFAE4D0098D42C /* 31-PropertyWrapperEnvironmentObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "31-PropertyWrapperEnvironmentObject.swift"; sourceTree = ""; }; 105 | F43BB15226EFAEB70098D42C /* 32-PropertyWrapperAppStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "32-PropertyWrapperAppStorage.swift"; sourceTree = ""; }; 106 | F43BB15426EFAECC0098D42C /* 33-PropertyWrapperSceneStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "33-PropertyWrapperSceneStorage.swift"; sourceTree = ""; }; 107 | F45B8FCE26EFAF9E00BE2C15 /* 34-AsyncImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "34-AsyncImageView.swift"; sourceTree = ""; }; 108 | F45B8FD026EFB01000BE2C15 /* 35-swipeActionsAndRefreshable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "35-swipeActionsAndRefreshable.swift"; sourceTree = ""; }; 109 | F45B8FD226EFB0BF00BE2C15 /* 36-GeometryReaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "36-GeometryReaderView.swift"; sourceTree = ""; }; 110 | F45B8FD426EFB0F100BE2C15 /* 37-View_Modifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "37-View_Modifier.swift"; sourceTree = ""; }; 111 | /* End PBXFileReference section */ 112 | 113 | /* Begin PBXFrameworksBuildPhase section */ 114 | F43BB10026EFAA220098D42C /* Frameworks */ = { 115 | isa = PBXFrameworksBuildPhase; 116 | buildActionMask = 2147483647; 117 | files = ( 118 | ); 119 | runOnlyForDeploymentPostprocessing = 0; 120 | }; 121 | /* End PBXFrameworksBuildPhase section */ 122 | 123 | /* Begin PBXGroup section */ 124 | F432558726EFB28600C8D212 /* 40-Calculadora */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | F432558826EFB29E00C8D212 /* 40-CalculadoraView.swift */, 128 | F432558A26EFB2BD00C8D212 /* CalculadoraViewModel.swift */, 129 | F432558C26EFB2D100C8D212 /* Model.swift */, 130 | F432558E26EFB2DF00C8D212 /* Colors.swift */, 131 | F432559026EFB2ED00C8D212 /* Matrix.swift */, 132 | F432559226EFB2FE00C8D212 /* VerticalButtonStack.swift */, 133 | ); 134 | path = "40-Calculadora"; 135 | sourceTree = ""; 136 | }; 137 | F43BB0FA26EFAA220098D42C = { 138 | isa = PBXGroup; 139 | children = ( 140 | F43BB10526EFAA220098D42C /* SwiftBeta-Curso-SwiftUI-Introduccion */, 141 | F43BB10426EFAA220098D42C /* Products */, 142 | ); 143 | sourceTree = ""; 144 | }; 145 | F43BB10426EFAA220098D42C /* Products */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | F43BB10326EFAA220098D42C /* SwiftBeta-Curso-SwiftUI-Introduccion.app */, 149 | ); 150 | name = Products; 151 | sourceTree = ""; 152 | }; 153 | F43BB10526EFAA220098D42C /* SwiftBeta-Curso-SwiftUI-Introduccion */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | F43BB10626EFAA220098D42C /* SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift */, 157 | F43BB10826EFAA220098D42C /* ContentView.swift */, 158 | F43BB11526EFAA2B0098D42C /* Videos */, 159 | F43BB10A26EFAA230098D42C /* Assets.xcassets */, 160 | F43BB10F26EFAA230098D42C /* Info.plist */, 161 | F43BB10C26EFAA230098D42C /* Preview Content */, 162 | ); 163 | path = "SwiftBeta-Curso-SwiftUI-Introduccion"; 164 | sourceTree = ""; 165 | }; 166 | F43BB10C26EFAA230098D42C /* Preview Content */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | F43BB10D26EFAA230098D42C /* Preview Assets.xcassets */, 170 | ); 171 | path = "Preview Content"; 172 | sourceTree = ""; 173 | }; 174 | F43BB11526EFAA2B0098D42C /* Videos */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | F43BB11D26EFAA2B0098D42C /* 2-StacksView.swift */, 178 | F43BB11E26EFAA2B0098D42C /* 3-Image.swift */, 179 | F43BB11F26EFAA2B0098D42C /* 4-IconsAndSymbols.swift */, 180 | F43BB11B26EFAA2B0098D42C /* 5-PropertyWrapperState.swift */, 181 | F43BB11726EFAA2B0098D42C /* 6-LabelView.swift */, 182 | F43BB12626EFAA2B0098D42C /* 7-TextView.swift */, 183 | F43BB12726EFAA2B0098D42C /* 8-ButtonView.swift */, 184 | F43BB12026EFAA2B0098D42C /* 9-TextFieldView.swift */, 185 | F43BB12526EFAA2B0098D42C /* 10-TextEditorView.swift */, 186 | F43BB12326EFAA2B0098D42C /* 11-DatePickerView.swift */, 187 | F43BB12126EFAA2B0098D42C /* 12-ColorPickerView.swift */, 188 | F43BB11926EFAA2B0098D42C /* 13-ProgressViewView.swift */, 189 | F43BB11826EFAA2B0098D42C /* 14-LinkView.swift */, 190 | F43BB12426EFAA2B0098D42C /* 15-ToggleView.swift */, 191 | F43BB11C26EFAA2B0098D42C /* 16-StepperView.swift */, 192 | F43BB12226EFAA2B0098D42C /* 17-SliderView.swift */, 193 | F43BB11A26EFAA2B0098D42C /* 18-LazyVGrid_LazyHGridView.swift */, 194 | F43BB11626EFAA2B0098D42C /* 19-FormView.swift */, 195 | F43BB13A26EFAA920098D42C /* 20-ListView.swift */, 196 | F43BB13C26EFAB090098D42C /* 21-NavigationView_NavigationLink.swift */, 197 | F43BB13E26EFAB500098D42C /* 22-TabView.swift */, 198 | F43BB14026EFABB70098D42C /* 23-fullScreenCover_sheet.swift */, 199 | F43BB14226EFABDE0098D42C /* 24-AlertView.swift */, 200 | F43BB14426EFAC000098D42C /* 25-ActionSheetView.swift */, 201 | F43BB14626EFAC2D0098D42C /* 26-ContextMenuView.swift */, 202 | F43BB14826EFAC5B0098D42C /* 27-Tap_Gesture.swift */, 203 | F43BB14A26EFAC8B0098D42C /* 28-Drag_Gesture.swift */, 204 | F43BB14C26EFACB60098D42C /* 29-StateVsBinding.swift */, 205 | F43BB14E26EFACF90098D42C /* 30-ObservedObjectVsStateObject.swift */, 206 | F43BB15026EFAE4D0098D42C /* 31-PropertyWrapperEnvironmentObject.swift */, 207 | F43BB15226EFAEB70098D42C /* 32-PropertyWrapperAppStorage.swift */, 208 | F43BB15426EFAECC0098D42C /* 33-PropertyWrapperSceneStorage.swift */, 209 | F45B8FCE26EFAF9E00BE2C15 /* 34-AsyncImageView.swift */, 210 | F45B8FD026EFB01000BE2C15 /* 35-swipeActionsAndRefreshable.swift */, 211 | F45B8FD226EFB0BF00BE2C15 /* 36-GeometryReaderView.swift */, 212 | F45B8FD426EFB0F100BE2C15 /* 37-View_Modifier.swift */, 213 | F432558326EFB13300C8D212 /* 38-PropertyWrapperPreferenceKey.swift */, 214 | F432558526EFB25A00C8D212 /* 39-ReduxView.swift */, 215 | F432558726EFB28600C8D212 /* 40-Calculadora */, 216 | ); 217 | path = Videos; 218 | sourceTree = ""; 219 | }; 220 | /* End PBXGroup section */ 221 | 222 | /* Begin PBXNativeTarget section */ 223 | F43BB10226EFAA220098D42C /* SwiftBeta-Curso-SwiftUI-Introduccion */ = { 224 | isa = PBXNativeTarget; 225 | buildConfigurationList = F43BB11226EFAA230098D42C /* Build configuration list for PBXNativeTarget "SwiftBeta-Curso-SwiftUI-Introduccion" */; 226 | buildPhases = ( 227 | F43BB0FF26EFAA220098D42C /* Sources */, 228 | F43BB10026EFAA220098D42C /* Frameworks */, 229 | F43BB10126EFAA220098D42C /* Resources */, 230 | ); 231 | buildRules = ( 232 | ); 233 | dependencies = ( 234 | ); 235 | name = "SwiftBeta-Curso-SwiftUI-Introduccion"; 236 | productName = "SwiftBeta-Curso-SwiftUI-Introduccion"; 237 | productReference = F43BB10326EFAA220098D42C /* SwiftBeta-Curso-SwiftUI-Introduccion.app */; 238 | productType = "com.apple.product-type.application"; 239 | }; 240 | /* End PBXNativeTarget section */ 241 | 242 | /* Begin PBXProject section */ 243 | F43BB0FB26EFAA220098D42C /* Project object */ = { 244 | isa = PBXProject; 245 | attributes = { 246 | LastSwiftUpdateCheck = 1250; 247 | LastUpgradeCheck = 1250; 248 | TargetAttributes = { 249 | F43BB10226EFAA220098D42C = { 250 | CreatedOnToolsVersion = 12.5; 251 | }; 252 | }; 253 | }; 254 | buildConfigurationList = F43BB0FE26EFAA220098D42C /* Build configuration list for PBXProject "SwiftBeta-Curso-SwiftUI-Introduccion" */; 255 | compatibilityVersion = "Xcode 9.3"; 256 | developmentRegion = en; 257 | hasScannedForEncodings = 0; 258 | knownRegions = ( 259 | en, 260 | Base, 261 | ); 262 | mainGroup = F43BB0FA26EFAA220098D42C; 263 | productRefGroup = F43BB10426EFAA220098D42C /* Products */; 264 | projectDirPath = ""; 265 | projectRoot = ""; 266 | targets = ( 267 | F43BB10226EFAA220098D42C /* SwiftBeta-Curso-SwiftUI-Introduccion */, 268 | ); 269 | }; 270 | /* End PBXProject section */ 271 | 272 | /* Begin PBXResourcesBuildPhase section */ 273 | F43BB10126EFAA220098D42C /* Resources */ = { 274 | isa = PBXResourcesBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | F43BB10E26EFAA230098D42C /* Preview Assets.xcassets in Resources */, 278 | F43BB10B26EFAA230098D42C /* Assets.xcassets in Resources */, 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | /* End PBXResourcesBuildPhase section */ 283 | 284 | /* Begin PBXSourcesBuildPhase section */ 285 | F43BB0FF26EFAA220098D42C /* Sources */ = { 286 | isa = PBXSourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | F43BB13026EFAA2B0098D42C /* 3-Image.swift in Sources */, 290 | F432558F26EFB2DF00C8D212 /* Colors.swift in Sources */, 291 | F432558426EFB13300C8D212 /* 38-PropertyWrapperPreferenceKey.swift in Sources */, 292 | F43BB13726EFAA2B0098D42C /* 10-TextEditorView.swift in Sources */, 293 | F43BB12F26EFAA2B0098D42C /* 2-StacksView.swift in Sources */, 294 | F45B8FD526EFB0F100BE2C15 /* 37-View_Modifier.swift in Sources */, 295 | F43BB14926EFAC5B0098D42C /* 27-Tap_Gesture.swift in Sources */, 296 | F45B8FD126EFB01000BE2C15 /* 35-swipeActionsAndRefreshable.swift in Sources */, 297 | F43BB13426EFAA2B0098D42C /* 17-SliderView.swift in Sources */, 298 | F43BB14F26EFACF90098D42C /* 30-ObservedObjectVsStateObject.swift in Sources */, 299 | F43BB12D26EFAA2B0098D42C /* 5-PropertyWrapperState.swift in Sources */, 300 | F432559126EFB2ED00C8D212 /* Matrix.swift in Sources */, 301 | F43BB14326EFABDE0098D42C /* 24-AlertView.swift in Sources */, 302 | F43BB14726EFAC2D0098D42C /* 26-ContextMenuView.swift in Sources */, 303 | F43BB10926EFAA220098D42C /* ContentView.swift in Sources */, 304 | F43BB12A26EFAA2B0098D42C /* 14-LinkView.swift in Sources */, 305 | F432558B26EFB2BD00C8D212 /* CalculadoraViewModel.swift in Sources */, 306 | F43BB12E26EFAA2B0098D42C /* 16-StepperView.swift in Sources */, 307 | F43BB12826EFAA2B0098D42C /* 19-FormView.swift in Sources */, 308 | F43BB13526EFAA2B0098D42C /* 11-DatePickerView.swift in Sources */, 309 | F43BB13326EFAA2B0098D42C /* 12-ColorPickerView.swift in Sources */, 310 | F43BB14D26EFACB60098D42C /* 29-StateVsBinding.swift in Sources */, 311 | F43BB13826EFAA2B0098D42C /* 7-TextView.swift in Sources */, 312 | F43BB14526EFAC000098D42C /* 25-ActionSheetView.swift in Sources */, 313 | F43BB13126EFAA2B0098D42C /* 4-IconsAndSymbols.swift in Sources */, 314 | F43BB15126EFAE4D0098D42C /* 31-PropertyWrapperEnvironmentObject.swift in Sources */, 315 | F43BB15326EFAEB70098D42C /* 32-PropertyWrapperAppStorage.swift in Sources */, 316 | F43BB13926EFAA2B0098D42C /* 8-ButtonView.swift in Sources */, 317 | F43BB13D26EFAB090098D42C /* 21-NavigationView_NavigationLink.swift in Sources */, 318 | F43BB12926EFAA2B0098D42C /* 6-LabelView.swift in Sources */, 319 | F43BB14126EFABB70098D42C /* 23-fullScreenCover_sheet.swift in Sources */, 320 | F43BB13626EFAA2B0098D42C /* 15-ToggleView.swift in Sources */, 321 | F432558626EFB25A00C8D212 /* 39-ReduxView.swift in Sources */, 322 | F43BB13226EFAA2B0098D42C /* 9-TextFieldView.swift in Sources */, 323 | F432558926EFB29E00C8D212 /* 40-CalculadoraView.swift in Sources */, 324 | F43BB13B26EFAA920098D42C /* 20-ListView.swift in Sources */, 325 | F432559326EFB2FE00C8D212 /* VerticalButtonStack.swift in Sources */, 326 | F45B8FCF26EFAF9E00BE2C15 /* 34-AsyncImageView.swift in Sources */, 327 | F43BB12B26EFAA2B0098D42C /* 13-ProgressViewView.swift in Sources */, 328 | F43BB13F26EFAB500098D42C /* 22-TabView.swift in Sources */, 329 | F43BB10726EFAA220098D42C /* SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift in Sources */, 330 | F43BB15526EFAECC0098D42C /* 33-PropertyWrapperSceneStorage.swift in Sources */, 331 | F432558D26EFB2D100C8D212 /* Model.swift in Sources */, 332 | F45B8FD326EFB0BF00BE2C15 /* 36-GeometryReaderView.swift in Sources */, 333 | F43BB12C26EFAA2B0098D42C /* 18-LazyVGrid_LazyHGridView.swift in Sources */, 334 | F43BB14B26EFAC8B0098D42C /* 28-Drag_Gesture.swift in Sources */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | /* End PBXSourcesBuildPhase section */ 339 | 340 | /* Begin XCBuildConfiguration section */ 341 | F43BB11026EFAA230098D42C /* Debug */ = { 342 | isa = XCBuildConfiguration; 343 | buildSettings = { 344 | ALWAYS_SEARCH_USER_PATHS = NO; 345 | CLANG_ANALYZER_NONNULL = YES; 346 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 347 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 348 | CLANG_CXX_LIBRARY = "libc++"; 349 | CLANG_ENABLE_MODULES = YES; 350 | CLANG_ENABLE_OBJC_ARC = YES; 351 | CLANG_ENABLE_OBJC_WEAK = YES; 352 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 353 | CLANG_WARN_BOOL_CONVERSION = YES; 354 | CLANG_WARN_COMMA = YES; 355 | CLANG_WARN_CONSTANT_CONVERSION = YES; 356 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 357 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 358 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 359 | CLANG_WARN_EMPTY_BODY = YES; 360 | CLANG_WARN_ENUM_CONVERSION = YES; 361 | CLANG_WARN_INFINITE_RECURSION = YES; 362 | CLANG_WARN_INT_CONVERSION = YES; 363 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 364 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 365 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 366 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 367 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 368 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 369 | CLANG_WARN_STRICT_PROTOTYPES = YES; 370 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 371 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 372 | CLANG_WARN_UNREACHABLE_CODE = YES; 373 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 374 | COPY_PHASE_STRIP = NO; 375 | DEBUG_INFORMATION_FORMAT = dwarf; 376 | ENABLE_STRICT_OBJC_MSGSEND = YES; 377 | ENABLE_TESTABILITY = YES; 378 | GCC_C_LANGUAGE_STANDARD = gnu11; 379 | GCC_DYNAMIC_NO_PIC = NO; 380 | GCC_NO_COMMON_BLOCKS = YES; 381 | GCC_OPTIMIZATION_LEVEL = 0; 382 | GCC_PREPROCESSOR_DEFINITIONS = ( 383 | "DEBUG=1", 384 | "$(inherited)", 385 | ); 386 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 387 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 388 | GCC_WARN_UNDECLARED_SELECTOR = YES; 389 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 390 | GCC_WARN_UNUSED_FUNCTION = YES; 391 | GCC_WARN_UNUSED_VARIABLE = YES; 392 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 393 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 394 | MTL_FAST_MATH = YES; 395 | ONLY_ACTIVE_ARCH = YES; 396 | SDKROOT = iphoneos; 397 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 398 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 399 | }; 400 | name = Debug; 401 | }; 402 | F43BB11126EFAA230098D42C /* Release */ = { 403 | isa = XCBuildConfiguration; 404 | buildSettings = { 405 | ALWAYS_SEARCH_USER_PATHS = NO; 406 | CLANG_ANALYZER_NONNULL = YES; 407 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 408 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 409 | CLANG_CXX_LIBRARY = "libc++"; 410 | CLANG_ENABLE_MODULES = YES; 411 | CLANG_ENABLE_OBJC_ARC = YES; 412 | CLANG_ENABLE_OBJC_WEAK = YES; 413 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 414 | CLANG_WARN_BOOL_CONVERSION = YES; 415 | CLANG_WARN_COMMA = YES; 416 | CLANG_WARN_CONSTANT_CONVERSION = YES; 417 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 418 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 419 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 420 | CLANG_WARN_EMPTY_BODY = YES; 421 | CLANG_WARN_ENUM_CONVERSION = YES; 422 | CLANG_WARN_INFINITE_RECURSION = YES; 423 | CLANG_WARN_INT_CONVERSION = YES; 424 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 425 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 426 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 427 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 428 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 429 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 430 | CLANG_WARN_STRICT_PROTOTYPES = YES; 431 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 432 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 433 | CLANG_WARN_UNREACHABLE_CODE = YES; 434 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 435 | COPY_PHASE_STRIP = NO; 436 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 437 | ENABLE_NS_ASSERTIONS = NO; 438 | ENABLE_STRICT_OBJC_MSGSEND = YES; 439 | GCC_C_LANGUAGE_STANDARD = gnu11; 440 | GCC_NO_COMMON_BLOCKS = YES; 441 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 442 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 443 | GCC_WARN_UNDECLARED_SELECTOR = YES; 444 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 445 | GCC_WARN_UNUSED_FUNCTION = YES; 446 | GCC_WARN_UNUSED_VARIABLE = YES; 447 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 448 | MTL_ENABLE_DEBUG_INFO = NO; 449 | MTL_FAST_MATH = YES; 450 | SDKROOT = iphoneos; 451 | SWIFT_COMPILATION_MODE = wholemodule; 452 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 453 | VALIDATE_PRODUCT = YES; 454 | }; 455 | name = Release; 456 | }; 457 | F43BB11326EFAA230098D42C /* Debug */ = { 458 | isa = XCBuildConfiguration; 459 | buildSettings = { 460 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 461 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 462 | CODE_SIGN_STYLE = Automatic; 463 | DEVELOPMENT_ASSET_PATHS = "\"SwiftBeta-Curso-SwiftUI-Introduccion/Preview Content\""; 464 | ENABLE_PREVIEWS = YES; 465 | INFOPLIST_FILE = "SwiftBeta-Curso-SwiftUI-Introduccion/Info.plist"; 466 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 467 | LD_RUNPATH_SEARCH_PATHS = ( 468 | "$(inherited)", 469 | "@executable_path/Frameworks", 470 | ); 471 | PRODUCT_BUNDLE_IDENTIFIER = "com.swiftbeta.SwiftBeta-Curso-SwiftUI-Introduccion"; 472 | PRODUCT_NAME = "$(TARGET_NAME)"; 473 | SWIFT_VERSION = 5.0; 474 | TARGETED_DEVICE_FAMILY = "1,2"; 475 | }; 476 | name = Debug; 477 | }; 478 | F43BB11426EFAA230098D42C /* Release */ = { 479 | isa = XCBuildConfiguration; 480 | buildSettings = { 481 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 482 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 483 | CODE_SIGN_STYLE = Automatic; 484 | DEVELOPMENT_ASSET_PATHS = "\"SwiftBeta-Curso-SwiftUI-Introduccion/Preview Content\""; 485 | ENABLE_PREVIEWS = YES; 486 | INFOPLIST_FILE = "SwiftBeta-Curso-SwiftUI-Introduccion/Info.plist"; 487 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 488 | LD_RUNPATH_SEARCH_PATHS = ( 489 | "$(inherited)", 490 | "@executable_path/Frameworks", 491 | ); 492 | PRODUCT_BUNDLE_IDENTIFIER = "com.swiftbeta.SwiftBeta-Curso-SwiftUI-Introduccion"; 493 | PRODUCT_NAME = "$(TARGET_NAME)"; 494 | SWIFT_VERSION = 5.0; 495 | TARGETED_DEVICE_FAMILY = "1,2"; 496 | }; 497 | name = Release; 498 | }; 499 | /* End XCBuildConfiguration section */ 500 | 501 | /* Begin XCConfigurationList section */ 502 | F43BB0FE26EFAA220098D42C /* Build configuration list for PBXProject "SwiftBeta-Curso-SwiftUI-Introduccion" */ = { 503 | isa = XCConfigurationList; 504 | buildConfigurations = ( 505 | F43BB11026EFAA230098D42C /* Debug */, 506 | F43BB11126EFAA230098D42C /* Release */, 507 | ); 508 | defaultConfigurationIsVisible = 0; 509 | defaultConfigurationName = Release; 510 | }; 511 | F43BB11226EFAA230098D42C /* Build configuration list for PBXNativeTarget "SwiftBeta-Curso-SwiftUI-Introduccion" */ = { 512 | isa = XCConfigurationList; 513 | buildConfigurations = ( 514 | F43BB11326EFAA230098D42C /* Debug */, 515 | F43BB11426EFAA230098D42C /* Release */, 516 | ); 517 | defaultConfigurationIsVisible = 0; 518 | defaultConfigurationName = Release; 519 | }; 520 | /* End XCConfigurationList section */ 521 | }; 522 | rootObject = F43BB0FB26EFAA220098D42C /* Project object */; 523 | } 524 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftBeta/Curso-SwiftUI-Introduccion/2756487a7734f410dcdc30691283de3fd4adb398/SwiftBeta-Curso-SwiftUI-Introduccion/.DS_Store -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Assets.xcassets/youtube.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "youtube.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Assets.xcassets/youtube.imageset/youtube.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftBeta/Curso-SwiftUI-Introduccion/2756487a7734f410dcdc30691283de3fd4adb398/SwiftBeta-Curso-SwiftUI-Introduccion/Assets.xcassets/youtube.imageset/youtube.pdf -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationView { 13 | Form { 14 | Section(header: Text("Aquí tienes todo el código del curso gratuito Swift Introducción de SwiftBeta")) { 15 | Group { 16 | NavigationLink("1. Introducción", 17 | destination: Text("1")) 18 | NavigationLink("2. Stacks", 19 | destination: StacksView() 20 | .navigationTitle("Stacks")) 21 | NavigationLink("3. Image", 22 | destination: ImageView() 23 | .navigationTitle("Image")) 24 | NavigationLink("4. Iconos y SF Symbols", 25 | destination: IconsAndSymbols() 26 | .navigationTitle("Icons & SF Symbols")) 27 | NavigationLink("5. @State", 28 | destination: PropertyWrapperState() 29 | .navigationTitle("@State")) 30 | NavigationLink("6. Label", 31 | destination: LabelView() 32 | .navigationTitle("Label")) 33 | NavigationLink("7. Text", 34 | destination: TextView() 35 | .navigationTitle("Text")) 36 | NavigationLink("8. Button", 37 | destination: ButtonView() 38 | .navigationTitle("Button")) 39 | NavigationLink("9. TextField", 40 | destination: TextFieldView() 41 | .navigationTitle("TextField")) 42 | NavigationLink("10. TextEditor", 43 | destination: TextEditorView() 44 | .navigationTitle("TextEditor")) 45 | } 46 | Group { 47 | NavigationLink("11. DatePicker", 48 | destination: DatePickerView() 49 | .navigationTitle("DatePicker")) 50 | NavigationLink("12. ColorPicker", 51 | destination: ColorPickerView() 52 | .navigationTitle("ColorPicker")) 53 | NavigationLink("13. ProgressView", 54 | destination: ProgressViewView() 55 | .navigationTitle("ProgressView")) 56 | NavigationLink("14. Link", 57 | destination: LinkView() 58 | .navigationTitle("Link")) 59 | NavigationLink("15. Toogle", 60 | destination: ToggleView() 61 | .navigationTitle("Toggle")) 62 | NavigationLink("16. Stepper", 63 | destination: StepperView() 64 | .navigationTitle("Stepper")) 65 | NavigationLink("17. Slider", 66 | destination: SliderView() 67 | .navigationTitle("Slider")) 68 | NavigationLink("18. LazyVGrid y LazyHGrid", 69 | destination: LazyVGrid_LazyHGridView() 70 | .navigationTitle("LazyVGrid y LazyHGrid")) 71 | NavigationLink("19. Form", 72 | destination: FormView() 73 | .navigationTitle("Form")) 74 | NavigationLink("20. List", 75 | destination: ListView() 76 | .navigationTitle("List")) 77 | } 78 | Group { 79 | NavigationLink("21. NavigationView y NavigationLink", 80 | destination: NavigationView_NavigationLink() 81 | .navigationTitle("NavigationView")) 82 | NavigationLink("22. TabView", 83 | destination: Tab_View() 84 | .navigationTitle("TabView")) 85 | NavigationLink("23. fullScreenCover & sheet", 86 | destination: fullScreenCover_sheet() 87 | .navigationTitle("fullScreenCover & sheet")) 88 | NavigationLink("24. Alert", 89 | destination: AlertView() 90 | .navigationTitle("Alert")) 91 | NavigationLink("25. ActionSheet", 92 | destination: ActionSheetView() 93 | .navigationTitle("ActionSheet")) 94 | NavigationLink("26. contextMenu", 95 | destination: ContextMenuView() 96 | .navigationTitle("contextMenu")) 97 | NavigationLink("27. TapGesture", 98 | destination: Tap_Gesture() 99 | .navigationTitle("TapGesture")) 100 | NavigationLink("28. DragGesture", 101 | destination: Drag_Gesture() 102 | .navigationTitle("DragGesture")) 103 | NavigationLink("29. @State vs @Binding", 104 | destination: StateVsBinding() 105 | .navigationTitle("@State Vs @Binding")) 106 | NavigationLink("30. @ObservedObject vs @StateObject", 107 | destination: ObservedObjectVsStateObject() 108 | .navigationTitle("@ObservedObject Vs @StateObject")) 109 | } 110 | Group { 111 | NavigationLink("31. @EnvironmentObject", 112 | destination: PropertyWrapperEnvironmentObject() 113 | .navigationTitle("@EnvironmentObject")) 114 | NavigationLink("32. @AppStorage", 115 | destination: PropertyWrapperAppStorage() 116 | .navigationTitle("@AppStorage")) 117 | NavigationLink("33. @SceneStorage", 118 | destination: PropertyWrapperSceneStorage() 119 | .navigationTitle("@SceneStorage")) 120 | NavigationLink("34. AsyncImage", 121 | destination: AsyncImageView() 122 | .navigationTitle("AsyncImage")) 123 | NavigationLink("35. swipeActions y refreshable", 124 | destination: swipeActionsAndRefreshable() 125 | .navigationTitle("swipeActions & refreshable")) 126 | NavigationLink("36. GeometryReader", 127 | destination: GeometryReaderView() 128 | .navigationTitle("GeometryReader")) 129 | NavigationLink("37. ViewModifier", 130 | destination: View_Modifier() 131 | .navigationTitle("ViewModifier")) 132 | NavigationLink("38. @PreferenceKey", 133 | destination: PropertyWrapperPreferenceKey() 134 | .navigationTitle("@PreferenceKey")) 135 | NavigationLink("39. SwiftUI Redux desde cero", 136 | destination: ReduxView() 137 | .navigationTitle("Arquitectura REDUX")) 138 | NavigationLink("40. SwiftUI Crear la app calculadora", 139 | destination: CalculadoraView() 140 | .navigationTitle("Calculadora en SWIFTUI")) 141 | } 142 | } 143 | } 144 | .navigationTitle("Swift Introducción") 145 | } 146 | } 147 | } 148 | 149 | struct ContentView_Previews: PreviewProvider { 150 | static var previews: some View { 151 | ContentView() 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/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 | 28 | UIApplicationSupportsIndirectInputEvents 29 | 30 | UILaunchScreen 31 | 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftBeta_Curso_SwiftUI_IntroduccionApp.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct SwiftBeta_Curso_SwiftUI_IntroduccionApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/10-TextEditorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextEditorView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TextEditorView: View { 11 | @State var text = "Escribe algo..." 12 | @State var counter = 0 13 | 14 | var body: some View { 15 | VStack { 16 | TextEditor(text: $text) 17 | .font(.title) 18 | .autocapitalization(.none) 19 | .disableAutocorrection(true) 20 | .foregroundColor(.blue) 21 | .padding() 22 | .onChange(of: text, perform: { value in 23 | counter = value.count 24 | }) 25 | Text("\(counter)") 26 | .foregroundColor(counter <= 280 ? .green : .red) 27 | .font(.largeTitle) 28 | } 29 | } 30 | } 31 | 32 | struct TextEditorView_Previews: PreviewProvider { 33 | static var previews: some View { 34 | TextEditorView() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/11-DatePickerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DatePickerView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct DatePickerView: View { 11 | @State var currentDate: Date = Date() 12 | 13 | var body: some View { 14 | Form { 15 | DatePicker("Fecha", 16 | selection: $currentDate) 17 | Text(currentDate, style: .date) 18 | .bold() 19 | } 20 | } 21 | } 22 | 23 | struct DatePickerView_Previews: PreviewProvider { 24 | static var previews: some View { 25 | DatePickerView() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/12-ColorPickerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorPickerView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ColorPickerView: View { 11 | @State var color: Color = .blue 12 | 13 | var body: some View { 14 | VStack { 15 | Rectangle() 16 | .foregroundColor(color) 17 | .frame(width: 300, height: 60) 18 | ColorPicker("Selecciona un Color", 19 | selection: $color) 20 | Spacer() 21 | }.padding(60) 22 | } 23 | } 24 | 25 | struct ColorPickerView_Previews: PreviewProvider { 26 | static var previews: some View { 27 | ColorPickerView() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/13-ProgressViewView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 13-ProgressViewView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ProgressViewView: View { 11 | @State var isLoading: Bool = false 12 | @State private var progress = 0.8 13 | 14 | var body: some View { 15 | VStack { 16 | ProgressView() 17 | .progressViewStyle(CircularProgressViewStyle(tint: .blue)) 18 | .scaleEffect(8) 19 | .padding(.top, 40) 20 | .padding(.bottom, 94) 21 | 22 | HStack { 23 | Text("0%") 24 | .bold() 25 | ProgressView(value: progress) 26 | .padding(.horizontal, 30) 27 | .padding(.bottom, 20) 28 | Text("100%") 29 | .bold() 30 | }.padding(.horizontal) 31 | HStack { 32 | Text("0%") 33 | .bold() 34 | ProgressView("Progreso", value: 0.5) 35 | .accentColor(.green) 36 | .padding(.horizontal, 30) 37 | .padding(.bottom, 20) 38 | Text("100%") 39 | .bold() 40 | }.padding(.horizontal) 41 | HStack { 42 | Text("0%") 43 | .bold() 44 | ProgressView("Progreso", value: 0.1) 45 | .accentColor(.red) 46 | .padding(.horizontal, 30) 47 | .padding(.bottom, 20) 48 | Text("100%") 49 | .bold() 50 | }.padding(.horizontal) 51 | Spacer() 52 | }.padding(.top, 32) 53 | } 54 | } 55 | 56 | struct ProgressViewView_Previews: PreviewProvider { 57 | static var previews: some View { 58 | ProgressViewView() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/14-LinkView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LinkView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct LinkView: View { 11 | var body: some View { 12 | Link(destination: URL(string: "https://www.swiftbeta.com")!, label: { 13 | Label("Aprende SwiftUI", systemImage: "swift") 14 | .font(.title) 15 | .foregroundColor(.white) 16 | .padding() 17 | .background(Color.blue) 18 | .cornerRadius(12) 19 | }) 20 | } 21 | } 22 | 23 | struct LinkView_Previews: PreviewProvider { 24 | static var previews: some View { 25 | LinkView() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/15-ToggleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ToggleView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ToggleView: View { 11 | @State var isOn: Bool = false 12 | 13 | var body: some View { 14 | Form { 15 | Toggle("Suscríbete a SwiftBeta", 16 | isOn: $isOn) 17 | HStack { 18 | Spacer() 19 | Text("\(isOn.description)".uppercased()) 20 | .foregroundColor(isOn ? .green : .black) 21 | .bold() 22 | .underline() 23 | } 24 | Section(header: Text("Quieres Aprender:")) { 25 | Toggle("SWIFTUI", 26 | isOn: $isOn) 27 | Toggle("SWIFT", 28 | isOn: $isOn) 29 | Toggle("XCODE", 30 | isOn: $isOn) 31 | } 32 | } 33 | } 34 | } 35 | 36 | struct ToggleView_Previews: PreviewProvider { 37 | static var previews: some View { 38 | ToggleView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/16-StepperView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StepperView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct StepperView: View { 11 | @State var iPhoneCounter: Int = 1 12 | @State var macCounter: Int = 1 13 | 14 | var body: some View { 15 | NavigationView { 16 | Form { 17 | Section(header: Text("Sección iPhone")) { 18 | Stepper("iPhone \(iPhoneCounter)") { 19 | iPhoneCounter += 1 20 | print("[Incrementar] Número \(iPhoneCounter)") 21 | } onDecrement: { 22 | iPhoneCounter -= 1 23 | print("[Decrementar] Número \(iPhoneCounter)") 24 | } 25 | } 26 | Section(header: Text("Sección Mac")) { 27 | Stepper("Mac \(macCounter)") { 28 | macCounter += 1 29 | print("[Incrementar] Número \(macCounter)") 30 | } onDecrement: { 31 | macCounter -= 1 32 | print("[Decrementar] Número \(macCounter)") 33 | } 34 | } 35 | HStack { 36 | Spacer() 37 | Button(action: {}, label: { 38 | Text("Comprar") 39 | .foregroundColor(.blue) 40 | }) 41 | } 42 | }.navigationTitle("Lista de la compra") 43 | } 44 | } 45 | } 46 | 47 | struct StepperView_Previews: PreviewProvider { 48 | static var previews: some View { 49 | StepperView() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/17-SliderView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct SliderView: View { 4 | @State var iPhoneCounter: Int = 1 5 | 6 | var body: some View { 7 | Form { 8 | Stepper("iPhone: \(iPhoneCounter)", 9 | value: $iPhoneCounter, 10 | in: 1...5) 11 | } 12 | } 13 | } 14 | 15 | struct SliderView_Previews: PreviewProvider { 16 | static var previews: some View { 17 | SliderView() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/19-FormView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct FormView: View { 4 | @State var deviceName: String = "iPhone 12 Pro Max" 5 | @State var isNetworkOn: Bool = true 6 | @State var date: Date = Date() 7 | @State var color: Color = .blue 8 | 9 | var body: some View { 10 | NavigationView { 11 | Form { 12 | Section(header: Text("Settings")) { 13 | TextField("Device Name", text: $deviceName) 14 | Toggle("Wi-Fi", isOn: $isNetworkOn) 15 | } 16 | 17 | Section(header: Text("Account"), 18 | footer: 19 | HStack { 20 | Spacer() 21 | Label("version 1.0", systemImage: "iphone") 22 | Spacer() 23 | } 24 | ) { 25 | DatePicker("Date", selection: $date) 26 | ColorPicker("Color", selection: $color) 27 | } 28 | }.navigationTitle("Form") 29 | } 30 | } 31 | } 32 | 33 | struct FormView_Previews: PreviewProvider { 34 | static var previews: some View { 35 | FormView() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/2-StacksView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 2-StacksView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct StacksView: View { 11 | var body: some View { 12 | List { 13 | VStack { 14 | VStack(alignment: .leading, spacing: 8) { 15 | Text("Siguiendo") 16 | .font(.largeTitle) 17 | .bold() 18 | Text("CANALES RECOMENDADOS") 19 | .foregroundColor(.gray) 20 | HStack { 21 | Rectangle() 22 | .foregroundColor(.blue) 23 | .frame(width: 118, height: 68) 24 | VStack(alignment: .leading) { 25 | HStack { 26 | Circle() 27 | .foregroundColor(.blue) 28 | .frame(width: 18, height: 18) 29 | Text("username") 30 | .font(.headline) 31 | } 32 | Text("streaming de programación...") 33 | .foregroundColor(.gray) 34 | Text("Solo Hablando") 35 | .foregroundColor(.gray) 36 | } 37 | } 38 | } 39 | ZStack() { 40 | VStack(alignment: .leading, spacing: 8) { 41 | Text("Siguiendo") 42 | .font(.largeTitle) 43 | .bold() 44 | Text("CANALES RECOMENDADOS") 45 | .foregroundColor(.gray) 46 | HStack { 47 | Rectangle() 48 | .foregroundColor(/*@START_MENU_TOKEN@*/.blue/*@END_MENU_TOKEN@*/) 49 | .frame(width: 118, height: 68) 50 | VStack(alignment: .leading) { 51 | HStack { 52 | Circle() 53 | .foregroundColor(.blue) 54 | .frame(width: 18, height: 18) 55 | Text("username") 56 | .font(.headline) 57 | } 58 | Text("streaming de programación...") 59 | .foregroundColor(.gray) 60 | Text("Solo Hablando") 61 | .foregroundColor(.gray) 62 | } 63 | } 64 | } 65 | Text("Suscribiros a SwiftBeta") 66 | .font(.largeTitle) 67 | .bold() 68 | .foregroundColor(.red) 69 | .underline() 70 | .background(Color.black) 71 | .rotationEffect(.degrees(-20)) 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | struct StacksView_Previews: PreviewProvider { 79 | static var previews: some View { 80 | ContentView() 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/20-ListView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListView.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Device { 11 | let title: String 12 | let imageName: String 13 | } 14 | 15 | let house = [ 16 | Device(title: "Laptop", imageName: "laptopcomputer"), 17 | Device(title: "Mac mini", imageName: "macmini"), 18 | Device(title: "Mac Pro", imageName: "macpro.gen3"), 19 | Device(title: "Pantallas", imageName: "display.2"), 20 | Device(title: "Apple TV", imageName: "appletv") 21 | ] 22 | 23 | let work = [ 24 | Device(title: "iPhone", imageName: "iphone"), 25 | Device(title: "iPad", imageName: "ipad"), 26 | Device(title: "Airpods", imageName: "airpods"), 27 | Device(title: "Apple Watch", imageName: "applewatch") 28 | ] 29 | 30 | struct ListView: View { 31 | var body: some View { 32 | List { 33 | Section(header: Text("Home")) { 34 | ForEach(house, id: \.title) { option in 35 | Label(option.title, systemImage: option.imageName) 36 | } 37 | } 38 | Section(header: Text("Work")) { 39 | ForEach(work, id: \.title) { option in 40 | Label(option.title, systemImage: option.imageName) 41 | } 42 | } 43 | } 44 | .listStyle(GroupedListStyle()) 45 | } 46 | } 47 | 48 | struct ListView_Previews: PreviewProvider { 49 | static var previews: some View { 50 | ListView() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/21-NavigationView_NavigationLink.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationView_NavigationLink.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct NavigationView_NavigationLink: View { 11 | var body: some View { 12 | NavigationView { 13 | List { 14 | NavigationLink("Option Menu 1", 15 | destination: Text("Some information")) 16 | NavigationLink("Option Menu 2", 17 | destination: Button("Tap me!", action: { 18 | print("Hello iOS Developer") 19 | })) 20 | Text("Option Menu 3") 21 | Text("Option Menu 4") 22 | } 23 | .navigationBarItems(trailing: Button("Done", action: { 24 | print("NavigationView Button") 25 | })) 26 | .navigationTitle("Menu") 27 | .navigationBarTitleDisplayMode(.large) 28 | .navigationBarHidden(false) 29 | } 30 | } 31 | } 32 | 33 | struct NavigationView_NavigationLink_Previews: PreviewProvider { 34 | static var previews: some View { 35 | NavigationView_NavigationLink() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/22-TabView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabView.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Tab_View: View { 11 | var body: some View { 12 | TabView { 13 | HomeView() 14 | .tabItem { 15 | Image(systemName: "house.fill") 16 | Text("1") 17 | } 18 | ProfileView() 19 | .tabItem { 20 | Image(systemName: "person.crop.circle.fill") 21 | Text("2") 22 | } 23 | View3() 24 | .tabItem { 25 | Image(systemName: "message.fill") 26 | Text("3") 27 | } 28 | }.accentColor(.blue) 29 | } 30 | } 31 | 32 | struct HomeView: View { 33 | var body: some View { 34 | ZStack { 35 | Color.clear 36 | Text("View 1") 37 | .font(.largeTitle) 38 | .padding(.top, -20) 39 | } 40 | .edgesIgnoringSafeArea(.all) 41 | } 42 | } 43 | 44 | struct ProfileView: View { 45 | var body: some View { 46 | ZStack { 47 | Color.blue 48 | Text("View 2") 49 | .font(.largeTitle) 50 | .padding(.top, -20) 51 | } 52 | .edgesIgnoringSafeArea(.all) 53 | } 54 | } 55 | 56 | struct View3: View { 57 | var body: some View { 58 | ZStack { 59 | Color.green 60 | Text("View 3") 61 | .font(.largeTitle) 62 | .padding(.top, -20) 63 | } 64 | .edgesIgnoringSafeArea(.all) 65 | } 66 | } 67 | 68 | struct Tab_View_Previews: PreviewProvider { 69 | static var previews: some View { 70 | Tab_View() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/23-fullScreenCover_sheet.swift: -------------------------------------------------------------------------------- 1 | // 2 | // fullScreenCover_sheet.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct fullScreenCover_sheet: View { 11 | @State var isPresented: Bool = false 12 | 13 | var body: some View { 14 | VStack { 15 | Image("swiftui") 16 | .resizable() 17 | .scaledToFit() 18 | .frame(height: 200) 19 | Text("¡Suscríbete a SwiftBeta!") 20 | .bold() 21 | .font(.largeTitle) 22 | .padding(.horizontal, 16) 23 | .multilineTextAlignment(.center) 24 | Text("para aprender SwiftUI, Swift y Xcode") 25 | .font(.body) 26 | .padding(.vertical, 12) 27 | Button(action: { isPresented = true }, label: { 28 | Text("Suscribir") 29 | .bold() 30 | .foregroundColor(.white) 31 | .padding(12) 32 | .background(Color.blue) 33 | .cornerRadius(12) 34 | 35 | }) 36 | } 37 | .padding(.bottom, 300) 38 | .fullScreenCover(isPresented: $isPresented, 39 | onDismiss: { isPresented = false }, 40 | content: { 41 | ZStack { 42 | Color.blue.ignoresSafeArea() 43 | Image("swiftbeta") 44 | .cornerRadius(50) 45 | .overlay(RoundedRectangle(cornerRadius: 50) 46 | .stroke(Color.white, lineWidth: 4)) 47 | .padding(.top, -380) 48 | Button(action: { isPresented = false }, label: { 49 | Text("¡Bienvenido a\n SwiftBeta! 🎉") 50 | .bold() 51 | .font(.largeTitle) 52 | .foregroundColor(.white) 53 | .padding(12) 54 | .background(Color.blue) 55 | .cornerRadius(12) 56 | 57 | }) 58 | .padding(.top, -270) 59 | } 60 | .onAppear { 61 | print("¡Suscríbete a SwiftBeta!") 62 | } 63 | }) 64 | } 65 | } 66 | 67 | struct fullScreenCover_sheet_Previews: PreviewProvider { 68 | static var previews: some View { 69 | fullScreenCover_sheet() 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/24-AlertView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertView.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AlertView: View { 11 | @State var isPresented: Bool = false 12 | @State var alertMessage: String = "Hola" 13 | 14 | var body: some View { 15 | VStack { 16 | Text("Suscríbete a SwiftBeta") 17 | .padding() 18 | Button("Aceptar") { 19 | isPresented = true 20 | DispatchQueue.main.asyncAfter(deadline: .now() + 2) { 21 | isPresented = false 22 | } 23 | } 24 | } 25 | .alert(isPresented: $isPresented, content: { 26 | Alert(title: Text($alertMessage.wrappedValue), 27 | message: Text("Cada semana sacamos nuevo video"), 28 | primaryButton: .default(Text("Aceptar"), 29 | action: { 30 | print("Button tapped") 31 | }), 32 | secondaryButton: .destructive(Text("Cancelar"))) 33 | }) 34 | } 35 | } 36 | 37 | struct AlertView_Previews: PreviewProvider { 38 | static var previews: some View { 39 | AlertView() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/25-ActionSheetView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionSheet.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ActionSheetView: View { 11 | @State var isPresented: Bool = false 12 | 13 | var body: some View { 14 | VStack { 15 | Text("Suscríbete a SwiftBeta") 16 | .padding() 17 | Button("Aceptar") { 18 | isPresented = true 19 | } 20 | } 21 | .actionSheet(isPresented: $isPresented, content: { 22 | ActionSheet(title: Text("Aprende SwiftUI con SwiftBeta"), 23 | message: Text("Elige la opción que quieras:"), 24 | buttons: [.default(Text("SwiftUI"), 25 | action: { 26 | print("Aprende SwiftUI") 27 | }), 28 | .default(Text("Xcode")), 29 | .destructive(Text("Cancelar"))]) 30 | }) 31 | } 32 | } 33 | 34 | struct ActionSheetView_Previews: PreviewProvider { 35 | static var previews: some View { 36 | ActionSheetView() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/26-ContextMenuView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContextMenuView.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContextMenuView: View { 11 | var body: some View { 12 | Text("Aprende con SwiftBeta") 13 | .padding() 14 | .contextMenu( 15 | ContextMenu(menuItems: { 16 | Button("SwiftUI") { 17 | print("Quiero Aprender SwiftUI") 18 | } 19 | Button("Xcode") { 20 | print("Quiero Aprender Xcode") 21 | } 22 | Button(action: { 23 | print("Quiero Aprender Swift") 24 | }, label: { 25 | Label("Swift", systemImage: "iphone") 26 | }) 27 | Button("Tips de Programación") { 28 | print("Quiero Aprender SwiftUI") 29 | } 30 | })).offset(y: -300) 31 | } 32 | } 33 | 34 | struct ContextMenuView_Previews: PreviewProvider { 35 | static var previews: some View { 36 | ContextMenuView() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/27-Tap_Gesture.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tap_Gesture.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Tap_Gesture: View { 11 | @State var count: Int = 0 12 | 13 | var body: some View { 14 | VStack { 15 | RoundedRectangle(cornerRadius: 20) 16 | .frame(width: 100, height: 100) 17 | .onTapGesture(count: 1) { 18 | print("View tapped") 19 | count += 1 20 | } 21 | Text("Número de taps") 22 | .bold() 23 | .font(.largeTitle) 24 | .padding(.top, 20) 25 | Text("\(count)") 26 | .underline() 27 | .bold() 28 | .foregroundColor(.green) 29 | .padding(.top, 12) 30 | .font(.system(size: 60)) 31 | }.offset(y: -250) 32 | 33 | } 34 | } 35 | 36 | struct Tap_Gesture_Previews: PreviewProvider { 37 | static var previews: some View { 38 | Tap_Gesture() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/28-Drag_Gesture.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Drag_Gesture.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Drag_Gesture: View { 11 | @State var dragOffset: CGSize = .zero 12 | 13 | var body: some View { 14 | RoundedRectangle(cornerRadius: 20) 15 | .frame(width: 100, height: 100) 16 | .offset(x: dragOffset.width, y: dragOffset.height) 17 | .gesture( 18 | DragGesture() 19 | .onChanged({ value in 20 | dragOffset = value.translation 21 | }) 22 | .onEnded({ _ in 23 | withAnimation(.spring()) { 24 | dragOffset = .zero 25 | } 26 | }) 27 | ) 28 | } 29 | } 30 | 31 | struct Drag_Gesture_Previews: PreviewProvider { 32 | static var previews: some View { 33 | Drag_Gesture() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/29-StateVsBinding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateVsBinding.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct StateVsBinding: View { 11 | @State var counter: Int = 0 12 | 13 | var body: some View { 14 | CounterView(counter: $counter) 15 | } 16 | } 17 | 18 | struct CounterView: View { 19 | @Binding var counter: Int 20 | 21 | var body: some View { 22 | VStack(spacing: 20) { 23 | Text("\(counter)") 24 | .font(.largeTitle) 25 | Button("Incrementar") { 26 | counter += 1 27 | } 28 | } 29 | } 30 | } 31 | 32 | struct StateVsBinding_Previews: PreviewProvider { 33 | static var previews: some View { 34 | StateVsBinding() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/3-Image.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct ImageView: View { 4 | var body: some View { 5 | Image("youtube") 6 | .resizable() 7 | .scaledToFit() 8 | .frame(width: 96, height: 68) 9 | } 10 | } 11 | 12 | struct ImageView_Previews: PreviewProvider { 13 | static var previews: some View { 14 | ImageView() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/30-ObservedObjectVsStateObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ObservedObjectVSStateObject.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ObservedObjectVsStateObject: View { 11 | @State private var counter: Int = 0 12 | 13 | var body: some View { 14 | VStack { 15 | Text("Contador: \(counter)") 16 | .bold() 17 | .font(.largeTitle) 18 | .padding() 19 | Button("Incrementar Contador") { 20 | counter += 1 21 | } 22 | ListVideos() 23 | Spacer() 24 | } 25 | } 26 | } 27 | 28 | struct ListVideos: View { 29 | @StateObject private var videoViewModel = VideoViewModel() 30 | 31 | var body: some View { 32 | NavigationView { 33 | List(videoViewModel.videosModel, id: \.self) { video in 34 | Text(video) 35 | } 36 | .navigationTitle("SwiftBeta Videos") 37 | .navigationBarItems(leading: 38 | Button("Añadir", action: videoViewModel.addMoreTopics) 39 | ) 40 | } 41 | } 42 | } 43 | 44 | struct RemoveVideos: View { 45 | @ObservedObject var videoViewModel: VideoViewModel 46 | 47 | var body: some View { 48 | Text("SwiftBeta Remove Video") 49 | } 50 | } 51 | 52 | final class VideoViewModel: ObservableObject { 53 | @Published var videosModel: [String] = [] 54 | 55 | init() { 56 | videosModel = ["Aprende SwiftUI", 57 | "Aprende Xcode", 58 | "Aprende Swift"] 59 | } 60 | 61 | func addMoreTopics() { 62 | videosModel.append("Aprende CI/CD") 63 | videosModel.append("Aprende Git") 64 | } 65 | } 66 | 67 | struct ObservedObjectVsStateObject_Previews: PreviewProvider { 68 | static var previews: some View { 69 | ObservedObjectVsStateObject() 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/31-PropertyWrapperEnvironmentObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PropertyWrapperEnvironmentObject.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | final class ViewModel: ObservableObject { 11 | @Published var counter: Int = 0 12 | } 13 | 14 | struct PropertyWrapperEnvironmentObject: View { 15 | @StateObject var viewModel = ViewModel() 16 | 17 | var body: some View { 18 | VStack { 19 | Text("Counter: \(viewModel.counter)") 20 | .bold() 21 | .font(.largeTitle) 22 | Text("View 1") 23 | .padding() 24 | PropertyWrapperEnvironmentObject_View2() 25 | } 26 | .environmentObject(viewModel) 27 | } 28 | } 29 | 30 | struct PropertyWrapperEnvironmentObject_View2: View { 31 | var body: some View { 32 | VStack { 33 | Text("View 2") 34 | .padding() 35 | PropertyWrapperEnvironmentObject_View3() 36 | } 37 | } 38 | } 39 | 40 | struct PropertyWrapperEnvironmentObject_View3: View { 41 | @EnvironmentObject var viewModel: ViewModel 42 | 43 | var body: some View { 44 | VStack { 45 | Text("View 3") 46 | .padding() 47 | Button("Incrementar") { 48 | viewModel.counter += 1 49 | } 50 | } 51 | } 52 | } 53 | 54 | struct PropertyWrapperEnvironmentObject_Previews: PreviewProvider { 55 | static var previews: some View { 56 | PropertyWrapperEnvironmentObject() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/32-PropertyWrapperAppStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 32-PropertyWrapperAppStorage.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PropertyWrapperAppStorage: View { 11 | @State var name: String = "" 12 | @AppStorage("appStorageName") var appStorageName: String = "" 13 | 14 | var body: some View { 15 | Form { 16 | TextField("Username", text: $name) 17 | HStack { 18 | Spacer() 19 | Button("Guardar") { 20 | // Si sabes que ese valor existe dentro de UserDefaults 21 | print(UserDefaults.standard.string(forKey: "appsStorageName")!) 22 | 23 | // Si no existe pero quieres retornar un valor por defecto 24 | print(UserDefaults.standard.string(forKey: "appsStorageName") ?? "") 25 | 26 | // Sacando el valor de un opcional con map 27 | UserDefaults.standard.string(forKey: "appsStorageName").map { print($0) } 28 | 29 | // usando if let 30 | if let appStorageName = UserDefaults.standard.string(forKey: "appsStorageName") { 31 | print(appStorageName) 32 | } 33 | 34 | // usando guard 35 | guard let appStorageName = UserDefaults.standard.string(forKey: "appsStorageName") else { 36 | return 37 | } 38 | print(appStorageName) 39 | } 40 | .padding() 41 | Spacer() 42 | } 43 | } 44 | .onAppear { 45 | name = appStorageName 46 | } 47 | } 48 | } 49 | 50 | struct PropertyWrapperAppStorage_Previews: PreviewProvider { 51 | static var previews: some View { 52 | PropertyWrapperAppStorage() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/33-PropertyWrapperSceneStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PropertyWrapperSceneStorage.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PropertyWrapperSceneStorage: View { 11 | @SceneStorage("tweet") private var tweet: String = "" 12 | @SceneStorage("toggle_publish_best_hour") private var togglePublishBestHour: Bool = false 13 | 14 | var body: some View { 15 | Form { 16 | TextEditor(text: $tweet) 17 | .frame(width: 300, height: 300) 18 | Toggle("Publicar a la mejor hora", isOn: $togglePublishBestHour) 19 | .padding() 20 | HStack { 21 | Spacer() 22 | Button(togglePublishBestHour ? "Publicar a la mejor hora 🍀" : "Publicar ahora 🐥") { 23 | print("Publicando...") 24 | } 25 | Spacer() 26 | } 27 | } 28 | } 29 | } 30 | 31 | struct PropertyWrapperSceneStorage_Previews: PreviewProvider { 32 | static var previews: some View { 33 | PropertyWrapperSceneStorage() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/34-AsyncImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AsyncImageView.swift 3 | // SwiftBeta-Curso-SwiftUI-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AsyncImageView: View { 11 | private let url = URL(string: "https://placebear.com/1000/1000") 12 | 13 | var body: some View { 14 | if #available(iOS 15.0, *) { 15 | AsyncImage(url: url!) { image in 16 | image 17 | .resizable() 18 | .scaledToFit() 19 | .cornerRadius(20) 20 | .padding() 21 | } placeholder: { 22 | ProgressView() 23 | } 24 | } else { 25 | // Fallback on earlier versions 26 | Text("AsyncImage needs iOS 15") 27 | } 28 | } 29 | } 30 | 31 | struct AsyncImageView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | AsyncImageView() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/35-swipeActionsAndRefreshable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // swipeActionsAndRefreshable.swift 3 | // swipeActionsAndRefreshable 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SwipeDevice { 11 | let name: String 12 | let systemImage: String 13 | } 14 | 15 | let arrayOfDevices = [ 16 | SwipeDevice(name: "iphone", systemImage: "iphone"), 17 | SwipeDevice(name: "ipad", systemImage: "ipad"), 18 | SwipeDevice(name: "pc", systemImage: "pc"), 19 | SwipeDevice(name: "4k", systemImage: "4k.tv"), 20 | SwipeDevice(name: "ipod", systemImage: "ipod"), 21 | SwipeDevice(name: "laptop", systemImage: "laptopcomputer") 22 | ] 23 | 24 | struct swipeActionsAndRefreshable: View { 25 | var body: some View { 26 | NavigationView { 27 | List { 28 | ForEach(arrayOfDevices, id: \.name) { device in 29 | Label(device.name, systemImage: device.systemImage) 30 | .swipeActions { 31 | Button { 32 | print("Favorito") 33 | } label: { 34 | Label("Favorito", systemImage: "star.fill") 35 | } 36 | .tint(.yellow) 37 | Button { 38 | print("Compartir") 39 | } label: { 40 | Label("Compartir", systemImage: "square.and.arrow.up") 41 | } 42 | .tint(.blue) 43 | } 44 | .swipeActions(edge: .leading) { 45 | Button { 46 | print("Borrar") 47 | } label: { 48 | Label("Borrar", systemImage: "trash.fill") 49 | } 50 | .tint(.red) 51 | } 52 | } 53 | } 54 | .refreshable { 55 | print("Recargar información...") 56 | } 57 | .navigationTitle("Devices") 58 | } 59 | } 60 | } 61 | 62 | struct swipeActionsAndRefreshable_Previews: PreviewProvider { 63 | static var previews: some View { 64 | swipeActionsAndRefreshable() 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/36-GeometryReaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GeometryReaderView.swift 3 | // GeometryReaderView 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | let arrayOfNames = [ 11 | "Suscríbete a SwiftBeta", 12 | "Aprende SwiftUI", 13 | "Aprende Swift", 14 | "Aprende Xcode", 15 | "Suscríbete al canal de Youtube", 16 | "SwiftUI", 17 | "Xcode", 18 | "Swift" 19 | ] 20 | 21 | struct GeometryReaderView: View { 22 | var body: some View { 23 | ScrollView(showsIndicators: false) { 24 | VStack { 25 | ForEach(arrayOfNames, id: \.self) { name in 26 | GeometryReader { proxy in 27 | VStack { 28 | Spacer() 29 | Text("\(name)") 30 | .font(.largeTitle) 31 | .bold() 32 | .frame(width: 370, height: 200) 33 | .background(Color.green) 34 | .cornerRadius(20) 35 | Spacer() 36 | } 37 | .shadow(color: .gray, radius: 10, x: 0, y: 0) 38 | .rotation3DEffect( 39 | Angle(degrees: Double(proxy.frame(in: .global).minY) - 47), 40 | axis: (x: 0.0, y: 10.0, z: 10.0) 41 | ) 42 | } 43 | .frame(width: 370, height: 300) 44 | } 45 | } 46 | .padding(.trailing) 47 | } 48 | .padding(.horizontal) 49 | } 50 | } 51 | 52 | struct GeometryReaderView_Previews: PreviewProvider { 53 | static var previews: some View { 54 | GeometryReaderView() 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/37-View_Modifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // View_Modifier.swift 3 | // View_Modifier 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct NewButtonModifier: ViewModifier { 11 | func body(content: Content) -> some View { 12 | content 13 | .font(.body) 14 | .foregroundColor(.white) 15 | .padding() 16 | .background(Color.blue) 17 | .cornerRadius(20) 18 | } 19 | } 20 | 21 | extension View { 22 | func newButtonModifier() -> some View { 23 | self.modifier(NewButtonModifier()) 24 | } 25 | } 26 | 27 | struct View_Modifier: View { 28 | var body: some View { 29 | VStack { 30 | Text("¡Suscríbete a SwiftBeta! 🎉") 31 | .bold() 32 | .padding() 33 | Button("Vale me suscribo!") { 34 | print("Suscribir canal de Youtube SwiftBeta") 35 | } 36 | .newButtonModifier() 37 | } 38 | } 39 | } 40 | 41 | struct View_Modifier_Previews: PreviewProvider { 42 | static var previews: some View { 43 | View_Modifier() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/38-PropertyWrapperPreferenceKey.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PropertyWrapperPreferenceKey.swift 3 | // PropertyWrapperPreferenceKey 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CustomNavigationView: View { 11 | 12 | @State private var title: String = "Navigation View" 13 | let content: Content 14 | 15 | init(@ViewBuilder content: () -> Content) { 16 | self.content = content() 17 | } 18 | 19 | var body: some View { 20 | VStack(alignment: .leading) { 21 | Text(title) 22 | .font(.largeTitle) 23 | .bold() 24 | GeometryReader { _ in 25 | ScrollView { 26 | content 27 | } 28 | } 29 | } 30 | .padding(.horizontal) 31 | .onPreferenceChange(CustomTitleKey.self) { (value: CustomTitleKey.Value) in 32 | print("Value \(value)") 33 | title = value 34 | } 35 | } 36 | } 37 | 38 | // Preference Key 39 | 40 | struct CustomTitleKey: PreferenceKey { 41 | static var defaultValue: String = "" 42 | 43 | static func reduce(value: inout String, nextValue: () -> String) { 44 | value = nextValue() 45 | } 46 | } 47 | 48 | struct PropertyWrapperPreferenceKey: View { 49 | var body: some View { 50 | CustomNavigationView { 51 | VStack { 52 | Text("Suscríbete a SwiftBeta 🚀") 53 | .padding() 54 | .preference(key: CustomTitleKey.self, value: "SwiftBeta 1") 55 | Text("Aprende SwiftUI 📚") 56 | .padding() 57 | .preference(key: CustomTitleKey.self, value: "SwiftBeta 2") 58 | } 59 | } 60 | } 61 | } 62 | 63 | // View Modifier 64 | 65 | struct CustomNavigationTitle: ViewModifier { 66 | 67 | private var title: String 68 | 69 | init(title: String) { 70 | self.title = title 71 | } 72 | 73 | func body(content: Content) -> some View { 74 | content 75 | .preference(key: CustomTitleKey.self, value: title) 76 | } 77 | } 78 | 79 | // Extensión 80 | 81 | extension View { 82 | func customNavigationTitle(title: String) -> some View { 83 | modifier(CustomNavigationTitle(title: title)) 84 | } 85 | } 86 | 87 | struct PropertyWrapperPreferenceKey_Previews: PreviewProvider { 88 | static var previews: some View { 89 | PropertyWrapperPreferenceKey() 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/39-ReduxView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReduxView.swift 3 | // ReduxView 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AppState { 11 | var names: [String] = ["Suscríbete a SwiftBeta", "Aprende SwiftUI"] 12 | } 13 | 14 | enum AppAction { 15 | case loadNames 16 | } 17 | 18 | func appReducer(action: AppAction, state: inout AppState) { 19 | switch action { 20 | case .loadNames: 21 | state.names.append(contentsOf: ["Aprende Swift", "Aprende Xcode"]) 22 | } 23 | } 24 | 25 | final class AppStore: ObservableObject { 26 | @Published private(set) var appState: AppState 27 | private let reducer: (AppAction, inout AppState) -> Void 28 | 29 | init(initialState: AppState, reducer: @escaping (AppAction, inout AppState) -> Void) { 30 | self.appState = initialState 31 | self.reducer = reducer 32 | } 33 | 34 | func reduce(action: AppAction) { 35 | reducer(action, &appState) 36 | } 37 | } 38 | 39 | 40 | struct ReduxView: View { 41 | @StateObject var store: AppStore = AppStore(initialState: AppState(), 42 | reducer: appReducer) 43 | 44 | var body: some View { 45 | NavigationView { 46 | List { 47 | ForEach(store.appState.names, id: \.self) { name in 48 | Text(name) 49 | } 50 | } 51 | .toolbar(content: { 52 | Button("tap me!") { 53 | store.reduce(action: .loadNames) 54 | } 55 | }) 56 | .navigationTitle("Names") 57 | } 58 | } 59 | } 60 | 61 | struct ReduxView_Previews: PreviewProvider { 62 | static var previews: some View { 63 | ReduxView() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/4-IconsAndSymbols.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IconsAndSymbols.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct IconsAndSymbols: View { 11 | var body: some View { 12 | Image(systemName: "moon.circle.fill") 13 | .renderingMode(.original) 14 | .resizable() 15 | .scaledToFit() 16 | .frame(height: 200) 17 | } 18 | } 19 | 20 | struct IconsAndSymbols_Previews: PreviewProvider { 21 | static var previews: some View { 22 | IconsAndSymbols() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/40-Calculadora/40-CalculadoraView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CalculadoraView.swift 3 | // CalculadoraView 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CalculadoraView: View { 11 | @StateObject var viewModel = CalculadoraViewModel() 12 | 13 | var body: some View { 14 | ZStack { 15 | Color.black.ignoresSafeArea() 16 | GeometryReader { proxy in 17 | VStack { 18 | VStack { 19 | Spacer() 20 | HStack { 21 | Spacer() 22 | Text(viewModel.textFieldValue) 23 | .foregroundColor(.white) 24 | .font(.system(size: 100, weight: .regular)) 25 | .frame(height: 100) 26 | .padding(.trailing, 20) 27 | } 28 | } 29 | VerticalButtonStack( 30 | viewModel: viewModel, 31 | data: Matrix.firstSectionData, 32 | columns: Matrix.firstSectionGrid(proxy.size.width * 0.25), 33 | width: proxy.size.width) 34 | VerticalButtonStack( 35 | viewModel: viewModel, 36 | data: Matrix.secondSectionData, 37 | columns: Matrix.secondSectionGrid(proxy.size.width * 0.25), 38 | width: proxy.size.width) 39 | } 40 | } 41 | .background(Color.black) 42 | } 43 | } 44 | } 45 | 46 | struct CalculadoraView_Previews: PreviewProvider { 47 | static var previews: some View { 48 | CalculadoraView() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/40-Calculadora/CalculadoraViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CalculadoraViewModel.swift 3 | // CalculadoraViewModel 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import Foundation 9 | 10 | final class CalculadoraViewModel: ObservableObject { 11 | @Published var textFieldValue: String = "0" 12 | 13 | var textFieldSavedValue: String = "0" 14 | var currentOperationToExecute: OperationType? 15 | var shouldRunOperation: Bool = false 16 | 17 | func logic(key: KeyboardButton) { 18 | switch key.type { 19 | case .number(let value): 20 | if shouldRunOperation { 21 | textFieldValue = "0" 22 | } 23 | textFieldValue = textFieldValue == "0" ? "\(value)" : textFieldValue + "\(value)" 24 | case .reset: 25 | textFieldValue = "0" 26 | textFieldSavedValue = "0" 27 | currentOperationToExecute = nil 28 | shouldRunOperation = false 29 | case .result: 30 | guard let operation = currentOperationToExecute else { 31 | return 32 | } 33 | 34 | switch operation { 35 | case .multiplication: 36 | textFieldValue = "\(Int(textFieldValue)! * Int(textFieldSavedValue)!)" 37 | case .sum: 38 | textFieldValue = "\(Int(textFieldValue)! + Int(textFieldSavedValue)!)" 39 | } 40 | case .operation(let type): 41 | textFieldSavedValue = textFieldValue 42 | currentOperationToExecute = type 43 | shouldRunOperation = true 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/40-Calculadora/Colors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Colors.swift 3 | // Colors 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | let customOrange = Color(red: 254/255, 12 | green: 159/255, 13 | blue: 6/255) 14 | 15 | let customLightGray = Color(red: 165/255, 16 | green: 165/255, 17 | blue: 165/255) 18 | 19 | let customDarkGray = Color(red: 52/255, 20 | green: 51/255, 21 | blue: 51/255) 22 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/40-Calculadora/Matrix.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Matrix.swift 3 | // Matrix 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import SwiftUI 11 | 12 | struct Matrix { 13 | static let firstSectionData: [KeyboardButton] = [ 14 | .init(title: "AC", textColor: .black, backgroundColor: customLightGray, isDoubleWidth: false, type: .reset), 15 | .init(title: "+/-", textColor: .black, backgroundColor: customLightGray, isDoubleWidth: false, type: .reset), 16 | .init(title: "%", textColor: .black, backgroundColor: customLightGray, isDoubleWidth: false, type: .reset), 17 | .init(title: "/", textColor: .white, backgroundColor: customOrange, isDoubleWidth: false, type: .reset), 18 | .init(title: "7", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(7)), 19 | .init(title: "8", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(8)), 20 | .init(title: "9", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(9)), 21 | .init(title: "X", textColor: .white, backgroundColor: customOrange, isDoubleWidth: false, type: .operation(.multiplication)), 22 | .init(title: "4", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(4)), 23 | .init(title: "5", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(5)), 24 | .init(title: "6", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(6)), 25 | .init(title: "-", textColor: .white, backgroundColor: customOrange, isDoubleWidth: false, type: .reset), 26 | .init(title: "1", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(1)), 27 | .init(title: "2", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(2)), 28 | .init(title: "3", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .number(3)), 29 | .init(title: "+", textColor: .white, backgroundColor: customOrange, isDoubleWidth: false, type: .operation(.sum)), 30 | ] 31 | 32 | static let secondSectionData: [KeyboardButton] = [ 33 | .init(title: "0", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: true, type: .number(0)), 34 | .init(title: ",", textColor: .white, backgroundColor: customDarkGray, isDoubleWidth: false, type: .reset), 35 | .init(title: "=", textColor: .white, backgroundColor: customOrange, isDoubleWidth: false, type: .result) 36 | ] 37 | 38 | static let firstSectionGrid: (CGFloat) -> [GridItem] = { width in 39 | return Array(repeating: GridItem(.flexible(minimum: width), spacing: 0), count: 4) 40 | } 41 | 42 | static let secondSectionGrid: (CGFloat) -> [GridItem] = { width in 43 | return [ 44 | GridItem(.flexible(minimum: width * 2), spacing: 0), 45 | GridItem(.flexible(minimum: width), spacing: 0), 46 | GridItem(.flexible(minimum: width), spacing: 0), 47 | ] 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/40-Calculadora/Model.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Model.swift 3 | // Model 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | struct KeyboardButton: Hashable { 12 | let title: String 13 | let textColor: Color 14 | let backgroundColor: Color 15 | let isDoubleWidth: Bool 16 | let type: ButtonType 17 | } 18 | 19 | enum ButtonType: Hashable { 20 | case number(Int) 21 | case operation(OperationType) 22 | case result 23 | case reset 24 | } 25 | 26 | enum OperationType: Hashable { 27 | case sum 28 | case multiplication 29 | } 30 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/40-Calculadora/VerticalButtonStack.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VerticalButtonStack.swift 3 | // VerticalButtonStack 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct VerticalButtonStack: View { 11 | 12 | @ObservedObject var viewModel: CalculadoraViewModel 13 | 14 | let data: [KeyboardButton] 15 | let columns: [GridItem] 16 | let width: CGFloat 17 | 18 | init( 19 | viewModel: CalculadoraViewModel, 20 | data: [KeyboardButton], 21 | columns: [GridItem], 22 | width: CGFloat) { 23 | self.viewModel = viewModel 24 | self.data = data 25 | self.columns = columns 26 | self.width = width 27 | } 28 | 29 | var body: some View { 30 | LazyVGrid(columns: columns, spacing: 12) { 31 | ForEach(data, id: \.self) { model in 32 | Button(action: { 33 | viewModel.logic(key: model) 34 | }, label: { 35 | if model.isDoubleWidth { 36 | Rectangle() 37 | .foregroundColor(model.backgroundColor) 38 | .overlay( 39 | Text(model.title) 40 | .font(.largeTitle) 41 | .offset(x: width * 0.22 * 0.5) 42 | ) 43 | .frame(width: width * 2 * 0.22, 44 | height: width * 0.22) 45 | } else { 46 | Text(model.title) 47 | .font(.largeTitle) 48 | .frame(width: width * 0.22, 49 | height: width * 0.22) 50 | } 51 | }) 52 | .foregroundColor(model.textColor) 53 | .background(model.backgroundColor) 54 | .cornerRadius(width * 0.25) 55 | } 56 | } 57 | .frame(width: width) 58 | } 59 | } 60 | 61 | struct VerticalButtonStack_Previews: PreviewProvider { 62 | static var previews: some View { 63 | VerticalButtonStack(viewModel: CalculadoraViewModel(), 64 | data: Matrix.firstSectionData, 65 | columns: Matrix.firstSectionGrid(390 * 0.25), 66 | width: 390) 67 | .previewLayout(.sizeThatFits) 68 | VerticalButtonStack(viewModel: CalculadoraViewModel(), 69 | data: Matrix.secondSectionData, 70 | columns: Matrix.secondSectionGrid(390 * 0.25), 71 | width: 390) 72 | .previewLayout(.sizeThatFits) 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/5-PropertyWrapperState.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PropertyWrapperState.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PropertyWrapperState: View { 11 | @State var counter: Int = 0 12 | 13 | var body: some View { 14 | VStack { 15 | Text("Counter \(counter)") 16 | Button("Incrementar Valor") { 17 | self.counter += 1 18 | } 19 | } 20 | } 21 | } 22 | 23 | struct PropertyWrapperState_Previews: PreviewProvider { 24 | static var previews: some View { 25 | PropertyWrapperState() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/6-LabelView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct LabelView: View { 11 | var body: some View { 12 | Label("Suscribiros a SwiftBeta", 13 | systemImage: "hand.thumbsup.fill") 14 | .labelStyle(TitleOnlyLabelStyle()) 15 | } 16 | } 17 | 18 | struct LabelView_Previews: PreviewProvider { 19 | static var previews: some View { 20 | LabelView() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/7-TextView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TextView: View { 11 | var body: some View { 12 | VStack { 13 | VStack { 14 | Text("Suscribiros a SwiftBeta") 15 | .font(.largeTitle) 16 | .underline() 17 | .foregroundColor(.red) 18 | + Text(" para aprender a programar") 19 | .font(.body) 20 | .foregroundColor(.blue) 21 | + Text(" SWIFTUI") 22 | .font(.body) 23 | .bold() 24 | + Text(" si te gusta el video puedes darle a LIKE") 25 | .font(.headline) 26 | .foregroundColor(.green) 27 | }.padding() 28 | Text("Suscribiros a SwiftBeta para aprender a programar SWIFTUI si te gusta el video puedes darle a LIKE") 29 | .font(.largeTitle) 30 | .underline() 31 | .rotation3DEffect(.degrees(20), 32 | axis: (x: 1, y: 0, z: 0)) 33 | .shadow(color: .gray, radius: 2, x: 0, y: 10) 34 | .lineLimit(10) 35 | .lineSpacing(10) 36 | .padding() 37 | .offset(x: 20) 38 | } 39 | } 40 | } 41 | 42 | struct TextView_Previews: PreviewProvider { 43 | static var previews: some View { 44 | TextView() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/8-ButtonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ButtonView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ButtonView: View { 11 | var body: some View { 12 | VStack { 13 | Button(action: { 14 | print("Suscríbete a SwiftBeta") 15 | }, label: { 16 | Text("Suscríbete".uppercased()) 17 | .font(.largeTitle) 18 | .fontWeight(.bold) 19 | .foregroundColor(.white) 20 | .padding() 21 | .background(Color.red) 22 | .cornerRadius(10) 23 | .shadow(radius: 10) 24 | }) 25 | Button(action: { 26 | print("Dale Like al video") 27 | }, label: { 28 | Circle() 29 | .fill(Color.blue) 30 | .frame(width: 200, height: 200) 31 | .shadow(radius: 10) 32 | .overlay( 33 | Image(systemName: "hand.thumbsup.fill") 34 | .foregroundColor(.white) 35 | .font(.system(size: 70, weight: .bold)) 36 | ) 37 | }) 38 | } 39 | } 40 | } 41 | 42 | struct ButtonView_Previews: PreviewProvider { 43 | static var previews: some View { 44 | ButtonView() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SwiftBeta-Curso-SwiftUI-Introduccion/Videos/9-TextFieldView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextFieldView.swift 3 | // SwiftBeta-Curso-Swift-Introduccion 4 | // 5 | // Created by Home on 13/9/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TextFieldView: View { 11 | @State var username: String = "" 12 | @State var password: String = "" 13 | 14 | var body: some View { 15 | VStack { 16 | TextField("Username", text: $username) 17 | SecureField("Password", text: $password) 18 | Spacer() 19 | } 20 | } 21 | } 22 | 23 | struct TextFieldView_Previews: PreviewProvider { 24 | static var previews: some View { 25 | TextFieldView() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /curso-swiftui.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "id": 1, 3 | "title": "¿Cómo crear tu primera iOS app? (SwiftUI y Xcode)", 4 | "youtube_url": "https://youtu.be/H0kihMlApn4", 5 | "post_url": "https://www.swiftbeta.com/primeros-pasos-en-swiftui/", 6 | "image_url": "https://i3.ytimg.com/vi/H0kihMlApn4/mqdefault.jpg?v=602641f8&sqp=CKiJg4oG&rs=AOn4CLBo1xU7JeNwYmoSZgXm8YJSk54G3A", 7 | "description": "¿Quieres APRENDER a programar en SWIFTUI y no sabes por dónde empezar? En SwiftBeta te vamos a guiar paso a paso hasta que puedas crear tu primera APLICACIÓN iOS en SWIFT con las últimas tecnologías como SWIFTUI." 8 | }, 9 | { 10 | "id": 2, 11 | "title": "SwiftUI: Stacks: VStack, HStack y ZStack", 12 | "youtube_url": "https://youtu.be/R5wIR9mRrkI", 13 | "post_url": "https://www.swiftbeta.com/stacks-en-swiftui/", 14 | "image_url": "https://i3.ytimg.com/vi/R5wIR9mRrkI/mqdefault.jpg?v=6026c132&sqp=CLCXg4oG&rs=AOn4CLBcf3G59htIwCw6vAGykH2kAGIyvQ", 15 | "description": "Aprende a estructurar tus vistas en SwiftUI, para ello aprenderás a crear vistas con Xcode y ver el resultado automáticamente en el canvas. Partimos de una vista y vamos creando poco a poco todas sus partes." 16 | }, 17 | { 18 | "id": 3, 19 | "title": "SwiftUI: Image", 20 | "youtube_url": "https://youtu.be/iPoae7PE7Nc", 21 | "post_url": "https://www.swiftbeta.com/swiftui-images/", 22 | "image_url": "https://i3.ytimg.com/vi/iPoae7PE7Nc/mqdefault.jpg?v=6029385d&sqp=CNyZg4oG&rs=AOn4CLDn81LHWB90YDuibJ1bHhgQeHwTzg", 23 | "description": "Aprende a usar imágenes en SwiftUI, en el video nos descargamos una imagen en formato PDF y la agregamos a nuestro proyecto en Xcode para poder acceder a ella desde el código." 24 | }, 25 | { 26 | "id": 4, 27 | "title": "SwiftUI: Iconos y SF Symbols", 28 | "youtube_url": "https://youtu.be/YKRqUq6_8RQ", 29 | "post_url": "https://www.swiftbeta.com/swiftui-sf-symbols/", 30 | "image_url": "https://i3.ytimg.com/vi/YKRqUq6_8RQ/mqdefault.jpg?v=602c2dc5&sqp=CLSeg4oG&rs=AOn4CLAZj65c_GkZTgZdVbNxWAMejyEmlg", 31 | "description": "Aprende a usar los iconos en SwiftUI e integrarlos en tus app. También damos un repaso a SF Symbols, una aplicación que nos ofrece Apple para encontrar los iconos ideales para nuestra app." 32 | }, 33 | { 34 | "id": 5, 35 | "title": "SwiftUI: Property Wrapper @State", 36 | "youtube_url": "https://youtu.be/geFS2IIfvCI", 37 | "post_url": "https://www.swiftbeta.com/state-en-swiftui/", 38 | "image_url": "https://i3.ytimg.com/vi/geFS2IIfvCI/mqdefault.jpg?v=60303acf&sqp=CLSeg4oG&rs=AOn4CLBczOaapyOzUM74Guw42jfutIgwOg", 39 | "description": "Aprende a usar los iconos en SwiftUI e integrarlos en tus app. También damos un repaso a SF Symbols, una aplicación que nos ofrece Apple para encontrar los iconos ideales para nuestra app." 40 | }, 41 | { 42 | "id": 6, 43 | "title": "SwiftUI: Label (Icono y Título)", 44 | "youtube_url": "https://youtu.be/99BLdSspVxM", 45 | "post_url": "https://www.swiftbeta.com/label-en-swiftui/", 46 | "image_url": "https://i3.ytimg.com/vi/99BLdSspVxM/mqdefault.jpg?v=60314766&sqp=CLSeg4oG&rs=AOn4CLD9ktHpIeQQlLIGZrAb5__NLukolg", 47 | "description": "Aprende a usar Label en SwiftUI, esta vista nos permite tener un icono y un texto. Antes de SwiftUI 2.0 esto lo teníamos que hacer de forma manual. También puedes customizar para que en ciertas ocaciones solo aparezca texto o solo el icono." 48 | }, 49 | { 50 | "id": 7, 51 | "title": "SwiftUI: Text (y sus modificadores)", 52 | "youtube_url": "https://youtu.be/tUZbPZG3o3U", 53 | "post_url": "https://www.swiftbeta.com/text-en-swiftui/", 54 | "image_url": "https://i3.ytimg.com/vi/tUZbPZG3o3U/mqdefault.jpg?v=603c0b60&sqp=CLSeg4oG&rs=AOn4CLAcobG3JGhSRfjOxBrt0YbHd_Dtaw", 55 | "description": "Aprende a usar Text en SwiftUI, esta vista nos permite mostrar texto y hay una gran variedad de modificadores: bold, font, foregroundColor, underline, etc" 56 | }, 57 | { 58 | "id": 8, 59 | "title": "SwiftUI: Button (y sus modificadores)", 60 | "youtube_url": "https://youtu.be/S2K8FGn5T4U", 61 | "post_url": "https://www.swiftbeta.com/button-en-swiftui/", 62 | "image_url": "https://i3.ytimg.com/vi/S2K8FGn5T4U/mqdefault.jpg?v=60421b27&sqp=CLSeg4oG&rs=AOn4CLCLMHIHiMQn5OWttRLUMXBF63Gq6w", 63 | "description": "Aprende a usar Button en SwiftUI, esta vista nos permite que cuando el usuario toque la vista, podamos ejecutar ciertas acciones. Como realizar una petición HTTP, realizar una validación, printar por consola, etc" 64 | }, 65 | { 66 | "id": 9, 67 | "title": "SwiftUI: TextField y SecureField", 68 | "youtube_url": "https://youtu.be/dIP2gC_nAok", 69 | "post_url": "https://www.swiftbeta.com/textfield-en-swiftui/", 70 | "image_url": "https://i3.ytimg.com/vi/dIP2gC_nAok/mqdefault.jpg?v=6043c947&sqp=CLSeg4oG&rs=AOn4CLD7aCfmRUAmQz4YTCrxyglZPHr3Ag", 71 | "description": "Aprende a usar TextField y SecureField en SwiftUI. Esta vista es un campo para que el user pueda meter datos y nosotros recogerlos para realizar alguna acción. El campo SecureField es lo mismo pero no podemos ver la información que añadimos." 72 | }, 73 | { 74 | "id": 10, 75 | "title": "SwiftUI: TextEditor", 76 | "youtube_url": "https://youtu.be/_UuhcApLlDg", 77 | "post_url": "https://www.swiftbeta.com/textedit-en-swiftui/", 78 | "image_url": "https://i3.ytimg.com/vi/_UuhcApLlDg/mqdefault.jpg?v=6047b53c&sqp=CKTNg4oG&rs=AOn4CLARGD7PRJI4T22gd8_u21gpXpcjCg", 79 | "description": "Aprende a usar TextEditor en SwiftUI. Esta vista permite que el user pueda meter más texto que en un TextField. Es como un TextField pero con Scroll." 80 | }, 81 | { 82 | "id": 11, 83 | "title": "SwiftUI: DatePicker", 84 | "youtube_url": "https://youtu.be/Hlh1rKjxIS4", 85 | "post_url": "https://www.swiftbeta.com/datepicker-en-swiftui/", 86 | "image_url": "https://i3.ytimg.com/vi/Hlh1rKjxIS4/mqdefault.jpg?v=604df210&sqp=CKTNg4oG&rs=AOn4CLBoSbSWhkBHTWrBSBRsK360lYOH-Q", 87 | "description": "Aprende a usar DatePicker en SwiftUI. Esta vista permite que el user pueda introducir una fecha por ejemplo desde un Form." 88 | }, 89 | { 90 | "id": 12, 91 | "title": "SwiftUI: ColorPicker", 92 | "youtube_url": "https://youtu.be/F3IzXHXKWjU", 93 | "post_url": "https://www.swiftbeta.com/colorpicker-en-swiftui/", 94 | "image_url": "https://i3.ytimg.com/vi/F3IzXHXKWjU/mqdefault.jpg?v=604e3e37&sqp=CKTNg4oG&rs=AOn4CLDtZ1L2MmF5PZD5W_VXgnz2Jm1P8g", 95 | "description": "Aprende a usar ColorPicker en SwiftUI. Esta vista permite que el user pueda escoger un color por ejemplo desde un Form." 96 | }, 97 | { 98 | "id": 13, 99 | "title": "SwiftUI: ProgressView", 100 | "youtube_url": "https://youtu.be/cKGPVNgKB0U", 101 | "post_url": "https://www.swiftbeta.com/progressview-en-swiftui/", 102 | "image_url": "https://i3.ytimg.com/vi/cKGPVNgKB0U/mqdefault.jpg?v=6057a1dd&sqp=CKTNg4oG&rs=AOn4CLAWZNYZzMfFywZmPL5UJqZpY_Goyg", 103 | "description": "Aprende a usar ProgressView en SwiftUI. Esta vista permite dar feedback al user indicando qué alguna acción se está realizando." 104 | }, 105 | { 106 | "id": 14, 107 | "title": "SwiftUI: Link", 108 | "youtube_url": "https://youtu.be/caVeT9_6A50", 109 | "post_url": "https://www.swiftbeta.com/link-en-swiftui/", 110 | "image_url": "https://i3.ytimg.com/vi/caVeT9_6A50/mqdefault.jpg?v=605a4c5d&sqp=CKTNg4oG&rs=AOn4CLAAE21o02a8fFXedZ7bUoaP7tKsbA", 111 | "description": "Aprende a usar Link en SwiftUI. Esta vista nos permite abrir URL directamente (es un tipo de Button muy específico)." 112 | }, 113 | { 114 | "id": 15, 115 | "title": "SwiftUI: Toggle", 116 | "youtube_url": "https://youtu.be/2qhd3p3aVGo", 117 | "post_url": "https://www.swiftbeta.com/toggle-en-swiftui/", 118 | "image_url": "https://i3.ytimg.com/vi/2qhd3p3aVGo/mqdefault.jpg?v=605ef984&sqp=CKTNg4oG&rs=AOn4CLD-FEeM8zFNb5IVU0n9nxdG4trpHQ", 119 | "description": "Aprende a usar Toggle en SwiftUI. Es una vista muy simple que puede tener dos valores, encendido o apagado (Es un interruptor)." 120 | }, 121 | { 122 | "id": 16, 123 | "title": "SwiftUI: Stepper", 124 | "youtube_url": "https://youtu.be/RxlpUGa3aX0", 125 | "post_url": "https://www.swiftbeta.com/stepper-en-swiftui/", 126 | "image_url": "https://i3.ytimg.com/vi/RxlpUGa3aX0/mqdefault.jpg?v=605f9666&sqp=CNDPg4oG&rs=AOn4CLDFxjGu4WTuoLpxYNXGPF9t-vQXdw", 127 | "description": "Aprende a usar Toggle en SwiftUI. Es una vista que nos permite incrementar o decrementar valores." 128 | }, 129 | { 130 | "id": 17, 131 | "title": "SwiftUI: Slider", 132 | "youtube_url": "https://youtu.be/ZNycSbbn3_o", 133 | "post_url": "https://www.swiftbeta.com/slider-en-swiftui/", 134 | "image_url": "https://i3.ytimg.com/vi/ZNycSbbn3_o/mqdefault.jpg?v=606ac9bb&sqp=CNDPg4oG&rs=AOn4CLBgpbBbwMfeQuMNITqzjvJ6uLmBpw", 135 | "description": "Aprende a usar Slider en SwiftUI. Esta vista nos permite seleccionar un valor de entre un posible rando de valores. Podemos deslizarnos por la vista." 136 | }, 137 | { 138 | "id": 18, 139 | "title": "SwiftUI: LazyVGrid y LazyHGrid", 140 | "youtube_url": "https://youtu.be/yM2yFqAHHrI", 141 | "post_url": "https://www.swiftbeta.com/lazyvgrid-y-lazyhgrid-en-swiftui/", 142 | "image_url": "https://i3.ytimg.com/vi/yM2yFqAHHrI/mqdefault.jpg?v=607075cd&sqp=CNDPg4oG&rs=AOn4CLAYPvZfY09hRqINooc7LpyS5ZHm7Q", 143 | "description": "Aprende a usar LazyVGrid y LazyHGrid en SwiftUI. Crea Grids y estructura tus vistas en unos minutos con LazyVGrid o LazyHGrid." 144 | }, 145 | { 146 | "id": 19, 147 | "title": "SwiftUI: Form", 148 | "youtube_url": "https://youtu.be/Qlnav1IEuUo", 149 | "post_url": "https://www.swiftbeta.com/forms-en-swiftui/", 150 | "image_url": "https://i3.ytimg.com/vi/Qlnav1IEuUo/mqdefault.jpg?v=6071e232&sqp=CNDPg4oG&rs=AOn4CLBil98FtW3tQVAGvpgxdcm1NZUtxw", 151 | "description": "Aprende a usar Form en SwiftUI. Podemos crear formularios y añadir todo tipo de vistas en SwiftUI." 152 | }, 153 | { 154 | "id": 20, 155 | "title": "SwiftUI: List", 156 | "youtube_url": "https://youtu.be/DpcubaF3maw", 157 | "post_url": "https://www.swiftbeta.com/list-en-swiftui/", 158 | "image_url": "https://i3.ytimg.com/vi/DpcubaF3maw/mqdefault.jpg?v=607b2f8c&sqp=CNDPg4oG&rs=AOn4CLBHF-oRxrDigM3_VNxiWAjWRhewOA", 159 | "description": "Aprende a usar List en SwiftUI. ¿Tienes que mostrar un listado? Usa List y ForEach para tener un listado en segundos." 160 | }, 161 | { 162 | "id": 21, 163 | "title": "SwiftUI: NavigationView y NavigationLink", 164 | "youtube_url": "https://youtu.be/Dkx0Bi8pNeo", 165 | "post_url": "https://www.swiftbeta.com/navigationview-y-navigationlink-en-swiftui/", 166 | "image_url": "https://i3.ytimg.com/vi/Dkx0Bi8pNeo/mqdefault.jpg?v=607bef70&sqp=CNDPg4oG&rs=AOn4CLB2Eg3CfAIrZAapag7FSDHoqPvZyQ", 167 | "description": "Aprende a usar NavigationView y NavigationLink en SwiftUI. Todas las apps tienen varias vistas, con NavigationView y NavigationLink podrás navegar a través de ellas." 168 | }, 169 | { 170 | "id": 22, 171 | "title": "SwiftUI: TabView", 172 | "youtube_url": "https://youtu.be/wd0byEC8YNA", 173 | "post_url": "https://www.swiftbeta.com/tabview-en-swiftui/", 174 | "image_url": "https://i3.ytimg.com/vi/wd0byEC8YNA/mqdefault.jpg?v=6083d390&sqp=CNDPg4oG&rs=AOn4CLA4M9fDvd_ThvhHCSAZmX7xMKJUsg", 175 | "description": "Aprende a usar NavigationView y NavigationLink en SwiftUI. Crea un menu en la parte inferior de la pantalla para poder navegar a las vistas más importantes de tu app." 176 | }, 177 | { 178 | "id": 23, 179 | "title": "SwiftUI: fullScreenCover & sheet", 180 | "youtube_url": "https://youtu.be/7PAcaQLARRY", 181 | "post_url": "https://www.swiftbeta.com/fullscreencover-y-sheet-en-swiftui/", 182 | "image_url": "https://i3.ytimg.com/vi/7PAcaQLARRY/mqdefault.jpg?v=608e6967&sqp=CNDPg4oG&rs=AOn4CLAa3zgylKG9EmNjjLyxTUeUcgU5fg", 183 | "description": "Aprende a usar fullScreenCover y sheet en SwiftUI. Otra manera de navegar es usar fullScreenCover y sheet, puedes presenter pantallas de forma modal." 184 | }, 185 | { 186 | "id": 24, 187 | "title": "SwiftUI: Alert", 188 | "youtube_url": "https://youtu.be/xG9v4llPR3Y", 189 | "post_url": "https://www.swiftbeta.com/alert-en-swiftui/", 190 | "image_url": "https://i3.ytimg.com/vi/xG9v4llPR3Y/mqdefault.jpg?v=60952a95&sqp=CNDPg4oG&rs=AOn4CLBmbvzwFGTA8q1Jg4BXrH1kGAhzqA", 191 | "description": "Aprende a usar Alert en SwiftUI. Muy útil si quieres mostrar un mensaje importante a tus users. También puedes especificar distintos botones con distintas acciones." 192 | }, 193 | { 194 | "id": 25, 195 | "title": "SwiftUI: ActionSheet", 196 | "youtube_url": "https://youtu.be/HuL35J9jvNE", 197 | "post_url": "https://www.swiftbeta.com/actionsheet-en-swiftui/", 198 | "image_url": "https://i3.ytimg.com/vi/HuL35J9jvNE/mqdefault.jpg?v=60979c60&sqp=CNDPg4oG&rs=AOn4CLCWm98KHfRsYdsSUo95SPDWA_aB4A", 199 | "description": "Aprende a usar ActionSheet en SwiftUI. Vista que aparece en la parte inferior de la pantalla, puedes añadir tantas acciones como quieras." 200 | }, 201 | { 202 | "id": 26, 203 | "title": "SwiftUI: ContextMenu", 204 | "youtube_url": "https://youtu.be/3nuFfJJeFj4", 205 | "post_url": "https://www.swiftbeta.com/contextmenu-en-swiftui/", 206 | "image_url": "https://i3.ytimg.com/vi/3nuFfJJeFj4/mqdefault.jpg?v=609c1958&sqp=CNDPg4oG&rs=AOn4CLCStcz7fFbGYJUP_QK0KqdyC4GF2Q", 207 | "description": "Aprende a usar ContextMenu en SwiftUI. Menu que aparece cuando mantienes pulsada una vista, puedes añadir varias acciones, y según la que el user pulse se realiza una u otra." 208 | }, 209 | { 210 | "id": 27, 211 | "title": "SwiftUI: TapGesture", 212 | "youtube_url": "https://youtu.be/LvN8yeCGIVo", 213 | "post_url": "https://www.swiftbeta.com/tapgesture-en-swiftui/", 214 | "image_url": "https://i3.ytimg.com/vi/LvN8yeCGIVo/mqdefault.jpg?v=60a0d2be&sqp=CNDPg4oG&rs=AOn4CLDi746CePbO6pgx_q3bJ7Ib52adPQ", 215 | "description": "Aprende a usar TapGesture en SwiftUI. Añade gestos a tus apps, en este caso aprenderás a usar el Tap Gesture. Al tocar una vista puedes realizar la acción que quieras." 216 | }, 217 | { 218 | "id": 28, 219 | "title": "SwiftUI: DragGesture", 220 | "youtube_url": "https://youtu.be/t_Z3mO6S6hA", 221 | "post_url": "https://www.swiftbeta.com/draggesture-en-swiftui/", 222 | "image_url": "https://i3.ytimg.com/vi/t_Z3mO6S6hA/mqdefault.jpg?v=60a6ac96&sqp=CPzRg4oG&rs=AOn4CLCG9cGakKpo4isgN9NZnV0WCML2GQ", 223 | "description": "Aprende a usar DragGesture en SwiftUI. Añade gestos a tus apps, en este caso aprenderás a arrastrar a usar el Drag Gesture. Al arrastrar una vista verás como se mueve por la pantalla." 224 | }, 225 | { 226 | "id": 29, 227 | "title": "SwiftUI: @State vs @Binding", 228 | "youtube_url": "https://youtu.be/35DnewGxabc", 229 | "post_url": "https://www.swiftbeta.com/state-vs-binding-en-swiftui/", 230 | "image_url": "https://i3.ytimg.com/vi/35DnewGxabc/mqdefault.jpg?v=60a7dcb3&sqp=CPzRg4oG&rs=AOn4CLC1zUiiZ2KoA2IJhC5CdXdkEjyVVA", 231 | "description": "Aprende las diferencias en el property wrapper @State y el property wrappe @Binding en SwiftUI. Muy importante saber para qué sirven los property wrappers en SwiftUI." 232 | }, 233 | { 234 | "id": 30, 235 | "title": "SwiftUI: @ObservedObject vs @StateObject", 236 | "youtube_url": "https://youtu.be/cKft6XVf27I", 237 | "post_url": "https://www.swiftbeta.com/observedobject-y-stateobject-en-swiftui/", 238 | "image_url": "https://i3.ytimg.com/vi/cKft6XVf27I/mqdefault.jpg?v=60ae752e&sqp=CPzRg4oG&rs=AOn4CLD_8eg8y6fUwIxeysYHx0viawrXOQ", 239 | "description": "Aprende las diferencias en el property wrapper @State y el property wrappe @Binding en SwiftUI. Cada property wrapper tiene su función, es importante saber qué hace cada uno." 240 | }, 241 | { 242 | "id": 31, 243 | "title": "SwiftUI: @EnvironmentObject", 244 | "youtube_url": "https://youtu.be/IvRmBnJi1_s", 245 | "post_url": "https://www.swiftbeta.com/environtmentobject-en-swiftui/", 246 | "image_url": "https://i3.ytimg.com/vi/IvRmBnJi1_s/mqdefault.jpg?v=60b126fe&sqp=CPzRg4oG&rs=AOn4CLDIKByaCoulHzxx2QvjSOh0V5VqfA", 247 | "description": "Aprende el property wrapper @EnvironmentObject en SwiftUI. Con este property wrapper puedes pasar información de una vista a otra sin pasarla como parámetro." 248 | }, 249 | { 250 | "id": 32, 251 | "title": "SwiftUI: @AppStorage", 252 | "youtube_url": "https://youtu.be/-hXV-GSb-io", 253 | "post_url": "https://www.swiftbeta.com/appstorage-en-swiftui/", 254 | "image_url": "https://i3.ytimg.com/vi/-hXV-GSb-io/mqdefault.jpg?v=60b3bede&sqp=CPzRg4oG&rs=AOn4CLDdbMJj6I3nPGyinpPfA1N8CI3dfg", 255 | "description": "Aprende a usar @AppStorage en SwiftUI, lo usamos en nuestras apps para guardar datos y al volver abrir la app vuelvan a aparecer. Si no lo hacemos los datos están en memoria y se pierden." 256 | }, 257 | { 258 | "id": 33, 259 | "title": "SwiftUI: @SceneStorage", 260 | "youtube_url": "https://youtu.be/34-C_jwqV_0", 261 | "post_url": "https://www.swiftbeta.com/scenestorage-en-swiftui/", 262 | "image_url": "https://i3.ytimg.com/vi/34-C_jwqV_0/mqdefault.jpg?v=60bb4295&sqp=CPzRg4oG&rs=AOn4CLCe1j3QqvRvaW8OYIOKMAhRJ4OWug", 263 | "description": "Aprende a usar @SceneStorage en SwiftUI. Es muy parecido al @AppStorage pero para guardar información de pantallas, muy útil si estás rellenando un formulario y cierras la app para seguir en otro momento." 264 | }, 265 | { 266 | "id": 34, 267 | "title": "SwiftUI: AsyncImage", 268 | "youtube_url": "https://youtu.be/KFZEZSk94wk", 269 | "post_url": "https://www.swiftbeta.com/asyncimage-en-swiftui/", 270 | "image_url": "https://i3.ytimg.com/vi/KFZEZSk94wk/mqdefault.jpg?v=60ccdfed&sqp=CPzRg4oG&rs=AOn4CLAJpojNCmh4CEIhPRbNjwKtYjNZXQ", 271 | "description": "Aprende a usar AsyncImage en SwiftUI a cargar imágenes de forma asíncrona." 272 | }, 273 | { 274 | "id": 35, 275 | "title": "SwiftUI: swipeActions y refreshable", 276 | "youtube_url": "https://youtu.be/gZ2IKHXkrFg", 277 | "post_url": "https://www.swiftbeta.com/swipeactions-y-refreshable-en-swiftui/", 278 | "image_url": "https://i3.ytimg.com/vi/gZ2IKHXkrFg/mqdefault.jpg?v=60e883ed&sqp=CPzRg4oG&rs=AOn4CLAYxDrLIUBPUix_3ZBe0YmaklDGug", 279 | "description": "Aprende para qué sirve swipeActions y refreshable. Se utilizan en listas para tener acciones adicionales en las celdas" 280 | }, 281 | { 282 | "id": 36, 283 | "title": "SwiftUI: GeometryReader", 284 | "youtube_url": "https://youtu.be/PWO6vCOAdsU", 285 | "post_url": "https://www.swiftbeta.com/geometryreader-en-swiftui/", 286 | "image_url": "https://i3.ytimg.com/vi/PWO6vCOAdsU/mqdefault.jpg?v=60f2a00c&sqp=CPzRg4oG&rs=AOn4CLCnBS4hkOwDxeXgg3r21pVld1dj6g", 287 | "description": "Aprende GeometryReader para poder crear animaciones en SwiftUI o adapter mejor las vistas a distintos tamaños." 288 | }, 289 | { 290 | "id": 37, 291 | "title": "SwiftUI: ViewModifier", 292 | "youtube_url": "https://youtu.be/CDBOXZ5eS-k", 293 | "post_url": "https://www.swiftbeta.com/viewmodifier-en-swiftui/", 294 | "image_url": "https://i3.ytimg.com/vi/CDBOXZ5eS-k/mqdefault.jpg?v=60fd23af&sqp=CPzRg4oG&rs=AOn4CLA31wj2MtBkICUwaz9uvDKGMlwSzw", 295 | "description": "Aprende a crear tu propio ViewModifier en SwiftUI. Artículo y video muy interesante donde creamos nuestro propio modificador en SwiftUI." 296 | }, 297 | { 298 | "id": 38, 299 | "title": "SwiftUI: PreferenceKey", 300 | "youtube_url": "https://youtu.be/tcJ_kUS67YA", 301 | "post_url": "https://www.swiftbeta.com/preferencekey-en-swiftui/", 302 | "image_url": "https://i3.ytimg.com/vi/tcJ_kUS67YA/mqdefault.jpg?v=60fe5b57&sqp=CPzRg4oG&rs=AOn4CLCheNbSvH8Lu0tC6CxJSK75WFlCdw", 303 | "description": "Aprende a usar @PreferenceKey en SwiftUI. Ejemplo muy práctico de como funciona el modificador navigationTitle. Aprenderás a crear el tuyo propio." 304 | }, 305 | { 306 | "id": 39, 307 | "title": "SwiftUI: Arquitectura REDUX", 308 | "youtube_url": "https://youtu.be/h-yNWWnlyMM", 309 | "post_url": "https://www.swiftbeta.com/arquitectura-redux-en-swiftui/", 310 | "image_url": "https://i3.ytimg.com/vi/h-yNWWnlyMM/mqdefault.jpg?v=612925f4&sqp=CPzRg4oG&rs=AOn4CLBptvVjMKhpLHavK8IWVGDIQrH8yQ", 311 | "description": "Aprende a usar REDUX en SwiftUI, una arquitectura que encaja a la perfección. Al crear tus iOS apps es muy importante tener una buena arquitectura." 312 | }, 313 | { 314 | "id": 40, 315 | "title": "SwiftUI: Crea la APP CALCULADORA", 316 | "youtube_url": "https://youtu.be/oTyRk56WyAI", 317 | "post_url": "https://www.swiftbeta.com/app-calculadora-en-swiftui/", 318 | "image_url": "https://i3.ytimg.com/vi/oTyRk56WyAI/mqdefault.jpg?v=6129245c&sqp=CPzRg4oG&rs=AOn4CLCYOn56tf2N2dZIyWSevFg5waP8kA", 319 | "description": "Aprende a crear la app Calculadora en SwiftUI. Es un video muy práctico donde con muy pocas líneas de código podemos crear la calculadora iOS." 320 | }, 321 | ] 322 | -------------------------------------------------------------------------------- /resources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftBeta/Curso-SwiftUI-Introduccion/2756487a7734f410dcdc30691283de3fd4adb398/resources/.DS_Store -------------------------------------------------------------------------------- /resources/all-videos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftBeta/Curso-SwiftUI-Introduccion/2756487a7734f410dcdc30691283de3fd4adb398/resources/all-videos.png -------------------------------------------------------------------------------- /resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftBeta/Curso-SwiftUI-Introduccion/2756487a7734f410dcdc30691283de3fd4adb398/resources/logo.png --------------------------------------------------------------------------------