10 tips to increase your iOS code quality (pt. 2)

Boost your Swift programming expertise and optimize your iOS app code

Bruno Lorenzo
4 min readOct 31, 2023

Quick and straight to the point, here are 10 tips that you can adopt in your iOS projects.

If you want to check part 1 and add another 10 tips to your toolkit, here it is πŸ‘‡

1. Composable UI

Break down your views into smaller pieces to make them more readable.

If you want, go one step further and make some reusable views to avoid code duplication.

struct HomeView: View {
var body: some View {
VStack {
headerView
mainView
footerView
}
}
}

// MARK: - UI Components
private extension HomeView {
var headerView: some View {...}
var mainView: some View {...}
var footerView: some View {...}
}

2. Reusable styling with view modifiers

If you have some custom styling that repeats across the app, take advantage of SwiftUI view modifiers to maintain the code in one place.

struct TitleStyle: ViewModifier {
func body(content: Content) -> some View {
content
.font(.system(size: 22, weight: .bold))
.foregroundColor(Color.black)
}
}

extension View {
func titleStyle() -> some View {
modifier(TitleStyle())
}
}

struct HomeView: View {
var body: some View {
Text("Hello!")
.titleStyle()
}
}

3. Include Unit Tests

One of the most undervalued processes that will considerably improve your code quality.

When adding a new piece of logic to your code, think about how would you ensure its correctness. Write a unit test and run your test cases. It will save a ton of time later.

4. Error handling

Don't be afraid of using throws. It's a great way to propagate errors without much effort.

enum NetworkError: Error {
case fetching(Error)
}

func fetchData(from url: URL) throws -> Data {
do {
let data = try Data(contentsOf: url)
return data
} catch {
throw NetworkError.fetching(error)
}
}

func fetchProducts() throws -> [Product] {
let productsURL = URL(string: "https:\\myapi.com/products")
let data = try fetchData(from: productsURL)
return try JSONDecoder().decode([Product].self, from: data)
}

do {
let products = fetchProducts()
} catch NetworkError.serverError(let message) {
print("Server error: \(message)")
} catch NetworkError.networkError(let error) {
print("Network error: \(error.localizedDescription)")
} catch {
print("An unknown error occurred: \(error)")
}

5. Code documentation

I'm a strong believer that the best documentation is the auto-document code. However, if you're designing a complex API or library, providing custom documentation will help others better understand your code interfaces.

It's super easy to add, just double-click on the function you want and click on Add Documentation.

/// Create a new request with the information provided
/// ```swift
/// do {
/// let request = try createRequest(from: .signing)
/// } catch {
/// print(error)
/// }
/// ```
/// - Parameter endpoint: Endpoint to perform the request
/// - Returns: A URLRequest instance with the information provided in `endpoint`
func createRequest(from endpoint: ApiEndpoint) throws -> URLRequest {...}

6. Enums

Use enums if you need to model states, options, or configurations. They provide a type-safe and self-documented way of representation.

You can accomplish more than you think.

enum AppTheme {
case light
case dark
case custom(primaryColor: Color, backgroundColor: Color)
}

7. Core Data + SwiftUI

If you're using Core Data in your app, use @FetchRequest property wrapper to get data directly in a View.

struct HomeView: View {
@FetchRequest(sortDescriptors: [SortDescriptor(\.id, order: .reverse)])
private var users: FetchedResults<User>

var body: some View {
VStack {
List(users) { user in
Text(user.name ?? "Unknown")
}
}
}
}

8. Coding Style Guide

Define a style guide for your team to provide a set of coding conventions and best practices to maintain consistency across your project.

Your style guide could include information like:

  • Naming conventions
  • Code formatting
  • Documentation
  • Files and project structure
  • Error handling
  • Swift language features to use
  • Testing best practices

9. Dependency injection

Use it to enhance modularity, maintainability, and testability of your code. DI promotes the Single Responsibility Principle, encouraging components to focus on a single task.

10. Design System

Create a Design System to manage all UI components in a flexible and reusable way. It will help to scale your app and adapt to possible changes in the future.

If you never made a DS, a good starting point is to define a manager for your app's font and labels. You can combine it with custom view modifiers and create a visual representation to serve as a guide.

Have any questions? Feel free to drop me a message! πŸ™‚

  • πŸ€“ Join me on X for regular content on iOS development tips and insights
  • πŸš€ Check out my GitHub where I share all my example projects

--

--

Bruno Lorenzo
Bruno Lorenzo

Written by Bruno Lorenzo

Software Engineer | Innovation Manager at www.houlak.com | Former iOS Tech Lead | I write about iOS, tech, and producitivy

Responses (4)