DEV Community

Cover image for SwiftUI Essentials: Crafting a To-Do List App with Xcode and Git Integration
Rohan Joshi
Rohan Joshi

Posted on • Updated on • Originally published at rohanjsh.Medium

SwiftUI Essentials: Crafting a To-Do List App with Xcode and Git Integration

SwiftUI Basics

Lets start…
We’ll cover basics of SwiftUI, basics of git in xcode and a hands-on task.

Declarative Syntax in SwiftUI

Declarative approach allows developers to focus on the “what” aspect of UI elements rather than the “how”. This means you simply declare what you want, and SwiftUI conjures the UI elements into existence.

Few SwiftUI Components

Let’s start our journey with a primer on the quintessential SwiftUI Views and Controls. SwiftUI provides a plethora of UI components, but mastering the basics can significantly ease your path.

  • Text: Renders static or dynamic text content in your app.
    // Displays a line of text with a predefined font style and padding around it.
    Text("Welcome to SwiftUI")
        .font(.title)// Sets the font style of the text to a title style.
        // More info: https://developer.apple.com/documentation/swiftui/text/font(_:)
        .padding()// Adds padding around the text.
        // More info: https://developer.apple.com/documentation/swiftui/view/padding(_:)
Enter fullscreen mode Exit fullscreen mode
  • Image: Adds images to your UI, supporting a wide range of formats.
    // Displays an image from the asset catalog, resizable and with aspect ratio control.
    Image("logo")
        .resizable() // Allows the image to be resized.
        // More info: https://developer.apple.com/documentation/swiftui/image/resizable(capinsets:resizingmode:)
        .aspectRatio(contentMode: .fit) // Keeps the aspect ratio and fits content within the bounds.
        .padding(50) // Adds padding of 50 points around the image.
Enter fullscreen mode Exit fullscreen mode
  • Button: Executes an action when tapped, a staple for interactive applications.
    // Creates a button with a text label, action to print a message, and various modifiers for appearance.
    Button("Tap Me!") {
        print("Button was tapped")
    }
    .padding() // Adds padding around the button for better touch area.
    .background(Color.blue) // Sets the background color of the button to blue.
    // More info: https://developer.apple.com/documentation/swiftui/view/background(alignment:content:)
    .foregroundColor(.white) // Sets the text color of the button to white.
Enter fullscreen mode Exit fullscreen mode
  • Stacks: Vertical (VStack) or horizontal (HStack) stacks arrange UI elements linearly.
    // Uses a VStack to organize text vertically with default spacing.
    VStack {
        Text("First Line") // First line of text.
        Text("Second Line") // Second line of text.
        // VStack docs: https://developer.apple.com/documentation/swiftui/vstack
    }

    HStack {
        Text("First")
        Text("Second") 
        // HStack docs: https://developer.apple.com/documentation/swiftui/hstack
    }
Enter fullscreen mode Exit fullscreen mode
  • Frame and Padding Modifiers: Customize the size and layout, adding breathing space around your UI elements.
    // Sets a specific frame size, applies a border, and adds padding.
    Text("Hello, SwiftUI")
        .frame(width: 200, height: 100) // Explicitly sets the frame size of the Text view.
        // More info: https://developer.apple.com/documentation/swiftui/view/frame(width:height:alignment:)
        .border(Color.black) // Adds a border with specified color around the Text view.
        // More info: https://developer.apple.com/documentation/swiftui/view/border(_:width:)
        .padding() // Adds padding around the bordered Text view.
Enter fullscreen mode Exit fullscreen mode

Git Version Control in Xcode

Through Xcode’s user-friendly interface, users can initialize a Git repository when creating a new project or add an existing project to a repository. Managing the repository involves several key actions:

  1. Committing Changes: After making modifications to your project, you can commit these changes directly within Xcode.
    Example: After editing a file, you can commit these changes by selecting it in the Source Control navigator, entering a commit message like "feat: new feature", and then committing the changes.

  2. Branching: Creating branches allows you to work on different features or fixes without affecting the main project.
    Example: To create a new branch for a feature, go to Source Control > New Branch, name it ‘feat/new-feature’, and start working on your feature independently.

  3. Pushing and Pulling: Syncing your local changes with a remote repository (e.g., GitHub) is done with pushing (to send local commits) and pulling (to receive changes from others). This ensures all team members are working with the latest codebase.
    Example: Push your commits by selecting Source Control > Push. If you've fetched changes from the remote repository, you can integrate them into your branch by selecting Source Control > Pull.

  4. Merging Changes: Integrating changes from one branch into another, such as merging a feature branch into the main branch, is done through the Merge feature in Xcode.
    Example: To merge the ‘feat/new-feature’ branch back into ‘main’, select the ‘main’ branch, then choose Source Control > Merge and select ‘feat/new-feature’ to merge its changes into ‘main’.

Hands-On Mini-Project: Building a simple “To-Do List” App

What better way to consolidate your learning than by diving into a hands-on mini-project? Applying the concepts of SwiftUI and version control, let’s create a simple yet functional “To-Do List” app.

  • Implementing basic TextField to gain input

  • Employing list views to display tasks.

  • Managing state with @State for dynamic UI updates.

Step 1: Set Up Your SwiftUI Environment

Start by creating a new SwiftUI project in Xcode.

Step 2: Define Your To-Do Model

First, we define a simple model for our to-do items.

    import Foundation

    // Identifiable docs: https://developer.apple.com/documentation/swift/identifiable
    struct ToDoItem: Identifiable {

        // UUID docs: https://developer.apple.com/documentation/foundation/uuid
        let id = UUID()
        var name: String
    }
Enter fullscreen mode Exit fullscreen mode

Step 3: Build the UI Components

Let’s build the UI for displaying and adding to-do items.

ContentView.swift

    import SwiftUI


    // Defines a ContentView struct that conforms to the View protocol, serving as the UI for your app.
    struct ContentView: View {
        // @State is a property wrapper designed for local state management in SwiftUI, triggering the view to re-render upon changes.
        // More info: https://developer.apple.com/documentation/swiftui/state
        @State private var items: [ToDoItem] = []
        @State private var newItemName: String = ""

        var body: some View {
            // More info: https://developer.apple.com/documentation/swiftui/navigationstack
            NavigationStack {

                // List is used to display an ordered collection of data.
                // More info: https://developer.apple.com/documentation/swiftui/list
                List {

                    // Section docs: https://developer.apple.com/documentation/swiftui/section
                    Section(header: Text("Add New Task")) {

                        // HStack docs: https://developer.apple.com/documentation/swiftui/hstack
                        HStack {

                            // TextField for user input.
                            // TextField docs: https://developer.apple.com/documentation/swiftui/textfield
                            TextField("Task Name", text: $newItemName)

                            // Button docs: https://developer.apple.com/documentation/swiftui/button
                            Button(action: addNewItem) {
                                Image(systemName: "plus.circle.fill")
                                    .foregroundColor(.orange)
                            }
                        }
                    }

                    Section(header: Text("My Tasks")) {

                        // ForEach docs: https://developer.apple.com/documentation/swiftui/foreach
                        ForEach(items) { item in
                            Text(item.name)
                        }
                        // onDelete docs: https://developer.apple.com/documentation/swiftui/dynamicviewcontent/ondelete(perform:)
                        .onDelete(perform: deleteItem)
                    }
                }
                // navigationTitle docs: https://developer.apple.com/documentation/swiftui/view/navigationtitle(_:)-43srq
                .navigationTitle("TaskTango")

                // toolbar docs: https://developer.apple.com/documentation/swiftui/view/toolbar(content:)-7vdkx
                .toolbar {

                    //EditButton docs: https://developer.apple.com/documentation/swiftui/editbutton
                    EditButton()
                }
            }
        }

        func addNewItem() {
            if !newItemName.isEmpty {
                items.append(ToDoItem(name: newItemName))
                newItemName = ""
            }
        }

        // IndexSet docs: https://developer.apple.com/documentation/foundation/indexset
        func deleteItem(at offsets: IndexSet) {
            items.remove(atOffsets: offsets)
        }
    }



    #Preview {
        ContentView()
    }
Enter fullscreen mode Exit fullscreen mode

Preview

SS1

SS2

TaskTango app

Through this example, we’ve seen how to use basic SwiftUI components to create an intuitive and functional app, incorporating core features such as state management.
Please note in this project we have not used the best architecture (we will cover later in the series), this is just to demonstrate how various components come together!

Github Repo — https://github.com/rohanjsh/todo.git

Practice. Experiment. Learn

Top comments (0)