├── .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 | #  👋 Hola, mi nombre es SwiftBeta
2 | ### 👨🏻💻 iOS Tech Lead de día - Creador de contenido iOS de noche
3 |
4 | [](https://youtube.com/swiftbeta?sub_confirmation=1)
5 | 
6 |
7 | # 40 videos GRATIS - Curso de SWIFTUI Introducción en Español.
8 |
9 | # 
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 |
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
--------------------------------------------------------------------------------