15.
Publishing in the Real World
Written by Pietro Rea & Keegan Rush
By this point, you’ve come quite a distance on your app distribution journey. You know how to deploy your app on TestFlight and the App Store, and you’re well-versed in the process of automation. Distributing Emitron has been straightforward, without too many problems along the way — but that’s not always the case with app distribution.
In the diverse world of iOS app distribution, you’ll find companies of varying sizes and differing needs. Some companies build similar apps for many clients with client-specific branding. Others have a strong need for security and testing, such as large banks. Here, you’ll typically find a slow and strict release cycle. Small startups, on the other hand, are more comfortable with playing fast and loose with their releases.
In this final chapter, you’ll reference everything you’ve learned so far. You’ll test your new skills by exploring the needs of different organizations. Each section in this chapter is dedicated to problems that different companies face in the real world. So, get ready, it’s time to put what you’ve learned into practice!
White labeling
How do you order a pizza from your favorite pizza place? You’ll find many popular pizza restaurants in every neighborhood, and they all share common needs. Every restaurant needs to manage stock, process payments and receive orders.
As an app developer, there’s an opportunity lying in those overlapping requirements. Since all pizza restaurants have the same needs, wouldn’t it be easy to build the same app for each restaurant? You’d only need to change the branding: the app’s icon, name and possibly some aspects of the design.
A white-label app is a generic app that you recompile and rebrand to fit the client’s needs. You could create apps for all the pizza places in your city by making a single, generic pizza restaurant app and then white labeling it for each specific client.
Using what you learned in Chapter 9, “Build Customizations”, white labeling is a breeze.
White labeling with build configurations
In Chapter 9, “Build Customizations”, you set up different build configurations for Emitron to create dev, beta and release builds. You use a similar trick for white labeling.
Say you have two clients that both want a pizza restaurant app, one named Paulie’s Pizza and another named Cheesy Dining. There’ll be some differences between the two such as:
- App icon
- Bundle identifier
- App name
- Restaurant name
These are all bits of information that you can update with build configurations. First, create two build configurations, one for each restaurant. Then, use the configurations to swap out values for branding unique to each restaurant for every build. In Chapter 10, “Advanced Build Configurations”, you learned how to use build configuration files, which make this job easier.
Once you have your build configurations set with the correct values, you can put them into use by creating one schema for Paulie’s Pizza and another for Cheesy Dining. To build the app for either client, just build the appropriate schema. You consider each schema as its own separate app, which you release on the App Store using what you learned in Chapter 3, “Submitting Your First App for Review”.
Fast deployments
When you’re part of a small, scrappy startup, time to market is critically important. If you’ve completed work that brings value to your users, it’s best to get it into their hands as soon as you can. That means getting new features through the software development lifecycle as quickly as possible, from idea to implementation, testing and, finally, release.
While you could just make it a personal goal of yours to always be on the ball, providing new builds to testers as soon as the code is on GitHub, it makes more practical sense to take advantage of automation and all its benefits. In Chapter 12, “Build Automation”, you learned all about automation. By reducing the effort it takes to compile and archive your app, you make it easy to publish frequent builds.
With a build in hand, you still need to deliver it to testers. You can automate this step, too. In Chapter 14, “Continuous Integration”, you learned how to build your app in the cloud with GitHub Action’s jobs and triggers. On that note, you can take GitHub Actions even further by implementing continuous delivery.
Continuous delivery
While continuous integration helps you merge the team’s work and provide feedback on the build through automated tests, continuous delivery supports build distribution to testers.
Continuous delivery builds on the foundations of continuous integration — you just add more jobs to your existing workflows to distribute the build. On iOS, this means including the appropriate code signing and provisioning. Thanks to Chapter 4, “Code Signing & Provisioning”, you have the tools you need to sign and distribute your builds.
For the fastest of deployments, you’ll start with a trigger that kicks off a build whenever a pull request is merged into the main branch. That way, once a developer completes a feature and merges it, the CI/CD server will provide a new build for testers. Your workflow will then build the app, sign it and distribute it to TestFlight (see Chapter 6, “TestFlight”) or the platform of your choice.
With continuous deployment publishing your builds after every merged pull request, you can focus on the code and let automation do the busy work for you. And, when you’re ready, your build is already waiting to be released to the excited hands of your users.
Smooth app reviews
Continuous delivery provides a stable, predictable build pipeline. Sometimes, however, building your app is only half the battle.
To ensure quick time to market, you need to get ready for App Review, too. Refer to Chapter 7, “Preparing for App Review”, to brush up on the App Store guidelines and to know what to do when something goes wrong.
Frequent updates
A helpful addition to your CI/CD pipeline is a job that shares the build’s state. You can accomplish this in a few ways:
- Send an email at the end of the build.
- Send a Slack message to a dedicated channel in your organization.
- Show the current build state in a physical build screen in your office.
If you see a red build status coming through in a status update, make sure to fix the build to keep your deployments running regularly!
Different environments
While some companies value quick releases, others have a stronger need for extensive testing. Companies dealing with sensitive information, such as banks and other financial institutions, go through rigorous testing cycles. Releases are larger and can take months to reach the App Store.
Usually, when working with such sensitive data, you don’t test on the production server at all. This prevents any mistakes from happening in the same environment that customers rely on for their day-to-day work. Instead, multiple back-end environments allow developers and testers to play around with zero risk to the client’s production database.
A common pattern to use with multiple back-end environments is to have three servers:
- Development
- Staging
- Production
Once a build passes initial testing on the Development environment, the team makes the build available on the Staging environment. Then, once the build is ready for release, the team switches it to the Production environment.
Implementing different environments
To swap out the environment, you’ll make use of build configurations, similar to the approach you use for white labeling.
First, you’ll create build configurations for each environment you have.
Note: If you’re using the development, staging and production approach outlined above, you only need to create one build configuration: staging. The
debugconfiguration uses yourdevelopmentenvironment andreleaseusesproduction.
Then, create a new build setting for the app environment, which you’ll set to the URL for your environment. For example, https://staging.emitron.com/api for Emitron’s Staging environment, https://dev.emitron.com/api for Development, and so on.
In Chapter 11, “Managing Secrets”, you learned how to reference build settings in code. You’ll need to follow that approach so you can access your environment URL. Finally, use that URL to make any API calls.
You can also change the bundle identifier so one device can install apps for more than one environment. Don’t forget to change the product name and app icon for builds on a different environment. Otherwise, you might just do your testing on Production by mistake!
Alternative hosting
While TestFlight is a remarkably convenient option for testing alpha builds, it isn’t the only choice available. Other platforms, such as AppCenter and Bitrise, also host builds for internal distribution. AppCenter facilitates analytics and crash reporting as well, making it a convenient solution for managing your app.
Companies that place a premium on security aren’t always comfortable hosting their builds on third-party solutions, including Apple’s TestFlight. Some choose to use ad-hoc distribution and manually host their builds on an internal company website.
See Chapter 5, “Internal Distribution”, for more on ad-hoc and enterprise builds.
One app, many teams
Besides rigorous testing, large companies face another problem that can be solved with your newfound understanding of app distribution: the coordination of large teams. There’s a limit to how many iOS developers you can put in a room to work on the same app. With too many developers on one team, the team becomes increasingly prone to communication and coordination problems.
Continuous integration alleviates many of these problems. Even with continuous integration in place, however, you’ll find it challenging to grow a team past a certain point.
Does that mean you can only have a handful of developers working on the same app? Not at all! One strategy that larger organizations apply is to use multiple teams of developers and testers to work on an app. Each team is self-organized and responsible for a certain feature or section of the app.
However, when multiple teams work on the same codebase, you still need to worry about merge conflicts and broken builds. So, there’s still not enough separation to ease the coordination issues of working with so many developers.
Rather than working together on the same codebase, each team can develop their proprietary codebase and avoid conflicts by using frameworks.
Building with frameworks
Leveraging frameworks is a great strategy to share code with others. In this context, each team builds its own framework to integrate into the main app. The codebase for the main app is, for the most part, an empty shell that integrates each framework.
For any code that needs to be shared between teams, you just use — you guessed it — another framework!
When it’s time to build the main app for testing and distribution, a CI/CD server compiles the main codebase. The build script pulls in stable versions of each team’s frameworks through a dependency manager like Swift Package Manager or CocoaPods.
This approach lets teams work independently of each other. It also dramatically reduces the compile time in large apps because a team is only ever compiling its own framework. That framework then links to stable versions of any other frameworks it depends upon.
Multiple platforms
Besides sharing between teams on the same iOS app, you can use frameworks to share code between platforms — for example, between the iOS, iPadOS, macOS, tvOS and watchOS team. To take things further, you can also create a framework to share code between an iOS and Android app.
To do so, you’ll need to step out of your Swift comfort zone. Cross-platform frameworks are often written in C or C++, but you can also use a modern language like Rust, if your C++ is a little rusty itself. :]
Automating with fastlane
Distributing an app takes a great deal of work, but it doesn’t need to be that way every time. In Chapter 13, “Introduction to Fastlane”, you learned how to use fastlane to automate your build. Actually, fastlane can do a whole lot more than just building your app.
Fastlane’s utility begins before you’ve written a single line of code. You can use fastlane to create an app record in App Store Connect, just as you learned in Chapter 2, “Your First App in the App Store”. You can manage all of your app’s metadata, including:
- Review information
- Name, description and subtitle
- Copyright details
Once you’ve built your app, you still need to do a lot of manual work. You need to upload the appropriate screenshots for a number of different devices to App Store Connect. What’s more, if you’ve localized your app into different languages, you’ll need screenshots for each of those languages, too!
Thankfully, taking screenshots is a breeze with fastlane. Its snapshot action hooks into your UI tests to take screenshots for you.
With fastlane, you can go from compiling, to submitting your app for review, to publishing it on the App Store, all from the command line. That is, if you’re brave enough! :]
After release
For many developers, one of the hardest aspects of app development has nothing to do with writing code.
If you’re an indie developer releasing your own app, you have to manage every aspect of your app’s successful release on your own. That means marketing, support, product management and more.
Some snazzy screenshots and an app preview video can entice people to download your app. Besides that, learning a bit about App Store Optimization is a great first step to promoting your app in the App Store. You may also want to focus your efforts elsewhere with a spirited campaign of inbound marketing.
Take a look at Chapter 8, “App Approved! (Now what?)”, to get started on supporting your app after release. Beyond that, you may want to start using organization tools like Trello: https://trello.com/ and Notion: https://www.notion.so/ to plan and track your strategy.
Key points
- Different companies face different challenges. You can use the knowledge gained in this book to help solve them.
- White labeling lets you reuse the same code base for multiple clients.
- When time to market is a key factor, invest time in automating daily builds.
- For rigorous testing, consider setting up multiple environments.
- TestFlight is a convenient hosting solution for test builds, but some companies host their in-house builds for added security.
- Teams can share code using frameworks.
- Fastlane has a lot to offer in the world of automation, even from the first day of coding out a new idea.
- Your journey doesn’t end once your app is released. Managing your app is as important as writing the code.