7 Key Strategies for Reducing Code Duplication in SwiftUI

7 Key Strategies for Reducing Code Duplication in SwiftUI

As software developers, we're often told to follow the DRY (Don't Repeat Yourself) principle, which is aimed at reducing the repetition of software patterns. SwiftUI provides various tools and methodologies that aid us in adhering to this principle. This blog post will cover a number of these techniques, complete with code examples.

1. Extracting Views

Extracting views is one of the simplest ways to avoid code duplication. This allows us to create reusable components that can be used throughout the app. For example, if you find yourself creating a similar Button style across multiple screens, consider extracting it into a separate View.

struct CustomButton: View {
    var title: String
    var action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .padding()
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(8)
        }
    }
}

You can now use CustomButton throughout your SwiftUI code, ensuring a consistent look and feel across your app.

2. Custom ViewModifiers

ViewModifiers provide an elegant way to bundle view modifications for reuse. This can dramatically reduce code duplication, particularly when dealing with consistent styling across many views.

struct CustomTextStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.title)
            .foregroundColor(.blue)
    }
}

extension View {
    func customTextStyle() -> some View {
        self.modifier(CustomTextStyle())
    }
}

Now you can apply customTextStyle() to any SwiftUI View.

3. Reusable Components

Creating reusable components is a powerful way to minimize code duplication. This could include buttons, form fields, cards, or any other UI element that appears frequently in your app. Here's an example of a reusable card view:

struct CardView: View {
    var body: some View {
        VStack {
            Image("example-image")
                .resizable()
                .aspectRatio(contentMode: .fit)
            Text("Example Text")
                .font(.headline)
                .padding()
        }
        .frame(width: 300, height: 400)
        .background(Color.white)
        .cornerRadius(10)
        .shadow(radius: 10)
    }
}

This CardView can be used anywhere in your app, reducing the need to repeat similar code.

4. ViewBuilder Functions

ViewBuilder is a result builder that constructs a view from a series of expressions. You can create functions that return complex views, helping you avoid repetition.

@ViewBuilder
func customLabel(title: String, subtitle: String) -> some View {
    VStack(alignment: .leading) {
        Text(title)
            .font(.title)
        Text(subtitle)
            .font(.subheadline)
            .foregroundColor(.gray)
    }
}

This customLabel function can be used to create a title and subtitle pair, reducing the need for duplication.

5. Extensions

Swift extensions allow you to add new functionality to existing types, which can be very useful in SwiftUI. For example, you can add a custom modifier to all Text views in your app, reducing the need to apply the same modifiers to Text views repeatedly.

extension Text {
    func titleStyle() -> some View {
        self
            .font(.largeTitle)
            .foregroundColor(.primary)
    }
}

6. Model Objects

Moving logic into model objects can significantly reduce code duplication. SwiftUI's design encourages a clear separation of concerns, with views focusing on UI and model objects handling data and business logic.

class TaskViewModel: ObservableObject {
    @Published var tasks = [Task]()

    func loadTasks() {
        // Load tasks from a data source
    }

    func addTask(_ task: Task) {
        tasks.append(task)
    }
}

This TaskViewModel can be used across multiple views, reducing the need to duplicate task management code.

7. Use System-provided Views

SwiftUI provides several pre-built views such as List, Form, Picker, and more. By leveraging these, you can reduce the amount of custom code you need to write.

struct TaskListView: View {
    var tasks = ["Task 1", "Task 2", "Task 3"]

    var body: some View {
        List(tasks, id: \.self) { task in
            Text(task)
        }
    }
}

In this TaskListView, we use SwiftUI's List view to display a list of tasks. This eliminates the need to manually create and manage a list of views.

These tips should help you keep your SwiftUI codebase DRY and maintainable. Remember, the goal of reducing code duplication is to make the code easier to maintain, read, and debug. Always keep this in mind when making decisions about how to structure your SwiftUI code.

You may also like: SwiftUI Magic: 7 Lesser-Known Features That Will Make Your Apps Stand Out

I hope you enjoyed this article, and if you have any questions, comments, or feedback, then feel free to comment here or reach out via Twitter.

Thanks for reading!