18 Build & Release an iOS App¶
In this chapter, you’ll learn how to use Xcode and TestFlight to distribute your Flutter app’s iOS version.
Unlike with Android, apps can’t be sideloaded onto iOS devices. To distribute your app to users and testers, you have to go through App Store Connect, Apple’s developer portal for the App Store. TestFlight allows you to send apps to testers and gather feedback from both your internal team and the outside world.
For this chapter, you’ll need to use a Mac with Xcode installed. You’ll also need a valid Apple Developer Program account to access the App Store.
If you’re following along with your app, open it and keep using it with this chapter. If not, locate the projects folder for this chapter and open the starter folder.
Note: If you use the starter app, don’t forget to add your apiKey and apiId in network/recipe_service.dart. Also, run
flutter pub get
from the IDE’s terminal.
Run your app on an iOS simulator to set up the necessary files in the iOS folder.
Creating the signing¶
It’s time to leave Android Studio (or VS Code) and move over to Xcode. Open starter/ios/Runner.xcworkspace. This workspace includes the main app projects and the CocoaPods dependencies you need to build the app.
In the Project navigator, check if there’s a folder arrow next to Pods and has a blue icon next to it as shown below.
If not, close the Xcode project, return to Android Studio and run your app on an iOS simulator. This will pull all the required files. When you’re done, re-open starter/ios/Runner.xcworkspace.
Select Runner in the Project navigator to open the project editor. Select the Runner target and open the General tab.
For app submission, it’s important to check the Bundle Identifier. This has to be unique for your app. If you want to follow along with this tutorial to test out the process — that is, not submit — you still have to change the existing value. Try using a random unique string if you are out of ideas.
Creating an Apple Developer Program account¶
If you already have a valid Apple Developer Program account, move on to the next section: Creating an app identifier.
If you want to enroll in the Apple Developer Program, open https://developer.apple.com/accountand sign in with your Apple ID. If you see a page prompting you to join the Apple Developer Program, you need to click the link and follow the instructions to enroll.
The instructions are ever-evolving, so this chapter won’t explain them. Just follow the prompts, enter all your personal or business information and pay the fee. Once registered, you’ll be able to access the Apple Developer Portal and the App Store.
Creating an app identifier¶
In the developer portal, you’ll tell Apple about your app.
From https://developer.apple.com/account, click Certificates, IDs & Profiles from the Program Resources.
From there, choose Identifiers to get to the identifiers list. This list contains all the app identifiers associated with your developer account. It will include all the IDs you create manually or through Xcode.
Click the + button to create a new identifier.
You’ll see a long list of identifiers supported by the portal. For this task, select App IDs and click Continue.
You’ll get a chance to choose between an App and an App Clip.
Note: App Clips are lightweight versions of your app that users can download quickly and start using. Later, they can download the full app. At the time of writing, these are only experimentally supported with Flutter and are out of the scope of this book. See https://flutter.dev/docs/development/platform-integration/ios-app-clipfor more details.
Choose App and click Continue.
Next, you have the opportunity to set an explicit App ID.
Copy the Bundle Identifier you previously chose for your app from Xcode and paste it in the Bundle ID field. Remember, this has to be unique so don’t use com.raywenderlich.recipefinder.
Next, set the description. This is for your use only. It helps you find the app you want from a long list in the console as you make more apps.
There’s also a long list of Capabilities, which are special entitlements that let your app access parts of the operating system, hardware or Apple’s Cloud services. The app for this chapter doesn’t require any special capabilities, so you don’t need to worry about setting up any of these.
Click Continue, then Register. After a moment for processing, you’ll see the app ID listed in the Identifiers list.
Now that Apple knows the identifier, you need to update Xcode. You’ll bounce back and forth between the web and Xcode a few times.
Setting the team¶
From the project editor, click the Signing & Capabilities tab. This will allow you to select a team. Select your developer team in the drop-down. If you aren’t signed in through Xcode, choose Add an Account… to sign in.
Once you’ve set the team and fixed any errors, Xcode will create the signing certificates.
Note: Instead of letting Xcode manage your app profile, you can deal with those issues manually. You usually do this if you’re working in a continuous integration environment. Manual signing is outside the scope of this book, but it’s covered in iOS App Distribution & Best Practices: https://www.raywenderlich.com/books/ios-app-distribution-best-practices.
Setting up the App Store¶
When you submit an Android app, you first have to have a Google Play developer account and then set up the app in the Play Store. For iOS (and macOS) apps, you need to follow the same procedure for Apple.
The first step is to set up a spot for the app in App Store Connect. This is Apple’s administrative console for developers in the App Store.
Navigate to the App Store Connect website: https://appstoreconnect.apple.com/
Note: You’ll need a valid Apple Developer Program account to access App Store Connect. If you log in and see an Enroll button, then you still have to sign up. Use the instructions above to create an account.
Creating a new app¶
Before you can upload and distribute a build, you first have to create a record for the app by adding some basic information.
From the main App Store Connect login menu, select My Apps. This is where you’ll create your app’s store listing.
To create a new app record, click the + button and select New App.
You may have to accept the App Store terms and conditions or enter business or legal info. This might happen now or at any point in the process. The site will let you know when you need to agree and will not let you proceed otherwise. Any time you see that request, resolve the issue and come back.
You’ll see a window where you can fill in some basic app information:
Fill in the following information:
- Select the iOS platform.
- Name is important here because your customers will see it. As with the Android app, you’ll need to use something unique. Recipe Finder is already taken, and you’ll get an error message if you pick a name that someone has already used.
- Primary Language is the default language for the app — in this case, US English.
- For Bundle ID, select the identifier you used in the developer portal from the drop-down. If it doesn’t show up here, go back to the Identifiers list and make sure you created an app ID.
- SKU is a unique identifier used for financial reports. Pick one that you’ll recognize when counting the money. :]
- User Access controls access to your team’s App Store Connect users. This is important if you have a large team and don’t want to show the app to everyone in your organization.
When you’re done, your responses should look like this:
Click Create and you’ll see a new screen showing your app’s App Store Connect entry.
Voilà! Your app is now ready for you to upload.
Uploading to the App Store¶
On Android, you made an appbundle to distribute to the Play Store. iOS has a parallel concept. You’ll need to build an archive to upload to the App Store. You can do this from either Xcode or the command line. For this chapter, you’ll use Xcode.
In Xcode, just above the section where you entered the Bundle Identifier, you’ll see the tiny app icon with a device.
To the right of the tiny app icon, click the device name and set the device to Any iOS Device as the build destination. This is important because you can make deployable builds only for actual devices, not the simulator.
When you upload your app to the App Store, you upload an app archive. To create an archive from the menu, go to Product ▸ Archive.
Archive builds the app for distribution and packages it for uploading to the App Store. You’ll see a progress bar across the top of your Xcode window.
When it completes, the Organizer window will pop up and display the archive.
The archive file contains the app binary along with metadata and symbols. The App Store will process this file and get the version that users will finally download on their devices.
Uploading the build¶
From the organizer window, click Distribute App.
You’ll see a list of distribution methods. Choose App Store Connect and click Next. The other options are for custom distributions typically used in enterprise contexts.
In the next dialog, choose Upload to send the build directly to Apple. The Export option creates an artifact that you can upload later, through other means. Click Next.
The next form covers distribution options. You have the option to strip the Swift symbols, which reduces app size. The other option is to upload the debug symbols, which makes it possible to symbolicate crash reports that come in from users. Click Next.
Note: With Xcode 14 bitcode apps are no longer accepted. By default, the Xcode project generated by Flutter is not bitcode-enabled. Flutter support for bitcode will be removed at a later date.
For more details on this see https://github.com/flutter/flutter/wiki/Creating-an-iOS-Bitcode-enabled-app.
The next form is about app signing. It’s easier to let Xcode manage your signing, but if you have a CI system doing your builds and uploading to the App Store, you’ll have more control with manual signing. For now, click Automatically manage signing then click Next.
If you have an Apple Distribution certificate, skip to the next step. If you don’t know what an Apple Distribution certificate is, then you’re in the right place.
You need a certificate to upload to App Store Connect. Xcode can generate one for you. If your account doesn’t have a certificate yet, you’ll see the following screen. Select Generate an Apple Distribution certificate and click Next.
While the certificate generates, you’ll see a screen with a spinning wheel. It can flash by or take a little while to generate. When it’s done, you’ll see the following screen. Be sure to read it.
You’ll notice that it warns you that the private key is stored locally and cannot be recovered if lost. Apple recommends saving the certificate and key in a safe place.
Click Export Signing Certificate, add a password and save it somewhere you can remember. After you’ve exported the certificate, click Next.
Xcode will then sign the app and prepare it for upload.
After Xcode creates the archive, the final form will show you the app contents and metadata. This includes any frameworks — such as Flutter — and other dependencies, as well as all the signing and entitlement information. Click Upload to send it to the App Store.
Now, it’s important that you’ve already set up the record in the App Store so there’s a place for this information to go. If there are no issues with App Store Connect, like having to accept agreements, then you’re done working in Xcode. Otherwise, resolve any errors and try again. Click Done when prompted.
In a few minutes, the app will show up under the iOS builds in App Store Connect. Go to https://appstoreconnect.apple.com/apps, click your app and go to the TestFlight tab. Select Builds ▸ iOS on the left to see the list of uploaded builds. You’ll see yours is Processing.
After some time, the status will update to Ready to Submit.
Alternately, you might see an error like Missing Compliance:
If there’s an error, follow the instructions at the link to fix it. If this is the first time you uploaded the build, you’ll likely get a compliance issue. Follow your local legal advice on how to answer those questions.
Once your app is ready to submit, you can continue with the TestFlight process.
Sharing builds through TestFlight¶
Now, you’re ready to test your build. There are two options for test builds: Internal Testing and External Testing.
Internal testing is for sharing within your own team or company for quality assurance or feedback. Typically, this includes other developers, quality engineers, product managers, designers and marketing specialists. Your mileage may vary.
External testing is for a limited group of testers. These can include people within your organization as well as beta test customers, friends, journalists and anyone you want to try your app before you release it.
Internal testing¶
You can begin internal testing as soon as the app finishes processing. To add testers from the TestFlight tab of the App store console, just select App Store Connect Users under the Internal Testing header.
Click + next to Testers.
You’ll get a list of users to add as testers. Internal testing is only open to users who have accounts in your App Store Connect. At a minimum, you’ll be listed as available. To add more people to your account, you’ll have to go through the Users and Access link from the top navigation bar.
Once you add a tester, they’ll appear in the Testers list.
That tester will have to accept the email invite before they can install a build.
The invite will provide instructions or a button to launch TestFlight. From there, the user will receive a prompt to install the app.
And that’s all it takes for the user to get your app on their device. From then on, the App Store will automatically notify your testers when a new build is available.
From the same Testers list in App Store Connect, you can monitor the app’s usage for crashes or feedback submitted through the TestFlight tool.
External testing¶
Internal testing is limited to a few people who are in your store account. Obviously, you don’t want to give store access to testers who aren’t part of your organization.
To get started with external testing, you first have to make a group. The App Store lets you separate testers into groups, so you don’t have to release every build to every tester. For example, you might want a test team to get every build, but update customer beta builds only once a week.
Click the + next to External Testing in the left navigation bar to create a new group.
You’ll see a window for you to enter the Group Name. Enter a name and click Create.
After you create the group, you’ll see it listed in the sidebar.
You can now add testers to your group. One difference from internal testing is that you can invite testers right from this panel. You can also create a web link to share, letting testers invite themselves to the group.
Before you can create a link or add users, you need to add a build. Click + next to Builds.
Apple reviews apps before it releases them to beta testers. The next window allows you to choose which build you wish to submit to Apple for Beta App Review.
Select the build that you want Beta App Review to test. Click Next to go to the next screen.
Next, enter contact information. This lets your readers supply user feedback and lets Beta App Review ask any questions they have. If your app has a login, you have to create an account that app review can use to log in and check out the app. Fortunately, Recipe Finder has no login. :]
Enter the information and click Next to continue.
Your last step is to enter a little message that will be included with the build notification. This an opportunity to ask people to check out certain things or to notify them about changes.
Enter a message and click Submit for Review.
This sends your build to Apple for a quick version of an app review. Within a short time — anywhere from a few minutes to a few days — the app will be ready to test, assuming there aren’t any issues.
Congratulations, now you can distribute the app for testing.
To submit your app to the App Store for download or purchase, you need to add all the information required under the App Store tab, such as screenshots, marketing copy, privacy policy and age rating.
Once that information is complete, you can submit your TestFlight build to the full app review. After testing, you can submit your app for release.
And there you have it: simple Flutter app distribution on iOS.
Key points¶
- You have to configure the Apple Developer Portal and App Store Connect before you can upload a build.
- Use Xcode to archive the project to easily upload your app to the App Store.
- Use TestFlight for internal and external testing of iOS apps.
Where to go from here?¶
If you want to take this to the next level and learn more about app signing or distributing and selling to customers in the App Store, then iOS App Distribution & Best Practices https://www.raywenderlich.com/books/ios-app-distribution-best-practices is for you.
Apple’s documentation is also helpful if you have questions about terms not covered here: https://developer.apple.com/documentation/xcode/distributing_your_app_for_beta_testing_and_releases.