iOS

Hero image for iOS

Project Structure

To keep all current and upcoming iOS projects aligned, an iOS project’s file organization is standardized by following the below structure:

Common

.
├── README.md
├── Modules
│   ├── Data
│   │   ├── Sources
│   │   │   ├── NetworkAPI
│   │   │   │   ├── Interceptors
│   │   │   │   ├── Models
│   │   │   │   ├── RequestConfigurations
│   │   │   │   ├── Core
│   │   │   │   │   ├── NetworkAPIError.swift
│   │   │   │   │   ├── NetworkAPIProtocol.swift
│   │   │   │   │   └── RequestConfiguration.swift
│   │   │   │   └── NetworkAPI.swift
│   │   │   └── Repositories
│   │   └── Tests
│   │       ├── Resources
│   │       └── Sources
│   │           ├── Dummies
│   │           │   ├── DummyNetworkModel.swift
│   │           │   └── DummyRequestConfiguration.swift
│   │           ├── Specs
│   │           │   └── NetworkAPISpec.swift
│   │           └── Utilities
│   │               └── NetworkStubber.swift
│   └── Domain
│       ├── Sources
│       │   ├── Entities
│       │   ├── Interfaces
│       │   └── UseCases
│       │       └── UseCaseFactoryProtocol.swift
│       └── Tests
│           ├── Resources
│           └── Sources
│               └── DummySpec.swift
├── {ProjectName}
│   ├── Configurations
│   │   ├── Plists
│   │   └── XCConfigs
│   ├── Resources
│   │   ├── Assets
│   │   ├── Languages
│   │   └── LaunchScreen
│   └── Sources
│       ├── Application
│       │   └── Varies by UI Interface
│       ├── Constants
│       │   ├── Constants+API.swift
│       │   └── Constants.swift
│       ├── Presentations
│       │   └── Varies by UI Interaface
│       └── Supports
│           ├── Builder
│           │   └── Builder.swift
│           ├── Extensions
│           │   ├── Foundation
│           │   └── UIKit
│           └── Helpers
│               ├── Typealias
│               └── UIKit
├── {ProjectName}Tests
│   ├── Configurations
│   │   └── Plists
│   ├── Resources
│   └── Sources
│       ├── Dummy
│       │   ├── Data
│       │   │   └── Models
│       │   ├── Domain
│       │   │   └── Entities
│       │   └── Modules
│       │       └── Home
│       ├── Mocks
│       │   ├── NetworkAPIMock.swift
│       │   └── Sourcery
│       │       ├── AutoMockable.generated.swift
│       │       └── HomeViewModelProtocolMock+Equatable.swift
│       ├── Specs
│       │   ├── Presentation
│       │   │   ├── Modules
│       │   │   └── Navigator
│       │   └── Supports
│       │       └── Extensions
│       └── Utilities
│           ├── Data+Decode.swift
│           ├── String+Data.swift
│           └── TestError.swift
└── {ProjectName}KIFUITests
    ├── Configurations
    │   └── Plists
    └── Sources
        ├── AccessibilityIdentifiers
        │   ├── Login
        │   └── Home
        ├── Flows
        │   ├── Login
        │   └── Home
        ├── Screens
        │   ├── Login
        │   └── Home
        ├── Specs
        │   ├── Login
        │   └── Home
        └── Utilities
            └── KIF+Swift.swift

SwiftUI

.
└── {ProjectName}
    └── Sources
        ├── Application
        │   ├── {ProjectName}App.swift
        │   └── AppDelegate.swift
        └── Presentation
            ├── Models
            │   └── ProductUIModel.swift
            ├── Coordinators
            │   └── AppCoordinator.swift
            ├── Modules
            │   ├── Home
            │   └── Login
            ├── Styles
            │   └── RoundedButtonStyle.swift
            ├── ViewModifiers
            │   └── View+PrimaryNavigationBar.swift
            ├── Views
            │   └── SearchBarView.swift
            └── ViewIds
                └── ViewId.swift

UIKit

.
└── {ProjectName}
    └── Sources
        ├── Application
        │   ├── AppDelegate.swift
        │   ├── Application.swift
        │   └── SceneDelegate.swift
        └── Presentation
            ├── Modules
            │   ├── Home
            │   └── Login
            ├── Navigator
            │   ├── Navigator+Scene.swift
            │   ├── Navigator+Transition.swift
            │   └── Navigator.swift
            └── Views
            │   ├── Button
            │   ├── CollectionView
            │   ├── TextField
            │   └── Transition
            └── ViewIds
                └── ViewId.swift

README.md

README.md introduces the overview of the project, for example:

  • What is the main feature of the project?
  • How to set up the project?
  • What are project configurations?

{ProjectName}

This folder contains the main sources of the project. There are three sub-folders:

  • Configurations: This folder contains only project configurations files, such as Info.plist, .xconfig, .entitlements, etc.
  • Resources: This folder contains only resources files, such as .plist, .json, .tff (fonts), .storyboard, .strings, .der (SSL certificates), etc.
  • Sources: This folder contains only .swift files - the main source code of the project.

{ProjectName}Tests

This folder contains the unit testing and integration testing of the main project.

{ProjectName}UITests

This folder contains the UI testing of the main project.

Modules

This folder contains modules that represent targets in the project. Currently, it contains the Data and Domain folders.

  • Data: This folder contains two subfolders
    • Sources: This folder contains only .swift files, the module’s main source code.
    • Tests: This folder contains the unit testing.
  • Domain: This folder contains source files and Unit Tests for the Domain target.
    • Sources: This folder contains only .swift files, the module’s main source code.
    • Tests: This folder contains the unit testing.

Development Tools

Xcode

Always use the latest version of Xcode available in the App Store or DMG. The exception is for an existing project in the transition phase. The project that cannot be compiled in the latest Xcode version should use the latest minor version instead.

Cocoapods

Cocoapods manages iOS packages to keep consistency throughout development machines.

Simulator

  • While developing, use multiple simulators with varies screen sizes, with the latest OS version provided by the current version of Xcode.
  • Sometimes older simulators are needed and can be downloaded from Xcode’s menu
Product > Destinations > Add Additional Simulators

Add Simulator

  • An example set of simulators for Xcode 13 that covers most of the cases is made up of:
    • iPhone 13 Pro Max with iOS 15.0: Large screen with the latest OS.
    • iPhone 8 with iOS 15.0: Small screen with the latest OS.
    • iPhone 8 with iOS 10.0: Device supporting the oldest OS.

Fastlane

Fastlane automates test, build, and most importantly: certificates and profiles which are a core part of the App Store ecosystem.

Debugging Tools

Wormholy

Wormholy is an iOS network debugging, it supports viewing and checking networking calls directly on the device.

Wormholy

View networking calls with easy to integrate library.

  • Modify network speed on an iOS device to simulate slower network or data loss.
  • Network Link Conditioner is available in iOS Device’s Settings.
Settings > Developer > Network Link Conditioner

Developer menu is available when the device is plugged into Xcode.

Proxyman

  • Inspect network calls of simulators and real devices.
  • Catch and inject custom requests/responses for easier debugging.

Database GUI

  • Debugging some APIs is not possible by inspecting the payload only. Some require a peek in the database to identify the underlying bug. Database GUI helps developers to navigate the database. Example includes TablePlus and Postico.

Screen Recording

  • Application such as Kap and Gifox make it easier to capture and convert screen recordings to share on GitHub.