Skip to content

DOMAIN:IOS_DEVELOPMENT:PITFALLS

OWNER: martijn
ALSO_USED_BY: valentin
UPDATED: 2026-03-24


PITFALL:SIGNING_IDENTITY_CONFUSION

SYMPTOM: "No signing certificate found" or "Provisioning profile doesn't match"
CAUSE: multiple Apple Developer accounts in Keychain, or cert/key mismatch
FIX: security find-identity -v -p codesigning to list all identities
FIX: delete old/expired certs from Keychain Access
FIX: ensure private key exists alongside certificate
FIX: use Fastlane match to centralize signing


PITFALL:DEVICE_UDID_LIMIT

SYMPTOM: cannot add more test devices to Ad Hoc profile
CAUSE: 100 device limit per device type per membership year
RULE: removing a device does NOT free the slot until renewal
FIX: use TestFlight instead — no device limit
FIX: plan device registrations at start of year


PITFALL:BACKGROUND_TASK_NOT_RUNNING

SYMPTOM: BGTaskScheduler tasks never execute
CAUSE: multiple possible causes
CHECK: is the task identifier registered in Info.plist BGTaskSchedulerPermittedIdentifiers?
CHECK: is BGTaskScheduler.shared.register() called in didFinishLaunchingWithOptions?
CHECK: is the device plugged in? (BGProcessingTask requires charging)
CHECK: did you call task.setTaskCompleted(success:) in the handler?
DEBUG: e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.app.refresh"] in Xcode debugger


PITFALL:ATS_BLOCKING_REQUESTS

SYMPTOM: network requests silently fail or return ATS error
CAUSE: HTTP URL or TLS < 1.2
FIX: use HTTPS everywhere
FIX: if legacy server, add per-domain exception in Info.plist (never global)
CHECK: Console.app → filter "ATS" to see blocked requests


PITFALL:PUSH_TOKEN_MISMATCH

SYMPTOM: push notifications work in development but not production
CAUSE: sandbox vs production APNs environments use different tokens
FIX: ensure backend sends to correct APNs endpoint based on build type
FIX: use APNs authentication key (.p8) — works for both environments
CHECK: is aps-environment entitlement set correctly? (development vs production)


PITFALL:MEMORY_PRESSURE_CRASHES

SYMPTOM: app crashes without crash log (jetsam termination)
CAUSE: excessive memory usage
CHECK: Xcode Organizer → Terminations → Memory
CHECK: Instruments → Allocations
FIX: downsample images to display size
FIX: release caches in didReceiveMemoryWarning
FIX: use autorelease pool for batch operations
FIX: lazy load heavy resources


PITFALL:RETAIN_CYCLES

SYMPTOM: memory grows over time, view controllers not deallocated
CAUSE: strong reference cycle (usually in closures or delegates)
FIX: [weak self] in escaping closures
FIX: weak var delegate in delegation pattern
FIX: use Xcode Memory Graph Debugger to find cycles
CHECK: add deinit { print("VC deallocated") } during development to verify cleanup


PITFALL:APP_STORE_REJECTION_LOOP

SYMPTOM: app rejected repeatedly for same or different issues
CAUSE: fixing one issue reveals another, or fix doesn't address reviewer's concern
FIX: read rejection message CAREFULLY — match specific guideline number
FIX: reply in Resolution Center asking for clarification if ambiguous
FIX: do NOT submit identical build hoping for different reviewer
ESCALATE_TO: human after 3 rejections — may need Apple Developer Relations call


PITFALL:SWIFTUI_LIST_PERFORMANCE

SYMPTOM: scrolling stutters with large lists
CAUSE: non-lazy views, complex view bodies, unnecessary redraws
FIX: use List or LazyVStack — NOT VStack for dynamic content
FIX: extract subviews to reduce body complexity
FIX: use @Observable macro (iOS 17+) — finer-grained updates than ObservableObject
FIX: avoid computing complex values in view body — move to view model
CHECK: Instruments → SwiftUI instrumentation


PITFALL:DYNAMIC_TYPE_BROKEN_LAYOUT

SYMPTOM: UI breaks at large/accessibility text sizes
CAUSE: fixed-height constraints, images competing with text
FIX: use text styles (.font(.body)) not fixed sizes
FIX: use flexible layouts (no fixed heights on text containers)
FIX: test at ALL Dynamic Type sizes including the 5 accessibility sizes
TOOL: Xcode → Environment Overrides → Dynamic Type slider


PITFALL:DARK_MODE_INVISIBLE_ELEMENTS

SYMPTOM: elements invisible or unreadable in dark mode
CAUSE: hardcoded colors (Color.white, Color.black, hex values)
FIX: use semantic colors (Color(.label), Color(.systemBackground))
FIX: define custom colors in Asset Catalog with dark mode variants
CHECK: toggle Appearance in Xcode preview or Environment Overrides


PITFALL:KEYBOARD_COVERS_INPUT

SYMPTOM: keyboard appears and covers the text field user is typing in
CAUSE: no keyboard avoidance
FIX: SwiftUI automatically adjusts for keyboard in ScrollView/List (iOS 15+)
FIX: for custom layouts, use KeyboardLayoutGuide (UIKit) or .scrollDismissesKeyboard(.interactively)
FIX: add .scrollDismissesKeyboard(.interactively) to ScrollView for dismiss-on-drag


PITFALL:EXPIRED_ENTERPRISE_CERT

SYMPTOM: all enterprise-distributed apps stop launching
CAUSE: enterprise distribution certificate expired or revoked
SEVERITY: CRITICAL — affects ALL apps signed with that cert across entire organization
FIX: renew certificate 30 days before expiry
FIX: re-sign and redistribute all apps
FIX: set calendar reminders for cert expiry
NOTE: Apple enterprise certs are valid for 3 years but provisioning profiles expire annually


PITFALL:PRIVACY_MANIFEST_MISSING

SYMPTOM: App Store Connect warning or rejection about missing privacy manifest
CAUSE: app or included SDK missing PrivacyInfo.xcprivacy
FIX: add PrivacyInfo.xcprivacy to app target
FIX: declare all required reason API usage
FIX: ensure all third-party SDKs include their own manifests
TOOL: Xcode → Product → Generate Privacy Report
CHECK: run privacy report before every submission


PITFALL:SIMULATOR_VS_DEVICE_DIFFERENCES

SYMPTOM: works in Simulator but not on device (or vice versa)
CAUSE: Simulator lacks hardware features + has different performance characteristics

Feature Simulator Device
Camera Not available Available
Push notifications Not available (APNs) Available
Bluetooth Not available Available
GPS Simulated only Real
Performance Host machine CPU A-series/M-series chip
Memory Host machine RAM Device-limited
Biometrics Simulated Real Face ID/Touch ID
Network Host network Cellular/Wi-Fi

RULE: ALWAYS test on real device before submission
RULE: test on oldest supported device if possible
RULE: test on device with minimal storage (low disk space handling)