├── swift-ui-logo.png ├── assets ├── images │ ├── list │ │ ├── 1.png │ │ ├── 2.png │ │ └── 3.png │ ├── input │ │ ├── tap │ │ │ └── 1.png │ │ ├── button │ │ │ ├── 1.png │ │ │ └── 2.png │ │ ├── picker │ │ │ └── 1.png │ │ ├── slider │ │ │ └── 1.png │ │ ├── toggle │ │ │ └── 1.png │ │ ├── textfield │ │ │ ├── 1.png │ │ │ └── 2.png │ │ └── date_picker │ │ │ └── 1.png │ ├── view │ │ ├── text │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ └── 3.png │ │ ├── image │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ └── 4.png │ │ └── shape │ │ │ ├── 1.png │ │ │ └── 2.png │ ├── navigation │ │ └── 1.png │ ├── layout │ │ ├── hstack │ │ │ └── 1.png │ │ ├── vstack │ │ │ ├── 1.png │ │ │ └── 2.png │ │ ├── zstack │ │ │ └── 1.png │ │ └── background │ │ │ ├── 1.png │ │ │ └── 2.png │ └── containers │ │ ├── group │ │ └── 1.png │ │ ├── tabview │ │ └── 1.png │ │ └── navigationview │ │ ├── 1.png │ │ └── 2.png └── swift-ui-logo.png ├── LICENSE ├── .gitignore ├── .github └── workflows │ └── aws.yml └── README.md /swift-ui-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/swift-ui-logo.png -------------------------------------------------------------------------------- /assets/images/list/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/list/1.png -------------------------------------------------------------------------------- /assets/images/list/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/list/2.png -------------------------------------------------------------------------------- /assets/images/list/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/list/3.png -------------------------------------------------------------------------------- /assets/swift-ui-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/swift-ui-logo.png -------------------------------------------------------------------------------- /assets/images/input/tap/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/tap/1.png -------------------------------------------------------------------------------- /assets/images/view/text/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/text/1.png -------------------------------------------------------------------------------- /assets/images/view/text/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/text/2.png -------------------------------------------------------------------------------- /assets/images/view/text/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/text/3.png -------------------------------------------------------------------------------- /assets/images/navigation/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/navigation/1.png -------------------------------------------------------------------------------- /assets/images/view/image/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/image/1.png -------------------------------------------------------------------------------- /assets/images/view/image/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/image/2.png -------------------------------------------------------------------------------- /assets/images/view/image/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/image/3.png -------------------------------------------------------------------------------- /assets/images/view/image/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/image/4.png -------------------------------------------------------------------------------- /assets/images/view/shape/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/shape/1.png -------------------------------------------------------------------------------- /assets/images/view/shape/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/view/shape/2.png -------------------------------------------------------------------------------- /assets/images/input/button/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/button/1.png -------------------------------------------------------------------------------- /assets/images/input/button/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/button/2.png -------------------------------------------------------------------------------- /assets/images/input/picker/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/picker/1.png -------------------------------------------------------------------------------- /assets/images/input/slider/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/slider/1.png -------------------------------------------------------------------------------- /assets/images/input/toggle/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/toggle/1.png -------------------------------------------------------------------------------- /assets/images/layout/hstack/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/layout/hstack/1.png -------------------------------------------------------------------------------- /assets/images/layout/vstack/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/layout/vstack/1.png -------------------------------------------------------------------------------- /assets/images/layout/vstack/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/layout/vstack/2.png -------------------------------------------------------------------------------- /assets/images/layout/zstack/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/layout/zstack/1.png -------------------------------------------------------------------------------- /assets/images/containers/group/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/containers/group/1.png -------------------------------------------------------------------------------- /assets/images/input/textfield/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/textfield/1.png -------------------------------------------------------------------------------- /assets/images/input/textfield/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/textfield/2.png -------------------------------------------------------------------------------- /assets/images/containers/tabview/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/containers/tabview/1.png -------------------------------------------------------------------------------- /assets/images/input/date_picker/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/input/date_picker/1.png -------------------------------------------------------------------------------- /assets/images/layout/background/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/layout/background/1.png -------------------------------------------------------------------------------- /assets/images/layout/background/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/layout/background/2.png -------------------------------------------------------------------------------- /assets/images/containers/navigationview/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/containers/navigationview/1.png -------------------------------------------------------------------------------- /assets/images/containers/navigationview/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverse-developer/SwiftUi-cheatsheet-GiSheet/HEAD/assets/images/containers/navigationview/2.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Giridharan Venkatapathy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | # .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | # Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | -------------------------------------------------------------------------------- /.github/workflows/aws.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build and push a new container image to Amazon ECR, 2 | # and then will deploy a new task definition to Amazon ECS, when a release is created 3 | # 4 | # To use this workflow, you will need to complete the following set-up steps: 5 | # 6 | # 1. Create an ECR repository to store your images. 7 | # For example: `aws ecr create-repository --repository-name my-ecr-repo --region us-east-2`. 8 | # Replace the value of `ECR_REPOSITORY` in the workflow below with your repository's name. 9 | # Replace the value of `aws-region` in the workflow below with your repository's region. 10 | # 11 | # 2. Create an ECS task definition, an ECS cluster, and an ECS service. 12 | # For example, follow the Getting Started guide on the ECS console: 13 | # https://us-east-2.console.aws.amazon.com/ecs/home?region=us-east-2#/firstRun 14 | # Replace the values for `service` and `cluster` in the workflow below with your service and cluster names. 15 | # 16 | # 3. Store your ECS task definition as a JSON file in your repository. 17 | # The format should follow the output of `aws ecs register-task-definition --generate-cli-skeleton`. 18 | # Replace the value of `task-definition` in the workflow below with your JSON file's name. 19 | # Replace the value of `container-name` in the workflow below with the name of the container 20 | # in the `containerDefinitions` section of the task definition. 21 | # 22 | # 4. Store an IAM user access key in GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. 23 | # See the documentation for each action used below for the recommended IAM policies for this IAM user, 24 | # and best practices on handling the access key credentials. 25 | 26 | on: 27 | release: 28 | types: [created] 29 | 30 | name: Deploy to Amazon ECS 31 | 32 | jobs: 33 | deploy: 34 | name: Deploy 35 | runs-on: ubuntu-latest 36 | environment: production 37 | 38 | steps: 39 | - name: Checkout 40 | uses: actions/checkout@v2 41 | 42 | - name: Configure AWS credentials 43 | uses: aws-actions/configure-aws-credentials@v1 44 | with: 45 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 46 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 47 | aws-region: us-east-2 48 | 49 | - name: Login to Amazon ECR 50 | id: login-ecr 51 | uses: aws-actions/amazon-ecr-login@v1 52 | 53 | - name: Build, tag, and push image to Amazon ECR 54 | id: build-image 55 | env: 56 | ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} 57 | ECR_REPOSITORY: my-ecr-repo 58 | IMAGE_TAG: ${{ github.sha }} 59 | run: | 60 | # Build a docker container and 61 | # push it to ECR so that it can 62 | # be deployed to ECS. 63 | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . 64 | docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 65 | echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" 66 | 67 | - name: Fill in the new image ID in the Amazon ECS task definition 68 | id: task-def 69 | uses: aws-actions/amazon-ecs-render-task-definition@v1 70 | with: 71 | task-definition: task-definition.json 72 | container-name: sample-app 73 | image: ${{ steps.build-image.outputs.image }} 74 | 75 | - name: Deploy Amazon ECS task definition 76 | uses: aws-actions/amazon-ecs-deploy-task-definition@v1 77 | with: 78 | task-definition: ${{ steps.task-def.outputs.task-definition }} 79 | service: sample-app-service 80 | cluster: default 81 | wait-for-service-stability: true 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftUI GiSheet - The Smart - Cheatsheet to everything on SwiftUI 2 | swiftui 3 | 4 | ![SwiftUI CHEATSHEET TUTORIAL](./swift-ui-logo.png) 5 | 6 | 7 | ### Table of Contents 8 | - [Resource](#resource) 9 | - [UIKit equivalent in SwiftUI](#uikit-equivalent-in-swiftui) 10 | - [View](#view) 11 | - [Text](#text) 12 | - [Label](#label) 13 | - [TextEditor](#texteditor) 14 | - [Image](#image) 15 | - [Shape](#shape) 16 | - [ProgressView](#progressview) 17 | - [Map](#map) 18 | - [Layout](#layout) 19 | - [Background](#background) 20 | - [VStack](#vstack) 21 | - [HStack](#hstack) 22 | - [ZStack](#zstack) 23 | - [LazyVStack](#lazyvstack) 24 | - [LazyHStack](#lazyhstack) 25 | - [LazyVGrid](#lazyvgrid) 26 | - [LazyHGrid](#lazyhgrid) 27 | - [Input](#input) 28 | - [Toggle](#toggle) 29 | - [Button](#button) 30 | - [TextField](#textfield) 31 | - [Slider](#slider) 32 | - [Date Picker](#date-picker) 33 | - [Picker](#picker) 34 | - [Stepper](#stepper) 35 | - [Tap](#tap) 36 | - [Gesture](#gesture) 37 | - [OnChange](#onChange) 38 | - [List](#list) 39 | - [Containers](#containers) 40 | - [NavigationView](#navigationview) 41 | - [TabView](#tabView) 42 | - [Group](#group) 43 | - [Alerts and Action Sheets](#alerts-and-action-sheets) 44 | - [Navigation](#navigation) 45 | - [Work with UIKit](#work-with-uikit) 46 | - [Navigate to ViewController](#navigate-to-viewcontroller) 47 | - [Use UIKit and SwiftUI Views Together](#use-uikit-and-swiftui-views-together) 48 | 49 | # Resource 50 | - [SwiftUI Tutorials (Official)](https://developer.apple.com/tutorials/swiftui/creating-and-combining-views) 51 | - [Introducing SwiftUI: Building Your First App (Official)](https://developer.apple.com/videos/play/wwdc2019/204/) 52 | - [SwiftUI: Getting Started Raywenderlich](https://www.raywenderlich.com/3715234-swiftui-getting-started) 53 | - [SwiftUI Essentials (Official)](https://developer.apple.com/videos/play/wwdc2019/216) 54 | - [SwiftUI - How to setup a project](https://medium.com/@martinlasek/swiftui-getting-started-372389fff423) 55 | - [About SwiftUI](https://github.com/Juanpe/About-SwiftUI) 56 | 57 | 58 | # UIKit equivalent in SwiftUI 59 | | UIKit | [SwiftUI](https://developer.apple.com/xcode/swiftui/) | 60 | | ----------- | ----------- | 61 | | UILabel | [Text](#text) & [Label](#label)| 62 | | UIImageView | [Image](#image) | 63 | | UITextField | [TextField](#textfield) | 64 | | UITextView | [TextEditor](#texteditor) | 65 | | UISwitch | [Toggle](#toggle) | 66 | | UISlider | [Slider](#slider) | 67 | | UIButton | [Button](#button) | 68 | | UITableView | [List](#list) | 69 | | UICollectionView | [LazyVGrid](#lazyvgrid) / [LazyHGrid](#lazyhgrid) | 70 | | UINavigationController | [NavigationView](#navigationview) | 71 | | UITabBarController | [TabView](#tabview) | 72 | | UIAlertController with style .alert | [Alert](#alerts-and-action-sheets) | 73 | | UIAlertController with style .actionSheet | [ActionSheet](#alerts-and-action-sheets) | 74 | | UIStackView with horizontal axis| [HStack](#hstack) / [LazyHStack](#lazyhstack) | 75 | | UIStackView with vertical axis| [VStack](#vstack) / [LazyVStack](#lazyvstack) | 76 | | UISegmentedControl | [Picker](#picker) | 77 | | UIStepper | [Stepper](#stepper) | 78 | | UIDatePicker | [DatePicker](#date-picker) | 79 | | NSAttributedString | No equivalent (use [Text](#text)) | 80 | | MapKit | [Map](#map) | 81 | | UIProgressView | [ProgressView](#progressview) | 82 | 83 | 84 | 85 | # View 86 | 87 | ### Text 88 | 89 | To show a **text** in UI simply write: 90 | ``` swift 91 | Text("Hello World") 92 | ``` 93 | 94 |
Screenshot 95 |

96 | 97 | ![](./assets/images/view/text/1.png) 98 | 99 |

100 |
101 | 102 | To add style 103 | 104 | ``` swift 105 | Text("Hello World") 106 | .font(.largeTitle) 107 | .fontWeight(.heavy) 108 | .foregroundColor(Color.red) 109 | .multilineTextAlignment(.leading) 110 | .lineLimit(1) 111 | .padding(.bottom) 112 | .frame(width: 400.0, height: 200.0) 113 | ``` 114 | 115 |
Screenshot 116 |

117 | 118 | ![](./assets/images/view/text/2.png) 119 | 120 |

121 |
122 | 123 | To format text inside text view 124 | 125 | ``` swift 126 | static let dateFormatter: DateFormatter = { 127 | let formatter = DateFormatter() 128 | formatter.dateStyle = .long 129 | return formatter 130 | }() 131 | 132 | var now = Date() 133 | var body: some View { 134 | Text("Task due date: \(now, formatter: Self.dateFormatter)") 135 | } 136 | ``` 137 | 138 |
Screenshot 139 |

140 | 141 | ![](./assets/images/view/text/3.png) 142 | 143 |

144 |
145 | 146 | ### Label 147 | Labels are a much-needed addition in the latest SwiftUI iteration. They let you set icons alongside text with the following line of code. 148 | 149 | ``` swift 150 | Label("SwiftUI CheatSheet 2.0", systemImage: "up.icloud") 151 | ``` 152 | 153 | It's possible to set URL, upon clicking which will redirect to browser. 154 | 155 | ``` swift 156 | Link("Click me",destination: URL(string: "your_url")!) 157 | ``` 158 | 159 | ### TextEditor 160 | Multi-line scrollable UITextViews natively in SwiftUI 161 | 162 | ``` swift 163 | TextEditor(text: $currentText) 164 | .onChange(of: clearText) { value in 165 | if clearText { 166 | currentText = "" 167 | } 168 | } 169 | ``` 170 | 171 | ### Map 172 | MapKit natively in SwiftUI 173 | 174 | ``` swift 175 | Map(mapRect:interactionModes:showsUserLocation: userTrackingMode: 176 | 177 | @State private var region = MKCoordinateRegion( 178 | center: CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868), 179 | span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2) 180 | ) 181 | 182 | Map(coordinateRegion: $region) 183 | ``` 184 | 185 | ### Image 186 | To show image 187 | 188 | ``` swift 189 | Image("hello_world") //image name is hello_world 190 | ``` 191 | 192 |
Screenshot 193 |

194 | 195 | ![](./assets/images/view/image/1.png) 196 | 197 |

198 |
199 | 200 | To use system icon 201 | ``` swift 202 | Image(systemName: "cloud.heavyrain.fill") 203 | .resizable() 204 | .aspectRatio(contentMode: .fit) 205 | .padding(.bottom) 206 | .clipShape(Circle()) 207 | .overlay(Circle().stroke(Color.gray, lineWidth: 4)) 208 | .shadow(radius: 7) 209 | ``` 210 | 211 |
Screenshot 212 |

213 | 214 | ![](./assets/images/view/image/2.png) 215 | 216 |

217 |
218 | 219 | you can add style to system icon set 220 | 221 | ``` swift 222 | Image(systemName: "cloud.heavyrain.fill") 223 | .foregroundColor(.red) 224 | .font(.largeTitle) 225 | ``` 226 | 227 |
Screenshot 228 |

229 | 230 | ![](./assets/images/view/image/3.png) 231 | 232 |

233 |
234 | 235 | Add style to Image 236 | 237 | ``` swift 238 | Image("hello_world") 239 | .resizable() //it will sized so that it fills all the available space 240 | .aspectRatio(contentMode: .fill) 241 | .padding(.bottom) 242 | ``` 243 | 244 |
Screenshot 245 |

246 | 247 | ![](./assets/images/view/image/4.png) 248 | 249 |

250 |
251 | 252 | ### Shape 253 | 254 | To create Rectangle 255 | 256 | ``` swift 257 | Rectangle() 258 | .fill(Color.red) 259 | .frame(width: 200, height: 200) 260 | ``` 261 | 262 |
Screenshot 263 |

264 | 265 | ![](./assets/images/view/shape/1.png) 266 | 267 |

268 |
269 | 270 | To create circle 271 | 272 | ``` swift 273 | Circle() 274 | .fill(Color.blue) 275 | .frame(width: 50, height: 50) 276 | ``` 277 | 278 |
Screenshot 279 |

280 | 281 | ![](./assets/images/view/shape/2.png) 282 | 283 |

284 |
285 | 286 | ### ProgressView 287 | 288 | To show a ProgressView 289 | ``` swift 290 | ProgressView("Text", value: 10, total: 100) 291 | ``` 292 | 293 | # Layout 294 | 295 | ### Background 296 | To use image as a background 297 | 298 | ``` swift 299 | Text("Hello World") 300 | .font(.largeTitle) 301 | .background( 302 | Image("hello_world") 303 | .resizable() 304 | .frame(width: 100, height: 100) 305 | ) 306 | ``` 307 | 308 |
Screenshot 309 |

310 | 311 | ![](./assets/images/layout/background/1.png) 312 | 313 |

314 |
315 | 316 | Gradient background 317 | 318 | ``` swift 319 | Text("Hello World") 320 | .background( 321 | LinearGradient( 322 | gradient: Gradient(colors: [.white, .red, .black]), 323 | startPoint: .leading, 324 | endPoint: .trailing 325 | ), 326 | cornerRadius: 0 327 | ) 328 | ``` 329 | 330 |
Screenshot 331 |

332 | 333 | ![](./assets/images/layout/background/2.png) 334 | 335 |

336 |
337 | 338 | ### VStack 339 | Shows child view vertically 340 | 341 | ``` swift 342 | VStack { 343 | Text("Hello") 344 | Text("World") 345 | } 346 | ``` 347 | 348 |
Screenshot 349 |

350 | 351 | ![](./assets/images/layout/vstack/1.png) 352 | 353 |

354 |
355 | 356 | Styling 357 | 358 | ``` swift 359 | VStack(alignment: .leading, spacing: 20) { 360 | Text("Hello") 361 | Divider() 362 | Text("World") 363 | } 364 | ``` 365 | 366 |
Screenshot 367 |

368 | 369 | ![](./assets/images/layout/vstack/2.png) 370 | 371 |

372 |
373 | 374 | ### HStack 375 | Shows child view horizontally 376 | 377 | ``` swift 378 | HStack { 379 | Text("Hello") 380 | Text("World") 381 | } 382 | ``` 383 | 384 |
Screenshot 385 |

386 | 387 | ![](./assets/images/layout/hstack/1.png) 388 | 389 |

390 |
391 | 392 | ### ZStack 393 | 394 | To create overlapping content use ZStack 395 | 396 | ``` swift 397 | ZStack() { 398 | Image("hello_world") 399 | Text("Hello World") 400 | .font(.largeTitle) 401 | .background(Color.black) 402 | .foregroundColor(.white) 403 | } 404 | ``` 405 | 406 |
Screenshot 407 |

408 | 409 | ![](./assets/images/layout/zstack/1.png) 410 | 411 |

412 |
413 | 414 | ### LazyVStack 415 | 416 | It loads content as and when it’s needed thus improving performance 417 | 418 | ``` swift 419 | ScrollView(.horizontal) { 420 | LazyVStack(spacing: 10) { 421 | ForEach(0..<1000) { index in 422 | Text("\(index)") 423 | .frame(width: 100, height: 200) 424 | .border(Color.gray.opacity(0.5), width: 0.5) 425 | .background(Color.blue) 426 | .cornerRadius(6) 427 | } 428 | } 429 | .padding(.leading, 10) 430 | } 431 | ``` 432 | 433 | ### LazyHStack 434 | 435 | It loads content as and when it’s needed thus improving performance 436 | 437 | ``` swift 438 | ScrollView(.horizontal) { 439 | LazyHStack(spacing: 10) { 440 | ForEach(0..<1000) { index in 441 | Text("\(index)") 442 | .frame(width: 100, height: 200) 443 | .border(Color.gray.opacity(0.5), width: 0.5) 444 | .background(Color.blue) 445 | .cornerRadius(6) 446 | } 447 | } 448 | .padding(.leading, 10) 449 | } 450 | ``` 451 | 452 | ### LazyVGrid 453 | A containers for grid-based layouts that let you set child views vertically in LazyVGrid. Each element of a SwiftUI grid is a GridItem. We can set the alignments, spacing, and size of the GridItem 454 | 455 | 456 | ``` swift 457 | struct ContentView: View { 458 | 459 | let colors: [Color] = [.red, .green, .yellow, .blue] 460 | 461 | var columns: [GridItem] = 462 | Array(repeating: .init(.flexible(), alignment: .center), count: 3) 463 | 464 | var body: some View { 465 | ScrollView { 466 | LazyVGrid(columns: columns, spacing: 10) { 467 | ForEach(0...100, id: \.self) { index in 468 | Text("Tab \(index)") 469 | .frame(width: 110, height: 200) 470 | .background(colors[index % colors.count]) 471 | .cornerRadius(8) 472 | } 473 | } 474 | } 475 | } 476 | } 477 | 478 | ``` 479 | 480 | ### LazyHGrid 481 | A containers for grid-based layouts that let you set child views horizontally in LazyHGrid 482 | 483 | 484 | ``` swift 485 | struct ContentView: View { 486 | 487 | let colors: [Color] = [.red, .green, .yellow, .blue] 488 | 489 | var columns: [GridItem] = 490 | Array(repeating: .init(.flexible(), alignment: .center), count: 3) 491 | 492 | var body: some View { 493 | ScrollView { 494 | LazyHGrid(columns: columns, spacing: 10) { 495 | ForEach(0...100, id: \.self) { index in 496 | Text("Tab \(index)") 497 | .frame(width: 110, height: 200) 498 | .background(colors[index % colors.count]) 499 | .cornerRadius(8) 500 | } 501 | } 502 | } 503 | } 504 | } 505 | 506 | ``` 507 | 508 | # Input 509 | 510 | ### Toggle 511 | 512 | Toggle lets users move between true and false states 513 | 514 | ``` swift 515 | @State var isShowing = true //state 516 | 517 | Toggle(isOn: $isShowing) { 518 | Text("Hello World") 519 | }.padding() 520 | ``` 521 | 522 |
Screenshot 523 |

524 | 525 | ![](./assets/images/input/toggle/1.png) 526 | 527 |

528 |
529 | 530 | ### Button 531 | To create button 532 | 533 | ``` swift 534 | Button( 535 | action: { 536 | // do something 537 | }, 538 | label: { Text("Click Me") } 539 | ) 540 | ``` 541 | 542 |
Screenshot 543 |

544 | 545 | ![](./assets/images/input/button/1.png) 546 | 547 |

548 |
549 | 550 | To create image Button 551 | 552 | ``` swift 553 | Button( 554 | action: { 555 | // do something 556 | }, 557 | label: { Image("hello_world") } 558 | ) 559 | ``` 560 | 561 | 562 | ### TextField 563 | 564 | It heavily relies in state, simply create a state and pass it as it will bind to it 565 | 566 | ``` swift 567 | @State var fullName: String = "Joe" //create State 568 | 569 | TextField($fullName) // passing it to bind 570 | .textFieldStyle(.roundedBorder) // adds border 571 | 572 | ``` 573 | 574 |
Screenshot 575 |

576 | 577 | ![](./assets/images/input/textfield/1.png) 578 | 579 |

580 |
581 | 582 | To create secure TextField 583 | 584 | ``` swift 585 | @State var password: String = "" // create State 586 | 587 | SecureField($password) // passing it to bind 588 | .textFieldStyle(.roundedBorder) // adds border 589 | 590 | ``` 591 | 592 |
Screenshot 593 |

594 | 595 | ![](./assets/images/input/textfield/2.png) 596 | 597 |

598 |
599 | 600 | ### Slider 601 | 602 | ``` swift 603 | @State var value: Double = 0 // create State 604 | 605 | Slider(value: $value, from: -100, through: 100, by: 1) 606 | ``` 607 | 608 |
Screenshot 609 |

610 | 611 | ![](./assets/images/input/slider/1.png) 612 | 613 |

614 |
615 | 616 | ### Date Picker 617 | 618 | ``` swift 619 | @State var selectedDate = Date() 620 | DatePicker( 621 | $selectedDate, 622 | maximumDate: Date(), 623 | displayedComponents: .date 624 | ) 625 | ``` 626 | 627 |
Screenshot 628 |

629 | 630 | ![](./assets/images/input/date_picker/1.png) 631 | 632 |

633 |
634 | 635 | ### Picker 636 | 637 | ``` swift 638 | @State var favoriteColor = 0 639 | var colors = ["Red", "Green", "Blue"] 640 | 641 | Picker("Favorite Color", selection: $favoriteColor) { 642 | ForEach(0 ..< colors.count) { index in 643 | Text(self.colors[index]) 644 | .tag(index) 645 | } 646 | } 647 | .pickerStyle(SegmentedPickerStyle()) 648 | ``` 649 | 650 |
Screenshot 651 |

652 | 653 | ![](./assets/images/input/picker/1.png) 654 | 655 |

656 |
657 | 658 | ### Stepper 659 | 660 | ``` swift 661 | @State var count:Int = 0 662 | 663 | Stepper( 664 | onIncrement: { self.count += 1 }, 665 | onDecrement: { self.count -= 1 }, 666 | label: { Text("Count is \(count)") } 667 | ) 668 | ``` 669 | 670 | or 671 | 672 | ``` swift 673 | @State var count:Int = 0 674 | 675 | Stepper(value: $count, in: 1...10) { 676 | Text("Count is \(count)") 677 | } 678 | ``` 679 | or 680 | 681 | ``` swift 682 | @State private var temperature = 0.0 683 | 684 | Stepper(value: $temperature, in: 0...100.0, step: 0.5) { 685 | Text("Temperature is \(temperature, specifier:"%g")") 686 | } 687 | ``` 688 | 689 | ### Tap 690 | For single tap 691 | 692 | ``` swift 693 | Text("Tap me!") 694 | .onTapGesture { 695 | print("Tapped!") 696 | } 697 | ``` 698 | For double tap 699 | 700 | ``` swift 701 | Text("Tap me!") 702 | .onTapGesture(count: 2) { 703 | print("Tapped!") 704 | } 705 | ``` 706 | 707 |
Screenshot 708 |

709 | 710 | ![](./assets/images/input/tap/1.png) 711 | 712 |

713 |
714 | 715 | ### Gesture 716 | Gesture like **TapGesture**, **LongPressGesture**, **DragGesture** 717 | 718 | ``` swift 719 | Text("Tap") 720 | .gesture( 721 | TapGesture() 722 | .onEnded { _ in 723 | // do something 724 | } 725 | ) 726 | 727 | Text("Drag Me") 728 | .gesture( 729 | DragGesture(minimumDistance: 50) 730 | .onEnded { _ in 731 | // do something 732 | } 733 | ) 734 | 735 | Text("Long Press") 736 | .gesture( 737 | LongPressGesture(minimumDuration: 2) 738 | .onEnded { _ in 739 | // do something 740 | } 741 | ) 742 | ``` 743 | 744 | ### OnChange 745 | 746 | onChange is a new view modifier that’s available across all SwiftUI views. It lets you listen to state changes and perform actions on a view accordingly. 747 | 748 | ``` swift 749 | 750 | TextEditor(text: $currentText) 751 | .onChange(of: clearText) { value in 752 | if clearText{ 753 | currentText = "" 754 | } 755 | } 756 | 757 | ``` 758 | 759 | # List 760 | 761 | To create static scrollable **List** 762 | 763 | ``` swift 764 | List { 765 | Text("Hello world") 766 | Text("Hello world") 767 | Text("Hello world") 768 | } 769 | ``` 770 | 771 |
Screenshot 772 |

773 | 774 | ![](./assets/images/list/1.png) 775 | 776 |

777 |
778 | 779 | To create dynamic **List** 780 | ``` swift 781 | let names = ["Thanos", "Iron man", "Ant man"] 782 | List(names, id: \.self) { name in 783 | Text(name) 784 | } 785 | ``` 786 | 787 | To add section 788 | 789 | ``` swift 790 | List { 791 | Section(header: Text("Good Hero")) { 792 | Text("Thanos") 793 | } 794 | 795 | Section(header: Text("Bad Heros")) { 796 | Text("Iron man") 797 | } 798 | } 799 | ``` 800 | 801 |
Screenshot 802 |

803 | 804 | ![](./assets/images/list/2.png) 805 | 806 |

807 |
808 | 809 | To make it grouped add *.listStyle(GroupedListStyle())* 810 | 811 | ``` swift 812 | List { 813 | Section(header: Text("Good Hero")) { 814 | Text("Thanos") 815 | } 816 | 817 | Section(header: Text("Bad Heros")) { 818 | Text("Iron man") 819 | } 820 | }.listStyle(GroupedListStyle()) 821 | ``` 822 | 823 |
Screenshot 824 |

825 | 826 | ![](./assets/images/list/3.png) 827 | 828 |

829 |
830 | 831 | To add a footer to a section 832 | 833 | ``` swift 834 | List { 835 | Section(header: Text("Good Heros"), footer: Text("Powerful")){ 836 | Text("Thanos") 837 | } 838 | Section(header: Text("Bad Heros"), footer: Text("Not as Powerful")){ 839 | Text("Iron Man") 840 | } 841 | }.listStyle(GroupedListStyle()) 842 | ``` 843 | 844 |
Screenshot 845 |

846 | 847 | ![](./assets/images/list/3.png) 848 | 849 |

850 |
851 | 852 | # Containers 853 | 854 | ### NavigationView 855 | 856 | **NavigationView** is more/less like **UINavigationController**, It handles navigation between views, shows title, places navigation bar on top. 857 | 858 | ``` swift 859 | NavigationView { 860 | Text("Hello") 861 | .navigationBarTitle(Text("World"), displayMode: .inline) 862 | } 863 | ``` 864 | 865 |
Screenshot 866 |

867 | 868 | ![](./assets/images/containers/navigationview/1.png) 869 | 870 |

871 |
872 | 873 | For large title use *.large* 874 | 875 | Add bar items to **NavigationView** 876 | 877 | ``` swift 878 | NavigationView { 879 | Text("Hello") 880 | .navigationBarTitle(Text("World"), displayMode: .inline) 881 | .navigationBarItems( 882 | trailing: 883 | Button( 884 | action: { print("Going to Setting") }, 885 | label: { Text("Setting") } 886 | ) 887 | ) 888 | } 889 | ``` 890 | 891 |
Screenshot 892 |

893 | 894 | ![](./assets/images/containers/navigationview/2.png) 895 | 896 |

897 |
898 | 899 | ### TabView 900 | 901 | **TabView** creates a container similar to **UITabBarController** with radio-style selection control which determines which `View` is presented. 902 | 903 | ``` swift 904 | @State private var selection = 0 905 | 906 | TabView(selection: $selection) { 907 | Text("View A") 908 | .font(.title) 909 | .tabItemLabel(Text("View A") 910 | .font(.caption)) 911 | .tag(0) 912 | Text("View B") 913 | .font(.title) 914 | .tabItemLabel(Text("View B") 915 | .font(.caption)) 916 | .tag(1) 917 | Text("View C") 918 | .font(.title) 919 | .tabItemLabel(Text("View C") 920 | .font(.caption)) 921 | .tag(2) 922 | } 923 | ``` 924 | 925 |
Screenshot 926 |

927 | 928 | ![](./assets/images/containers/tabview/1.png) 929 | 930 |

931 |
932 | 933 | ### Group 934 | Group creates several views to act as one, also to avoid Stack's 10 View maximum limit. 935 | 936 | ``` swift 937 | VStack { 938 | Group { 939 | Text("Hello") 940 | Text("Hello") 941 | Text("Hello") 942 | } 943 | Group { 944 | Text("Hello") 945 | Text("Hello") 946 | } 947 | } 948 | ``` 949 | 950 |
Screenshot 951 |

952 | 953 | ![](./assets/images/containers/group/1.png) 954 | 955 |

956 |
957 | 958 | # Alerts and Action Sheets 959 | To Show an Alert 960 | 961 | ``` swift 962 | Alert( 963 | title: Text("Title"), 964 | message: Text("message"), 965 | dismissButton: .default(Text("Ok!")) 966 | ) 967 | 968 | ``` 969 | To Show Action Sheet 970 | 971 | ``` swift 972 | ActionSheet( 973 | title: Text("Title"), 974 | message: Text("Message"), 975 | buttons: [ 976 | .default(Text("Ok!"), action: { print("hello") }) 977 | ] 978 | ) 979 | ``` 980 | 981 | # Navigation 982 | Navigate via **NavigationLink** 983 | 984 | ``` swift 985 | NavigationView { 986 | NavigationLink(destination: SecondView()) { 987 | Text("Show") 988 | }.navigationBarTitle(Text("First View")) 989 | } 990 | ``` 991 | 992 |
Screenshot 993 |

994 | 995 | ![](./assets/images/navigation/1.png) 996 | 997 |

998 |
999 | 1000 | Navigate via tap on List Item 1001 | 1002 | ``` swift 1003 | let names = ["Thanos", "Iron man", "Ant man"] 1004 | List(names, id: \.self) { name in 1005 | NavigationLink(destination: HeroView(name: name)) { 1006 | Text(name) 1007 | } 1008 | } 1009 | ``` 1010 | 1011 | # Work with UIKit 1012 | 1013 | ### Navigate to ViewController 1014 | 1015 | > It's possible to work with UIKit components from SwiftUI or call SwiftUI views as View Controllers from UIKit. 1016 | 1017 | Let's say you have a View Controller named SuperVillainViewController and want to call it from a SwiftUI view, to do that ViewController needs to implement UIViewControllerRepresentable: 1018 | 1019 | ``` swift 1020 | struct SuperVillainViewController: UIViewControllerRepresentable { 1021 | var controllers: [UIViewController] 1022 | func makeUIViewcontroller(context: Context) -> SuperVillainViewController { 1023 | // you could have a custom constructor here, I'm just keeping it simple 1024 | let vc = SuperVillainViewController() 1025 | return vc 1026 | } 1027 | } 1028 | ``` 1029 | Now you can use it like 1030 | 1031 | ``` swift 1032 | NavigationLink(destination: SuperVillainViewController()) { 1033 | Text("Click") 1034 | } 1035 | ``` 1036 | ### Use UIKit and SwiftUI Views Together 1037 | 1038 | > To use UIView subclasses from within SwiftUI, you wrap the other view in a SwiftUI view that conforms to the UIViewRepresentable protocol. ([Reference](https://developer.apple.com/tutorials/swiftui/creating-and-combining-views#use-uikit-and-swiftui-views-together)) 1039 | 1040 | as example 1041 | 1042 | ``` swift 1043 | 1044 | import SwiftUI 1045 | import MapKit 1046 | 1047 | struct MapView: UIViewRepresentable { 1048 | func makeUIView(context: Context) -> MKMapView { 1049 | MKMapView(frame: .zero) 1050 | } 1051 | 1052 | func updateUIView(_ view: MKMapView, context: Context) { 1053 | let coordinate = CLLocationCoordinate2D( 1054 | latitude: 34.011286, 1055 | longitude: -116.166868 1056 | ) 1057 | let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0) 1058 | let region = MKCoordinateRegion(center: coordinate, span: span) 1059 | view.setRegion(region, animated: true) 1060 | } 1061 | } 1062 | 1063 | struct MapView_Preview: PreviewProvider { 1064 | static var previews: some View { 1065 | MapView() 1066 | } 1067 | } 1068 | 1069 | ``` 1070 | [![Stargazers repo roster for @giridharan-dev/SwiftUi-GiSheet](https://reporoster.com/stars/giridharan-dev/SwiftUi-GiSheet)](https://github.com/giridharan-dev/SwiftUi-GiSheet/stargazers) 1071 | 1072 | Thank you for all the people who starred this repo!! 1073 | 1074 | 1075 | [⏫ Top](#table-of-contents) 1076 | --------------------------------------------------------------------------------