
13. Dec 2022
iOSOur iOS tech stack for mobile app development
A tech stack provides product teams with the tools they need to build and maintain products that truly meet users’ needs. It typically includes programming languages, frameworks, analytics tools, architectural patterns, and more.


Mobile apps today face high expectations in terms of performance, security, and user experience. To meet those demands, we rely on a reliable and modern tech stack that helps us deliver high-quality solutions quickly, efficiently, and sustainably.
So what does the technology behind our iOS apps look like? Let’s take a peek behind the scenes of our development process.
Programming language
Swift
Swift is a modern, powerful, and safe programming language developed by Apple, designed for building applications across iOS, macOS, watchOS, and tvOS. It was created as a successor to Objective-C, offering a simpler, more readable, and secure approach to app development.
Today, Swift is our primary language for native development. For all new projects, and selected existing apps, we’re already actively adopting the latest version, Swift 6, which introduces advanced support for Swift Concurrency, including stricter rules for safe data access (strict concurrency checking).
This modern approach to asynchronous programming improves code readability and maintainability, which in turn positively impacts the overall quality of the final product.
UI Frameworks
When building user interfaces today, we primarily rely on SwiftUI - Apple’s modern UI framework that enables us to design clean, consistent interfaces with less code and greater efficiency.
UIKit, the former standard, is still used in specific scenarios – particularly where SwiftUI doesn’t yet support certain technical requirements or where backward compatibility with older iOS versions is necessary.
We’re able to combine both approaches when needed. This gives us the flexibility to efficiently build new products while also modernizing existing applications.
You can read more about our experience with SwiftUI in the article 👇

UIKit
At GoodRequest, UIKit is no longer our primary UI framework, but it remains in use across several existing iOS projects where it was originally implemented during earlier phases of development.
The Framework includes components designed for creating user interfaces for iOS, iPasOS, WatchOS or tvOS applications.
It provides an architecture for creating UI, infrastructure for processing user inputs and interaction between the user, the system and our application.
SwiftUI
SwiftUI is a modern framework that we use today as the main tool in UI development for Apple platforms. It has replaced UIKit in new projects and is gradually becoming a standard within existing applications.
The advantage is a declarative approach to programming that simplifies the process of creating a user interface, the ability to cooperate with UIKit. Previews are a big help, with the help of which the developer can almost immediately see all the changes made without the need to launch the application
Internal frameworks
In addition to working on projects for clients, we also spend time building our own library ecosystem. This helps us standardize development, streamline repetitive tasks, and improve code quality across projects.
You can read more about how we designed these libraries and where they're used everywhere today in our article 👇

Exploring our iOS toolbox: sharing our codebase with the world
GoodNetworking
GoodNetworking is a library focused on communicating with REST APIs. It takes care of request configuration, response handling and basic error handling scenarios. It is designed to support different application layers and be easily extensible.
GoodReactor
GoodReactor implements the Reactor architectural pattern, which extends the MVVM concept. It allows to efficiently manage the state of screens and respond to user actions through a defined data flow. The library provides the basic building blocks for a consistent implementation of this architecture.
GoodPersistence
GoodPersistence s a framework for working with local storage. It simplifies working with data stored in, for example, UserDefaults or Keychain, and offers a type-safe API for storing and reading data within an application.
iOS Extensions
"By developers for developers", GoodExtensions library is a collection of modules and enhancements from server communication to text formatting that make the work of our developers easier.
Package management
SPM
In our iOS projects today, we primarily use Swift Package Manager (SPM) as it is natively integrated in Xcode and allows for simple and efficient dependency management.
Swift Package Manager (SPM) is a tool for managing the distribution of code written in the Swift language. The advantage is that we can integrate dependencies into projects directly through Xcode. Unlike CocoaPods, the files are only stored on local devices and do not "inflate" the project size. SPM now supports most common libraries, including Firebase, and is therefore our preferred choice for new projects.
Tools
SwiftLint
This tool helps developers maintain good code readability and ensures that the conventions and style are followed when writing code in Swift. SwiftLint alerts the developer to their errors directly through the Xcode UI.
SwiftFormat
SwiftFormat is a tool for automatically formatting code. SwiftFormat can automatically edit spacing, add or remove implicit self, remove unnecessary parentheses, and remove other deviations from the standardized idioms of the Swift language.
Logen
Logen is an internal tool written in Python that helps developers generate localized strings for Swift projects directly from a Google Docs spreadsheet.
Swiftgen
SwiftGen is a tool for automatically generating Swift code, specifically for resources such as colors, images or localized strings, so that they are type-safe.
Analytical services
Firebase
We use the Firebase platform to collect analytical data, monitor applications and deliver notifications, which covers several areas of mobile application development and operation.
We use Firebase Cloud Messaging to deliver push notifications. The main advantage is the unified integration on the back-end side, thanks to which the service communicates with both iOS and Android apps automatically.
Firebase Crashlytics provides automatic collection of information about app failures in production. It allows us to track, prioritize and resolve them efficiently, contributing to higher app stability.
Firebase Analytics provides us with a detailed view of user behavior. Tracking app interactions and events helps us optimize both the user interface and business decisions.
Firebase Remote Config allows you to change the behavior or appearance of your application remotely - without the need to release a new version. We use it, for example, when experimenting with different variations of functionality or content.
CI/CD process
Continuous Integration and Delivery (CI/CD) allows new code to be integrated more often without reducing the quality of the application itself. CI/CD is designed to automate repetitive tasks such as build, test, and deploy, and to flag potential problems. We primarily use three tools for these purposes.
Fastlane
Fastlane is an OpenSource platform designed to simplify the process of deploying iOS applications. Fastlane allows us to automate almost every aspect of our work flow in the software development or release phase.
Bitrise
It allows developers to automate basic workflows, allowing us to combine common tasks such as deploying to a tester, informing the team on Slack about a new version, or increasing a version number.
Danger JS
Danger is a tool deployed as part of the CI process. It gives us the opportunity to automate the work associated with code review and commenting on our PRs based on predefined rules. This allows the development team to focus on more complex issues in the code review process.
Architecture
MVVM
It makes it easy for developers to separate UI development from logic development. It then looks like this in projects: View and ViewModel are defined separately, View has its own ViewModel assigned. View takes care of all user interface components and displaying data from the associated ViewModel. The responsibility of the ViewModel is to ensure the necessary handling of the data displayed by the View.
Reactor
Reactor was created as a combination of Flux and Reactive Programming.
View is used to display data. Reactor is a layer independent of the user interface, it manages the state of the View.
In practice, the flow looks like this: View sends Reactor an action, for example, based on some user input. The Reactor "reacts" to the given action, performs all the logic defined as a reaction to the given action, and as a response the View returns the state, which causes changes to the View.
Coordinator
We use Coordinator pattern to organize the navigation between screens in the application. It allows you to separate the logic of transitions from the UI itself, which increases the readability, repeatability, and testability of the code.
We have implemented this approach as part of the GoodReactor library, where it serves as a natural extension to the Reactor architecture. This allows us to manage navigation consistently with other layers of the architecture without unnecessarily complicating the View or Reactor layer.
Technologies that give our applications a solid foundation
Our iOS tech stack is constantly evolving along with the technologies we use. We keep an eye on current trends, test new approaches, and actively build our own ecosystem of tools and libraries that help us maintain high quality development.
The goal is always to deliver solutions that are sustainable, stable and also ready to scale according to our clients' needs.
If you're interested in learning more about our work, feel free to check out our other blog articles.

Related articles

App Intents: How to make your app more accessible through Siri, Spotlight, and Widgets


App Intents tips and tricks: How to make iOS apps more accessible than ever


How to build a successful iOS app using overlooked features
