The short answeriOS does what Android does: a sandbox per app, a lifecycle the system drives, permissions the user decides. Apple holds the keys: only code Apple has authorized runs, and every door is Apple's. An app the user leaves is frozen within seconds.
Same shape as Android, other keys
Three rows are the same idea, renamed. Three decide who holds the keys.
| Android capsule 02 | iOS | |
|---|---|---|
| The package | An APK | An .app bundle, in an .ipa |
| The contract | AndroidManifest.xml | Info.plist, plus entitlements: what Apple granted |
| The sandbox | A Linux user per app | A container per app |
| The certificate | Self-signed, no authority | Issued by Apple |
| The way in | Play, or an APK the user allows | Apple's doors only |
| Work after leaving | A declared foreground service, with a notification | A declared mode, or handed to iOS |
On Android, no authority vouches for your certificate. On an iPhone, nothing runs unless Apple authorized it.
Go deeper Inside the signature 1 min
Before anything runs, iOS checks the code signature. It is a hash of every file, signed with a certificate Apple issued to a named developer. Change one byte, and iOS will not launch the app. This covers the app's native code. JavaScript an app downloads, such as an Expo update, is not signed by Apple; the store's rules limit what it may change. Updates are capsule 10.
The signature carries the app's entitlements: the capabilities Apple granted, such as push notifications or iCloud. A provisioning profile ties it all together: who may sign, which app, on which devices, until when, with which entitlements. The App Store signs the app once more when it distributes it.
On Android, the certificate is self-signed: no authority stands behind it. On Google Play, Google keeps the app's signing key and signs what it delivers.
Go deeper Files and secrets 1 min
At install, iOS creates a container for the app: a folder with a random name, holding Documents/, Library/ and tmp/. The app reads and writes there, and nowhere else. Sharing goes through the system: the share sheet, the document picker, iCloud.
Files in the container are encrypted by default once the user has set a passcode, and readable from the first unlock after a restart. Secrets belong in the keychain, by default readable only while the device is unlocked. Where the data lives, and which copy is the truth, is capsule 05.
Every door is Apple's
iOS runs only code Apple has authorized. So every way onto an iPhone is a way Apple provides.
- The App Store, after App Review.
- TestFlight, for testers you invite.
- Your own devices, from Xcode.
- A company's staff, employees only.
In the European Union, Japan and Brazil, a law or a regulator added other doors. The fold below lists them.
There is no “unknown sources” switch. Apple is the doorman at every door.
Go deeper Where a law or a regulator opened other doors 1 min
In the European Union, a law brought alternative app marketplaces in iOS 17.4, and a developer's own website in iOS 17.5. In Japan, a law brought marketplaces in iOS 26.2. In Brazil, an agreement with the competition regulator brought them in iOS 26.5. In Japan and Brazil, only marketplaces install from a website.
These apps skip the App Store, not Apple. Each one is notarized: a baseline review by Apple of security and privacy, whatever the channel.
TestFlight takes up to 10,000 testers, invited by email or by a public link, each build for 90 days; the first build for outside testers is reviewed. Your own devices take a build from Xcode, a few days at a time with a free Apple Account. Delivery is capsule 10.
Checkpoint
A classmate sends you their app's .ipa file. Can you install it on your iPhone by opening the file?
See the answer
There is no unknown-sources switch on iOS. An app arrives through the App Store or TestFlight, or as a build whose profile lists your device. The developer's signature alone is not enough.
No purpose string, a crash
The first use of the camera shows a dialog. iOS draws it, not your app, and quotes your purpose string. Without that string, the request fails, and iOS usually crashes the app.
- The app asks for the camera. iOS shows its own dialog, with the app's name and its purpose string.
- The user allows or refuses. iOS stores the answer in Settings, and does not ask again.
- No purpose string: the request fails, and the app crashes at that moment.
The user answers once, and can change it in Settings. The app must work when the answer is no.
Go deeper Notifications, reviews, privacy labels 1 min
The camera, the microphone, the location, the photos and the contacts are protected resources, among others. Notifications ask for permission too, but need no purpose string.
App Review rejects a build whose code reaches a protected resource without a purpose string, even when only a library calls the API. The App Store listing shows what data the app collects. Since May 2024, a privacy manifest must also say why the app uses certain APIs that could fingerprint a device, UserDefaults among them: self-declared, and the developer answers for it.
Leave the app, and it freezes
When the user leaves, the app gets a few seconds. Then iOS suspends it: in memory, running nothing. When memory runs short, iOS terminates it, without a callback.
- Not runningnever launched, or terminated
- Inactivea passage between states
- Activein front, interactive
- Backgrounda few seconds to finish
- Suspendedfrozen in memory, no CPU
- Terminatedno callback; back to not running
Back from suspended: instant. From terminated: a cold launch.
Save as the app leaves the foreground. Design for a cold launch at any time.
Go deeper Background modes, the hooks, and Android 2 min
Work that must go on after the user leaves needs a background mode the app declares and App Review checks: audio, location, voice over IP, fetch and processing jobs the system schedules, pushes that wake the app briefly. Or it is handed to the system: a background URLSession transfers files even while the app is suspended. Since iOS 26, an app can also ask to finish one job the user started, visibly and cancellably. A general “keep running” does not exist.
Where to save: scenePhase .inactive then .background in SwiftUI; sceneWillResignActive then sceneDidEnterBackground in UIKit; AppState “inactive” then “background” in React Native; the visibilitychange event in a web app. Since iOS 13, these states belong to each scene, each window of the app.
Android now freezes too: since Android 14, a cached process is frozen about ten seconds after the user leaves, on phones that support it. The difference is the way out: on Android, a foreground service, declared with its type and shown as a notification, keeps the app running. On iOS, nothing general does.
Before the lab
Seeing it needs no Mac; building it does
Xcode and the iOS simulators run only on macOS. To build an iOS app, you need a Mac: yours, or one in the cloud. To see your app on an iPhone, you may not.
| Family | See it on an iPhone, no Mac | Build it for the App Store |
|---|---|---|
| Native, Swift | No | A Mac with Xcode, yours or one in the cloud |
| Expo | Yes: Expo Go, within its limits | EAS Build, on Expo's Macs |
| Ionic + Capacitor | The web build, in Safari | A Mac with Xcode, yours or one in the cloud |
| PWA | Yes: Safari opens it | No build: it is a website |
To build for the App Store, the certificate and the profile must be yours: a paid Apple Developer Program membership.
Go deeper Expo Go's limits, and the cloud 1 min
Expo Go comes from the App Store. It runs your project only on the same SDK version, only with the native libraries it ships, and only when you are logged in to Expo both in the CLI and in the app. Anything else needs a development build.
EAS Build and Codemagic build on their Macs and hand you the signed .ipa. Xcode Cloud too, but you first set it up from Xcode, on a Mac. The membership costs 99 USD a year; an accredited school can ask Apple for a fee waiver.
With knowledge · in class
The AI gets the paperwork wrong
An assistant writes Swift as fluently as Kotlin. It gets the paperwork wrong. It forgets the purpose string and the keychain, iOS's safe for secrets. It switches on background modes you did not ask for.
Paste first, whatever the family
assume iOS can freeze the app seconds after the user leaves and terminate it without warning: save the draft as the app leaves the foreground, restore it on a cold launch, and enable no background mode unless I ask
All families
Say it in the prompt
for every protected resource the app uses, add its iOS purpose string with a one-sentence reason a user would accept, and tell me in which file or setting you put it
Where the purpose strings live
- Native: the target's Signing & Capabilities and Info panes. A new Xcode project has no
Info.plistfile. - Expo:
app.json, inios.infoPlistor a module's config plugin. - Ionic:
ios/App/App/Info.plist, a real file afternpx cap add ios. - PWA: nothing to declare. Safari asks the user for you.
Native
Say it in the prompt
for every protected resource the app uses, add its usage description (in Info.plist, or as an INFOPLIST_KEY_ build setting if the project has no Info.plist file) with a one-sentence reason a user would accept; store the session token in the Keychain, never in UserDefaults
Check the project
Expo
Say it in the prompt
set each iOS purpose string through the module's config plugin or ios.infoPlist in app.json, with a one-sentence reason a user would accept; store the session token with expo-secure-store
Check the project
Ionic
Say it in the prompt
after npx cap add ios, add to ios/App/App/Info.plist the usage description each plugin's documentation lists, with a one-sentence reason a user would accept
Check the project
PWA
Say it in the prompt
ask for the camera only when the user taps a button that needs it, and keep every other feature working when the answer is no
Check the project
Review reads these settings too. Guideline 2.5.4: background services only for their intended purposes, such as VoIP, audio, location, task completion and local notifications. Guideline 5.1.1: ask only for data relevant to the app's core functionality.
Try it on your phone · 10 minutes
See the sandbox from the user's side, no Mac needed
On any iPhone; no iPhone, pair with a classmate. Each “You should see” follows Apple's own guide, linked.
-
The answer lives in Settings. Settings → Privacy & Security → Camera.
You should see The apps that asked for the camera, each with its own switch. Apps that never asked are not listed. iPhone User Guide
This proves The answer belongs to the user and the system, not to the app.
-
The bundle and the container. Settings → General → iPhone Storage → an app.
You should see Its storage in detail, then two actions: offload the app, or delete it. Offloading frees the app's storage but keeps its documents and data. Apple Support
This proves The app and its data are two things: the bundle, and its container.
-
Who works in the background. Settings → Battery → View All Battery Usage, then a day, then an app.
You should see For each app, two times: “On screen” and “Background”. iPhone User Guide
This proves The system counts background time, app by app. It is not free.
Go deeper Two more places, and homework 2 min
Files → Browse → On My iPhone. A folder appears for an app only when it chose to share its Documents folder with the user. Every other container stays invisible, even to you.
Settings → General → VPN & Device Management. A company's own app, installed by hand outside the App Store, opens only once the user trusts its developer here. Apple Support
Homework for capsule 09. Settings → Privacy & Security → App Privacy Report: turn it on for a week. It shows when each app accessed data or sensors, and which domains it contacted. Apple Support
Quick check
Capsule 02 On Android, your notes app is cached, and memory runs short. What runs in your code before the process dies?
See the answer
A killed process runs nothing, not even onDestroy. iOS does the same to a suspended app: it terminates it with no callback, so on both you save on the way out, not at the end.
Capsule 02 Who vouches for the certificate that signs an app, on Android and on iOS?
See the answer
An Android certificate is self-signed, from a key the developer generates; on iOS, nothing runs unless Apple issued the certificate to a named developer. Play App Signing means Google keeps a key, not that it vouches for one.
The first time your app asks for the camera, a dialog appears. Who draws it, and whose sentence does it show?
See the answer
iOS draws the dialog, not your app, with your app's name and the purpose string it declares. Apple writes no default sentence: without that string, the request fails and the app usually crashes.
Your app's upload is at 40% when the user switches to another app for twenty minutes. The app declares no background mode. When the user comes back, the upload…
See the answer
Without a declared mode, the app gets a few seconds and is then suspended, upload included; if memory ran short meanwhile, iOS terminated it with no callback. To finish a transfer while suspended, hand it to iOS: a background URLSession.
Last week the user tapped “Don’t Allow” for the camera. Today your app asks again. What happens?
See the answer
iOS asks once and keeps the answer: the request now reports no access, with no dialog. A refusal crashes nothing; the app must keep working, and can point the user to Settings.
Your iOS app will use the camera. Which line belongs in your prompt to the assistant?
See the answer
Without a purpose string, the camera request fails and the app usually crashes. Background modes are what assistants switch on unasked, and the camera is asked for when the user taps the button that needs it, not at launch.
In Expo Go, your app opens the camera without a problem. Are your own purpose strings right?
See the answer
In Expo Go, your project runs inside Expo Go's app, with Expo Go's purpose strings: Settings shows Expo Go. Yours ship only in a native build, such as eas build, so test the camera there; android.permissions is Android's list anyway.
An assistant stores the user's session token in UserDefaults. What do you ask it to change?
See the answer
A file in the container, UserDefaults included, is readable from the first unlock after a restart; a keychain item, by default, only while the device is unlocked. Documents/ holds files too, and the user can even see them when the app shares that folder.
Settings → General → iPhone Storage → an app → Offload App. What happens?
See the answer
Offloading frees the app's own storage but keeps its documents and data; deleting would remove both. The app and its data are two things: the bundle, and its container.
You have no Mac, and your lab is the Expo app. How can you see it running on your iPhone?
See the answer
Expo Go, an App Store app, runs your project when it uses the same SDK and only the native libraries Expo Go ships. The simulator runs only on macOS, and a build for the App Store can come from Expo's Macs, with EAS Build.
Recap
- Same shape as Android. A sandbox, a lifecycle, permissions. Apple holds the keys.
- Authorized by Apple. Nothing runs unless Apple's chain of signatures allows it.
- Every door is Apple's. App Store, TestFlight, your own devices. No side door.
- A purpose string, or a crash. The user decides, and can change it in Settings.
- Frozen within seconds. Terminated without a callback. Save as the app leaves the foreground.
- A Mac to build. Expo Go and Safari let you see it without one.
Sources
- Managing your app's life cycle, Extending your app's background execution time, five seconds, then suspended, and Downloading files in the background, a transfer that goes on while the app is suspended.
- Requesting access to protected resources, the dialog and the crash, and Managing your app's information property list, why a new Xcode project has no
Info.plistfile, and Describing use of required reason API, the privacy manifest and its deadline. - TN3125: Inside code signing, provisioning profiles, Entitlements, and AOSP: Application signing, self-signed certificates on Android.
- Encrypting your app's files and Restricting keychain item accessibility, the defaults.
- TestFlight overview, App Store Review Guidelines, 2.5.4 and 5.1.1, Web distribution in the EU, App distribution in Japan, and alternative distribution by region, Brazil included, and Changes to iOS in Brazil, the agreement with the regulator CADE.
- BGContinuedProcessingTask, iOS 26's visible job, and AOSP: Cached apps freezer and Android 14: foreground service types are required, the Android side of the comparison.
- Apple Developer Program: enrollment, the fee and its waiver, Configuring your first Xcode Cloud workflow, Expo: EAS Build, Expo Go: login now required, Expo: development builds FAQ, Expo: permissions, and Capacitor: iOS configuration.