Files
daily-notification-plugin/docs/platform/ios/TROUBLESHOOTING.md
Matthew Raymer c39bd7cec6 docs: Consolidate documentation structure (139 files, zero information loss)
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
2025-12-18 09:13:18 +00:00

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:


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:

  1. 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
    
  2. Check Pending Notifications:

    UNUserNotificationCenter.current().getPendingNotificationRequests { requests in
        print("Pending notifications: \(requests.count)")
    }
    
  3. Check Background App Refresh:

    • Settings → [Your App] → Background App Refresh
    • Must be enabled for background tasks
  4. 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
  • 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:

  1. Check BGTaskScheduler Registration:

    // Verify registration in AppDelegate
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.timesafari.dailynotification.fetch", using: nil) { task in
        // Handler should be registered
    }
    
  2. Check Info.plist:

    <key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
        <string>com.timesafari.dailynotification.fetch</string>
    </array>
    
  3. Check Background App Refresh:

    • Must be enabled in Settings
    • System-controlled timing (not guaranteed)
  4. Check Logs:

    DNP-FETCH-START: Background fetch task started
    

Solutions:

  • Not Registered:

    • Verify registration in AppDelegate.application(_:didFinishLaunchingWithOptions:)
    • Check Info.plist has correct identifiers
  • 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:

  1. Notification Trigger Type:

    • Calendar/time triggers persist
    • Location triggers do NOT persist
  2. Notification Content:

    • Ensure notification has valid content
    • Check for invalid trigger dates
  3. 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):

  1. 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
    
  2. Verify Recovery Logic:

    • Should run in DailyNotificationPlugin.load()
    • Should detect missed notifications
    • Should verify future notifications

Solutions:

  • Implementation Pending:

  • 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:

  1. 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)")
    
  2. Check Core Data Stack:

    • Verify NSPersistentContainer initialization
    • Check for migration errors
  3. 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:

  1. 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
        }
    }
    
  2. 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
  • Provisional:

    • iOS 12+ feature
    • Notifications delivered quietly
    • User can upgrade to full permission

2. Debugging Techniques

2.1 Viewing Logs

Xcode Console (Recommended):

  1. Run app in Xcode (Cmd+R)
  2. Open Debug Area (Cmd+Shift+Y)
  3. Filter by: DNP- or DailyNotification

Console.app:

  1. Open Console.app
  2. Select device/simulator
  3. 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:

  1. Reproduce the issue
  2. Collect logs from Xcode Console or Console.app
  3. Filter by DNP- prefix
  4. 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