Consolidate all markdown documentation into organized structure per CONSOLIDATION_DIRECTIVE. All files preserved (canonical, merged, or archived). - docs/integration/ - Integration documentation (7 files) - docs/platform/ios/ - iOS platform docs (12 files) - docs/platform/android/ - Android platform docs (9 files) - docs/testing/ - Testing documentation (15 files) - docs/design/ - Design & research (5 files) - docs/ai/ - AI/ChatGPT artifacts (7 files) - docs/archive/2025-legacy-doc/ - Historical docs (17 files) - Integration: Root INTEGRATION_GUIDE.md → docs/integration/ - Platform: Separated iOS and Android into platform/ subdirectories - Testing: Consolidated all testing docs to docs/testing/ - Legacy: Archived entire doc/ directory to archive/ - AI: Moved all ChatGPT artifacts to docs/ai/ - Added docs/00-INDEX.md - Central navigation hub - Added docs/CONSOLIDATION_SOURCE_MAP.md - Complete audit trail - Added docs/CONSOLIDATION_COMPLETE.md - Consolidation summary - Updated README.md with links to documentation index - All 139 files have destinations (see CONSOLIDATION_SOURCE_MAP.md) - Zero information loss (all files preserved) - Archive preserves original structure - Index provides clear navigation - 87 files moved/created/updated - Root-level docs consolidated - Legacy doc/ directory archived - Test app docs remain with test apps (indexed) Ref: CONSOLIDATION_DIRECTIVE Author: Matthew Raymer
14 KiB
iOS Troubleshooting Guide
Author: Matthew Raymer
Date: 2025-12-08
Status: 🎯 ACTIVE - iOS Troubleshooting Reference
Version: 1.0.0
Purpose
This guide provides solutions to common iOS-specific issues when using the Daily Notification Plugin. It covers debugging techniques, common problems, and their solutions.
Reference:
- iOS Implementation Directive - Implementation details
- Platform Capability Reference - iOS OS behaviors
- iOS Logging Guide - How to view logs
1. Common Issues
1.1 Notifications Not Firing
Symptoms:
- Notifications scheduled but don't appear
- No notification at scheduled time
- Notifications work in simulator but not on device
Diagnosis Steps:
-
Check Notification Permission:
// In app code UNUserNotificationCenter.current().getNotificationSettings { settings in print("Authorization status: \(settings.authorizationStatus)") }Or check in Xcode Console:
DNP-PLUGIN: Notification permission status: authorized -
Check Pending Notifications:
UNUserNotificationCenter.current().getPendingNotificationRequests { requests in print("Pending notifications: \(requests.count)") } -
Check Background App Refresh:
- Settings → [Your App] → Background App Refresh
- Must be enabled for background tasks
-
Check Notification Limit:
- iOS limits to 64 pending notifications
- Check if limit is exceeded
Solutions:
-
Permission Denied:
- Request permission:
DailyNotification.requestNotificationPermission() - Guide user to Settings → [Your App] → Notifications
- Request permission:
-
Background App Refresh Disabled:
- Guide user to enable: Settings → [Your App] → Background App Refresh
- Or use:
DailyNotification.openBackgroundAppRefreshSettings()
-
Notification Limit Exceeded:
- Reduce number of scheduled notifications
- Implement notification cleanup logic
- Check rolling window implementation
-
Simulator vs Device:
- Simulator may not fire notifications reliably
- Test on physical device for accurate behavior
1.2 Background Tasks Not Executing
Symptoms:
- Prefetch tasks don't run
- Background fetch never executes
- BGTaskScheduler tasks not firing
Diagnosis Steps:
-
Check BGTaskScheduler Registration:
// Verify registration in AppDelegate BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.timesafari.dailynotification.fetch", using: nil) { task in // Handler should be registered } -
Check Info.plist:
<key>BGTaskSchedulerPermittedIdentifiers</key> <array> <string>com.timesafari.dailynotification.fetch</string> </array> -
Check Background App Refresh:
- Must be enabled in Settings
- System-controlled timing (not guaranteed)
-
Check Logs:
DNP-FETCH-START: Background fetch task started
Solutions:
-
Not Registered:
- Verify registration in
AppDelegate.application(_:didFinishLaunchingWithOptions:) - Check Info.plist has correct identifiers
- Verify registration in
-
Background App Refresh Disabled:
- User must enable in Settings
- Cannot be programmatically enabled
-
System Not Executing:
- BGTaskScheduler is system-controlled
- Execution timing is not guaranteed
- System may defer or skip tasks
- Use for prefetching only, not critical scheduling
-
Simulator Limitations:
- Background tasks may not execute in simulator
- Test on physical device
1.3 Notifications Disappear After App Termination
Symptoms:
- Notifications scheduled but disappear when app is terminated
- Notifications don't persist across app restarts
Diagnosis:
This should NOT happen on iOS - notifications persist automatically (OS-guaranteed).
If it happens, check:
-
Notification Trigger Type:
- Calendar/time triggers persist ✅
- Location triggers do NOT persist ❌
-
Notification Content:
- Ensure notification has valid content
- Check for invalid trigger dates
-
System Storage:
- iOS may clear notifications if device storage is full
- Check available storage
Solutions:
-
Use Calendar Triggers:
// ✅ Persists across reboot let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true) // ❌ Does NOT persist let trigger = UNLocationNotificationTrigger(region: region, repeats: true) -
Check Device Storage:
- Free up storage if device is full
- iOS may clear notifications when storage is critical
1.4 Recovery Not Working
Symptoms:
- Missed notifications not detected on app launch
- Future notifications not verified/rescheduled
- No recovery activity in logs
Diagnosis:
Recovery features are NOT yet implemented (as of 2025-12-08).
Expected Behavior (Once Implemented):
-
Check Logs for Recovery:
DNP-REACTIVATION: Starting app launch recovery DNP-REACTIVATION: Detected scenario: coldStart DNP-REACTIVATION: Missed notifications detected: 2 DNP-REACTIVATION: Future notifications verified: 1 -
Verify Recovery Logic:
- Should run in
DailyNotificationPlugin.load() - Should detect missed notifications
- Should verify future notifications
- Should run in
Solutions:
-
Implementation Pending:
- See iOS Implementation Directive Phase 1
- Recovery features need to be implemented
-
Manual Workaround:
- Check pending notifications manually
- Reschedule if needed
1.5 Database/Storage Issues
Symptoms:
- Database errors in logs
- Data not persisting
- Core Data errors
Diagnosis Steps:
-
Check Database Path:
let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] let dbPath = documentsPath.appendingPathComponent("daily_notifications.db") print("Database path: \(dbPath.path)") -
Check Core Data Stack:
- Verify
NSPersistentContainerinitialization - Check for migration errors
- Verify
-
Check Logs:
DNP-STORAGE: Database opened successfully DNP-STORAGE: Error opening database: [error]
Solutions:
-
Database Path Issues:
- Verify app has write permissions
- Check Documents directory is accessible
- Ensure path is correct
-
Core Data Errors:
- Check Core Data model version
- Verify migration policies
- Check for schema mismatches
-
Storage Full:
- Free up device storage
- iOS may clear app data if storage is critical
1.6 Permission Issues
Symptoms:
- Permission requests fail
- Permission status incorrect
- Cannot schedule notifications
Diagnosis:
-
Check Current Status:
UNUserNotificationCenter.current().getNotificationSettings { settings in switch settings.authorizationStatus { case .authorized: // ✅ Can schedule case .denied: // ❌ User denied case .notDetermined: // ⚠️ Not requested yet case .provisional: // ⚠️ Provisional (iOS 12+) @unknown default: break } } -
Check Logs:
DNP-PLUGIN: Notification permission status: denied
Solutions:
-
Permission Denied:
- Cannot request again programmatically
- Guide user to Settings → [Your App] → Notifications
- Use:
DailyNotification.openNotificationSettings()
-
Not Determined:
- Request permission:
DailyNotification.requestNotificationPermission() - Show explanation before requesting
- Request permission:
-
Provisional:
- iOS 12+ feature
- Notifications delivered quietly
- User can upgrade to full permission
2. Debugging Techniques
2.1 Viewing Logs
Xcode Console (Recommended):
- Run app in Xcode (Cmd+R)
- Open Debug Area (Cmd+Shift+Y)
- Filter by:
DNP-orDailyNotification
Console.app:
- Open Console.app
- Select device/simulator
- Filter by process:
ios-test-app
Command Line:
# Simulator logs
xcrun simctl spawn <device-id> log stream --level=debug --predicate 'processImagePath contains "ios-test-app"'
# Device logs (requires device connected)
xcrun devicectl device process monitor --device <device-id> --filter "ios-test-app"
2.2 Checking Pending Notifications
Via Plugin Method:
const result = await DailyNotification.getPendingNotifications();
console.log(`Pending: ${result.count}`);
Via Swift Code:
UNUserNotificationCenter.current().getPendingNotificationRequests { requests in
print("Pending notifications: \(requests.count)")
for request in requests {
print(" - \(request.identifier): \(request.content.title)")
}
}
2.3 Checking Background Task Status
Via Plugin Method:
const status = await DailyNotification.getBackgroundTaskStatus();
console.log(`Fetch task registered: ${status.fetchTaskRegistered}`);
console.log(`Background refresh enabled: ${status.backgroundRefreshEnabled}`);
Via Swift Code:
// Check registration
let registered = BGTaskScheduler.shared.registeredTaskIdentifiers
print("Registered tasks: \(registered)")
// Check Background App Refresh (requires entitlement)
// Cannot check programmatically - must guide user to Settings
2.4 Simulating Background Tasks (Simulator Only)
LLDB Command in Xcode:
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.timesafari.dailynotification.fetch"]
Note: This only works in simulator, not on physical devices.
3. Platform-Specific Considerations
3.1 Simulator vs Device
Simulator Limitations:
- Background tasks may not execute reliably
- Notifications may not fire at exact time
- Some features require physical device
Device Testing:
- More accurate behavior
- Background tasks execute (system-controlled)
- Notifications fire reliably
Recommendation: Test critical features on physical device.
3.2 iOS Version Differences
iOS 12+:
- Provisional notification authorization
- Background task improvements
iOS 13+:
- State actor support (concurrency)
- Improved background execution
iOS 14+:
- Notification interruption levels
- Focus modes (may affect notifications)
iOS 15+:
- Notification summary
- Focus mode integration
3.3 Background Execution Limits
iOS Constraints:
- BGTaskScheduler is system-controlled
- Execution timing not guaranteed
- Minimum intervals between tasks (hours)
- Tasks may be deferred or skipped
Workaround:
- Use BGTaskScheduler for prefetching only
- Don't rely on it for critical scheduling
- Use UNUserNotificationCenter for notifications (more reliable)
4. Error Codes
4.1 Common Error Codes
| Error Code | Description | Solution |
|---|---|---|
NOTIFICATION_PERMISSION_DENIED |
User denied notification permission | Guide user to Settings |
BACKGROUND_REFRESH_DISABLED |
Background App Refresh disabled | Guide user to enable in Settings |
PENDING_NOTIFICATION_LIMIT_EXCEEDED |
Exceeded 64 notification limit | Reduce scheduled notifications |
BG_TASK_NOT_REGISTERED |
Background task not registered | Check Info.plist and AppDelegate |
BG_TASK_EXECUTION_FAILED |
Background task execution failed | Check logs for specific error |
4.2 Checking Error Details
Via Logs:
DNP-ERROR: [Error Code] [Error Message]
DNP-ERROR: NOTIFICATION_PERMISSION_DENIED: User denied notification permission
Via Plugin:
try {
await DailyNotification.scheduleDailyNotification({...});
} catch (error) {
console.error('Error code:', error.code);
console.error('Error message:', error.message);
}
5. Performance Issues
5.1 Slow Notification Scheduling
Symptoms:
- Scheduling takes too long
- App freezes during scheduling
Solutions:
- Schedule notifications asynchronously
- Batch operations when possible
- Use background queue for heavy operations
5.2 High Memory Usage
Symptoms:
- App memory usage high
- Memory warnings in logs
Solutions:
- Implement notification cleanup
- Limit cached notifications
- Use efficient data structures
5.3 Battery Drain
Symptoms:
- Battery drains quickly
- Background activity high
Solutions:
- Limit background task frequency
- Optimize prefetch operations
- Use efficient scheduling algorithms
6. Getting Help
6.1 Log Collection
Collect Logs:
- Reproduce the issue
- Collect logs from Xcode Console or Console.app
- Filter by
DNP-prefix - Include relevant error messages
Log Format:
DNP-PLUGIN: [Message]
DNP-ERROR: [Error Code] [Error Message]
DNP-REACTIVATION: [Recovery Activity]
6.2 Issue Reporting
Include:
- iOS version
- Device model (or simulator)
- Plugin version
- Steps to reproduce
- Relevant logs
- Expected vs actual behavior
6.3 Documentation References
7. Quick Reference
7.1 Common Commands
Check Pending Notifications:
# Via plugin method (recommended)
# Or check logs for scheduling activity
View Logs:
# Xcode Console (Cmd+Shift+Y)
# Filter: DNP-
# Console.app
# Filter: ios-test-app
Check Permissions:
const status = await DailyNotification.getNotificationPermissionStatus();
Open Settings:
await DailyNotification.openNotificationSettings();
await DailyNotification.openBackgroundAppRefreshSettings();
7.2 Checklist
Before Reporting Issue:
- Checked notification permissions
- Verified Background App Refresh is enabled
- Checked pending notification count (< 64)
- Reviewed logs for errors
- Tested on physical device (not just simulator)
- Verified iOS version compatibility
- Checked device storage availability
Document Version: 1.0.0
Last Updated: 2025-12-08
Next Review: After Phase 1 implementation