Files
magnus919_agent-skills/mobile-development/references/ios.md
T
Magnus HedemarkGitHubfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
f68721873e feat(skill): add mobile development skill (iOS / Android / Flutter / React Native) (#248) (#268)
ONE family skill covering iOS, Android, Flutter, and React Native with
per-framework references (ios.md, android.md, flutter.md, react-native.md),
shared scaffold/build/sign/test/ship workflow, mobile lifecycle, offline and
sync guidance, and mobile-specific testing. Ships a 5-heading human README and
a schema-v1 eval manifest with 6 cases covering build/sign, testing, and
store-readiness. Adds the README index entry and regenerates catalogs.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-08-03 19:48:20 -04:00

8.3 KiB

iOS Reference — Swift, Xcode, App Store

Last Updated: 2026-08-03

Load this reference when the target platform is iOS — native Swift apps built with Xcode, or an iOS target inside a Flutter or React Native project (that tooling is covered in flutter.md and react-native.md; this file is the platform layer under them). It complements the shared workflow in SKILL.md; this file is the iOS-specific detail for scaffolding, building and signing, simulator and device testing, and App Store submission.

iOS fundamentals

An iOS app is a signed, structured bundle (.app) archived into an .ipa for distribution:

  • Xcode project.xcodeproj (single target) or .xcworkspace (when using CocoaPods or Swift Package Manager workspace integration). The project file holds build settings, targets, schemes, and signing configuration.
  • Build products — the .app bundle contains the compiled binary (Mach-O), Info.plist (bundle ID, version, permissions), entitlements, and resources. Xcode "Archive" produces the .xcarchive used for store upload.
  • Distribution artifacts.ipa (signed .app inside a Payload/ directory) for TestFlight and App Store, and .xcarchive for archival and re-export. Ad-hoc and enterprise distribution reuse the same .ipa format with different signing profiles.

Keep Info.plist keys (bundle identifier, CFBundleShortVersionString, CFBundleVersion, usage-description strings for camera/location/etc.) accurate and reviewed — store review and crash reporting both depend on them.

Scaffolding

  • New native app — create the project in Xcode or with xcodebuild templates; choose SwiftUI for new apps (UIKit remains for legacy or fine-grained control). Set the deployment target to the minimum iOS version you committed to in scope.
  • Dependencies — prefer Swift Package Manager (SPM) for new work; CocoaPods is still common in existing codebases. Commit the lockfile (Package.resolved, Podfile.lock) so builds are reproducible.
  • App structure — keep the app entry point (the @main App/AppDelegate and scene) thin, and organize the rest by feature rather than by type.
  • Signing early — set up a development team and automatic signing before the first device run; the simulator can build unsigned, but a device needs a valid signing identity and provisioning profile.

Builds and signing

Signing model

iOS signing has two assets, both managed per Apple Developer account:

  • Certificates — a development certificate (for device installs) and a distribution certificate (for TestFlight/App Store). Certificates are tied to the account; distribution certificates can be shared between machines but should be kept in secure storage.
  • Provisioning profiles — bind a certificate to app IDs and (for development) devices. Profiles expire and must be renewed; automatic signing in Xcode handles this when a developer account is configured.

Signing practices

  • Automatic signing for development — let Xcode manage profiles against the developer account for local device builds.
  • Release signing in CI — export the distribution certificate and profile as secrets; never commit .p12, .mobileprovision, or private keys to the repository. Use xcodebuild -exportArchive -exportOptionsPlist with the -exportOptionsPlist file committed (it contains no secrets) so CI produces the same artifact as a local Archive.
  • Two app IDs, two signing identities — a development build and a release build are different signed artifacts. Verify both sign correctly; a profile mismatch is the most common first-upload rejection.

Build commands

# Build for a simulator (no signing needed)
xcodebuild -workspace App.xcworkspace -scheme App -configuration Debug \
  -sdk iphonesimulator build

# Archive for distribution (signs with the distribution identity)
xcodebuild -workspace App.xcworkspace -scheme App -configuration Release \
  -archivePath build/App.xcarchive archive

# Export an .ipa for TestFlight / App Store from the archive
xcodebuild -exportArchive -archivePath build/App.xcarchive \
  -exportOptionsPlist ExportOptions.plist -exportPath build/ipa

Simulators and devices

  • Simulatorsxcrun simctl lists, boots, installs, and launches simulators headlessly, which makes it scriptable for CI smoke tests:

    xcrun simctl list devices
    xcrun simctl boot "iPhone 16"
    xcrun simctl install booted build/App.app
    xcrun simctl launch booted com.example.app
    
  • Physical devices — a device build requires the device's UDID in a development provisioning profile. Verify on a physical device: real networking, background execution, push, and sensors behave differently from the simulator.

  • Debuggingxcodebuild + Instruments for profiling; log stream and unified logging (OSLog) for diagnostics on device. Crash reports appear in Xcode Organizer and App Store Connect once TestFlight testers use the app.

Lifecycle and backgrounding

  • Scene-based lifecycle — modern iOS apps manage Scene lifecycle (active/inactive/background); the app delegate owns launch and termination. Persist state in sceneDidEnterBackground or at state transitions — do not assume the app will be resumed.
  • Background modes — background execution requires a declared background mode (audio, location, background fetch, push notifications) in Info.plist capabilities. Apple reviews these declarations; use them only for their stated purpose.
  • Push notifications — the app must register for remote notifications and handle both foreground presentation and background delivery; silent pushes are rate-limited by the OS.
  • Process death — the OS can terminate the app at any time. Save user-visible state and restore it on launch rather than keeping it in memory.

Offline and sync

  • Local persistence — Core Data or SwiftData for relational models, FileManager/Documents for files, UserDefaults for small settings. Consider that UserDefaults is not a database.
  • Sync pattern — persist locally first, then sync: queue writes in a local store, replay them against the API when connectivity returns, and resolve conflicts with an explicit strategy. URLSession with waitsForConnectivity and background URL sessions handle retries and large transfers.
  • Reachability — use NWPathMonitor to react to connectivity changes, but design so a lost network degrades gracefully instead of crashing.

Testing

  • Unit tests — XCTest with the @testable import pattern; run in the simulator (xcodebuild test).
  • UI tests — XCUITest drives the real app via accessibility identifiers; keep those identifiers stable and semantic.
  • Snapshot/visual tests — libraries such as Swift Snapshot Testing render views to images for regression detection; keep fixtures in-repo and reviewed.
  • Performance — measure launch time, frame rate, and memory with Instruments (or XCTest metrics) on a physical device; simulator numbers are not representative.

Store submission

  1. TestFlight first — upload the archive to App Store Connect (xcrun altool/notarytool or Xcode Organizer), distribute to internal and external testers, and let real devices exercise the app before review.
  2. App Store Connect setup — the app record, bundle ID, pricing, and availability; export compliance questions; and the build must match the uploaded binary.
  3. Review readiness — privacy nutrition labels for collected data, Info.plist usage descriptions, a complete store listing (screenshots for the required device sizes), and a working demo account or demo mode if the app requires sign-in. The App Review guidelines are enforced by humans; flaky sign-in, hidden features, and misleading metadata are common rejection causes.
  4. Staged release — submit for review with a gradual release or schedule the release so a regression reaches few users first. Monitor crash rates after release.

Key references

  • Apple Developer Program and App Store Connect documentation (developer.apple.com/app-store/submitting).
  • Xcode release notes and current SDK requirements near submission time — minimum Xcode and iOS SDK versions change annually.