list.png

Introduction

In the realm of iOS development, using Swift UI for constructing interactive and user-centric interfaces is indispensable. This tutorial is designed to delve into the practical implementation of Lists within Swift UI, an essential component for the structured presentation of data.

We will explore the procedures for dynamically adding and removing entries in a list, focusing on names. Moreover, to ensure data integrity and enhance user input quality, we will integrate regular expression (regex) based validation for the text field, allowing only valid names to be added to the list.

Embark on this technical journey to refine your Swift UI development skills by creating a dynamic list with validated input.

Implementation

Begin by initiating a new project in Xcode, selecting the “App” template as your starting point. Once done, navigate to the ContentView.swift file to apply the necessary updates as outlined below.

Kick-off this practical exercise by creating a new project in Xcode. Choose the App template for the foundation of your work.

After setting up your project, proceed to the ContentView.swift file, where I will guide you through the updates and modifications required to bring our dynamic list to life.

import SwiftUI

// Defines the main view of the app, managing a list of names with validation and deletion capabilities.
struct ContentView: View {
    // State variables to dynamically update the UI based on user interaction.
    @State private var names = ["Alice", "Bob", "Charlie", "David"] // The list of names displayed in the UI.
    @State private var newName: String = "" // The current input from the user for a new name.
    @State private var showError = false // Controls the visibility of an error message for invalid names.

    // Key Point 1: Name Validation
    let namePredicate = NSPredicate(format: "SELF MATCHES %@", "^[a-zA-ZÀ-ÿ-.' ]+$")

    // Builds the UI elements displayed to the user.
    var body: some View {
        VStack {
            HStack {
                // User input field for adding new names. Utilizes two-way binding to update 'newName' in real-time.
                TextField("Enter name", text: $newName)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .padding()

                // Button to trigger adding the new name to the list. Disabled if the name does not pass validation.
                Button("Add") { addName() }
                    .disabled(!isValidName(newName))
                    .padding()
            }

            // Conditionally displayed error message for invalid name inputs.
            if showError {
                Text("Invalid name. Please use letters only.")
                    .foregroundColor(.red)
                    .padding(.bottom)
            }

            // Key Point 2: Dynamic List with Deletion
            List {
                ForEach(names, id: \\.self) { name in
                    Text(name)
                }
                .onDelete(perform: delete)
            }
        }
    }

    // Attempts to add the new name to the list if it passes validation
    func addName() {
        if isValidName(newName) {
            names.append(newName)
            newName = "" // Resets the input field for a new name
            showError = false // Hides the error message if previously shown
        } else {
            showError = true // Shows an error message if the name is invalid
        }
    }

    // Removes a name from the list based on user selection
    func delete(at offsets: IndexSet) {
        names.remove(atOffsets: offsets)
    }

    // Checks if the provided name string matches the defined regular expression pattern
    func isValidName(_ name: String) -> Bool {
        // Uses the pre-initialized NSPredicate for efficient validation
        return namePredicate.evaluate(with: name)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Key Point 1: Name Validation

Key Point 2: Dynamic List with Deletion