Implement UNUserNotificationCenterDelegate in AppDelegate to display notifications when app is in foreground. Add visual feedback indicator in test app UI to confirm notification delivery. Changes: - AppDelegate: Conform to UNUserNotificationCenterDelegate protocol - AppDelegate: Implement willPresent and didReceive delegate methods - AppDelegate: Set delegate at multiple lifecycle points to ensure it's always active (immediate, after Capacitor init, on app active) - UI: Add notification received indicator in status card - UI: Add periodic check for notification delivery (every 5 seconds) - UI: Add instructions on where to look for notification banner - Docs: Add IOS_LOGGING_GUIDE.md for debugging iOS logs This fixes the issue where scheduled notifications were not visible when the app was in the foreground. The delegate method now properly presents notifications with banner, sound, and badge options. Verified working: Logs show delegate method called successfully when notification fires, with proper presentation options set.
284 lines
8.1 KiB
Markdown
284 lines
8.1 KiB
Markdown
# iOS Logging Guide - How to Check Logs for Errors
|
|
|
|
**Purpose:** Quick reference for viewing iOS app logs during development and debugging
|
|
|
|
**Last Updated:** 2025-11-15
|
|
**Status:** 🎯 **ACTIVE** - Reference guide for iOS debugging
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
**Most Common Methods (in order of ease):**
|
|
|
|
1. **Xcode Console** (when app is running in Xcode) - Easiest
|
|
2. **Console.app** (macOS system console) - Good for background logs
|
|
3. **Command-line** (`xcrun simctl`) - Best for automation/scripts
|
|
|
|
---
|
|
|
|
## Method 1: Xcode Console (Recommended for Development)
|
|
|
|
**When to use:** App is running in Xcode (simulator or device)
|
|
|
|
### Steps:
|
|
|
|
1. **Open Xcode** and run your app (Cmd+R)
|
|
2. **Open Debug Area:**
|
|
- Press **Cmd+Shift+Y** (or View → Debug Area → Activate Console)
|
|
- Or click the bottom panel icon in Xcode
|
|
3. **Filter logs:**
|
|
- Click the search box at bottom of console
|
|
- Type: `DNP-` or `DailyNotification` or `Error`
|
|
- Press Enter
|
|
|
|
### Filter Examples:
|
|
|
|
```
|
|
DNP-PLUGIN # Plugin operations
|
|
DNP-FETCH # Background fetch operations
|
|
DNP-SCHEDULER # Scheduling operations
|
|
DNP-STORAGE # Storage operations
|
|
Error # All errors
|
|
```
|
|
|
|
### Copy-Paste Commands (LLDB Console):
|
|
|
|
When app is running, you can also use LLDB commands in Xcode console:
|
|
|
|
```swift
|
|
// Check pending notifications
|
|
po UNUserNotificationCenter.current().pendingNotificationRequests()
|
|
|
|
// Check permission status
|
|
po await UNUserNotificationCenter.current().notificationSettings()
|
|
|
|
// Manually trigger BGTask (simulator only)
|
|
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.timesafari.dailynotification.fetch"]
|
|
```
|
|
|
|
---
|
|
|
|
## Method 2: Console.app (macOS System Console)
|
|
|
|
**When to use:** App is running in background, or you want to see system-level logs
|
|
|
|
### Steps:
|
|
|
|
1. **Open Console.app:**
|
|
- Press **Cmd+Space** (Spotlight)
|
|
- Type: `Console`
|
|
- Press Enter
|
|
- Or: Applications → Utilities → Console
|
|
|
|
2. **Select Device/Simulator:**
|
|
- In left sidebar, expand "Devices"
|
|
- Select your simulator or connected device
|
|
- Or select "All Logs" for system-wide logs
|
|
|
|
3. **Filter logs:**
|
|
- Click search box (top right)
|
|
- Type: `DNP-` or `com.timesafari.dailynotification`
|
|
- Press Enter
|
|
|
|
### Filter by Subsystem (Structured Logging):
|
|
|
|
The plugin uses structured logging with subsystems:
|
|
|
|
```
|
|
com.timesafari.dailynotification.plugin # Plugin operations
|
|
com.timesafari.dailynotification.fetch # Fetch operations
|
|
com.timesafari.dailynotification.scheduler # Scheduling operations
|
|
com.timesafari.dailynotification.storage # Storage operations
|
|
```
|
|
|
|
**To filter by subsystem:**
|
|
- In Console.app search: `subsystem:com.timesafari.dailynotification`
|
|
|
|
---
|
|
|
|
## Method 3: Command-Line (xcrun simctl)
|
|
|
|
**When to use:** Automation, scripts, or when Xcode/Console.app aren't available
|
|
|
|
### Stream Live Logs (Simulator):
|
|
|
|
```bash
|
|
# Stream all logs from booted simulator
|
|
xcrun simctl spawn booted log stream
|
|
|
|
# Stream only plugin logs (filtered)
|
|
xcrun simctl spawn booted log stream --predicate 'subsystem == "com.timesafari.dailynotification"'
|
|
|
|
# Stream with DNP- prefix filter
|
|
xcrun simctl spawn booted log stream | grep "DNP-"
|
|
```
|
|
|
|
### Save Logs to File:
|
|
|
|
```bash
|
|
# Save all logs to file
|
|
xcrun simctl spawn booted log stream > device.log 2>&1
|
|
|
|
# Save filtered logs
|
|
xcrun simctl spawn booted log stream --predicate 'subsystem == "com.timesafari.dailynotification"' > plugin.log 2>&1
|
|
|
|
# Then analyze with grep
|
|
grep -E "\[DNP-(FETCH|SCHEDULER|PLUGIN)\]" device.log
|
|
```
|
|
|
|
### View Recent Logs (Not Streaming):
|
|
|
|
```bash
|
|
# Show recent logs (last 100 lines)
|
|
xcrun simctl spawn booted log show --last 1m | grep "DNP-"
|
|
|
|
# Show logs for specific time range
|
|
xcrun simctl spawn booted log show --start "2025-11-15 10:00:00" --end "2025-11-15 11:00:00" | grep "DNP-"
|
|
```
|
|
|
|
### Physical Device Logs:
|
|
|
|
```bash
|
|
# List connected devices
|
|
xcrun devicectl list devices
|
|
|
|
# Stream logs from physical device (requires device UDID)
|
|
xcrun devicectl device process launch --device <UDID> com.timesafari.dailynotification.test
|
|
|
|
# Or use Console.app for physical devices (easier)
|
|
```
|
|
|
|
---
|
|
|
|
## Method 4: Validate Log Sequence (Automated)
|
|
|
|
**When to use:** Testing prefetch cycles, verifying complete execution
|
|
|
|
### Using Validation Script:
|
|
|
|
```bash
|
|
# From log file
|
|
./scripts/validate-ios-logs.sh device.log
|
|
|
|
# From live stream
|
|
xcrun simctl spawn booted log stream --predicate 'subsystem == "com.timesafari.dailynotification"' | ./scripts/validate-ios-logs.sh
|
|
|
|
# From filtered grep
|
|
grep -E "\[DNP-(FETCH|SCHEDULER|PLUGIN)\]" device.log | ./scripts/validate-ios-logs.sh
|
|
```
|
|
|
|
**See:** `scripts/validate-ios-logs.sh` for complete validation script
|
|
|
|
---
|
|
|
|
## Common Log Prefixes
|
|
|
|
**Plugin Logs (look for these):**
|
|
|
|
| Prefix | Meaning | Example |
|
|
|--------|---------|---------|
|
|
| `[DNP-PLUGIN]` | Main plugin operations | `[DNP-PLUGIN] configure() called` |
|
|
| `[DNP-FETCH]` | Background fetch operations | `[DNP-FETCH] BGTask handler invoked` |
|
|
| `[DNP-SCHEDULER]` | Notification scheduling | `[DNP-SCHEDULER] Scheduling notification` |
|
|
| `[DNP-STORAGE]` | Storage/DB operations | `[DNP-STORAGE] Persisted schedule` |
|
|
| `[DNP-DEBUG]` | Debug diagnostics | `[DNP-DEBUG] Plugin class found` |
|
|
|
|
**Error Indicators:**
|
|
|
|
- `Error:` - System errors
|
|
- `Failed:` - Operation failures
|
|
- `❌` - Visual error markers in logs
|
|
- `⚠️` - Warning markers
|
|
|
|
---
|
|
|
|
## Troubleshooting Common Issues
|
|
|
|
### Issue: No logs appearing
|
|
|
|
**Solutions:**
|
|
1. **Check app is running:** App must be launched to generate logs
|
|
2. **Check filter:** Remove filters to see all logs
|
|
3. **Check log level:** Some logs may be at debug level only
|
|
4. **Restart logging:** Close and reopen Console.app or restart log stream
|
|
|
|
### Issue: Too many logs (noise)
|
|
|
|
**Solutions:**
|
|
1. **Use specific filters:** `DNP-` instead of `DailyNotification`
|
|
2. **Filter by subsystem:** `subsystem:com.timesafari.dailynotification`
|
|
3. **Use time range:** Only show logs from last 5 minutes
|
|
4. **Use validation script:** Automatically filters for important events
|
|
|
|
### Issue: Can't see background task logs
|
|
|
|
**Solutions:**
|
|
1. **Use Console.app:** Background tasks show better in system console
|
|
2. **Check Background App Refresh:** Must be enabled for BGTask logs
|
|
3. **Use log stream:** `xcrun simctl spawn booted log stream` shows all logs
|
|
4. **Check predicate:** Use `--predicate` to filter specific subsystems
|
|
|
|
### Issue: Physical device logs not showing
|
|
|
|
**Solutions:**
|
|
1. **Use Console.app:** Easiest for physical devices
|
|
2. **Check device connection:** Device must be connected and trusted
|
|
3. **Check provisioning:** Device must be provisioned for development
|
|
4. **Use Xcode:** Xcode → Window → Devices and Simulators → View Device Logs
|
|
|
|
---
|
|
|
|
## Quick Reference Commands
|
|
|
|
### Copy-Paste Ready Commands:
|
|
|
|
```bash
|
|
# Stream plugin logs (simulator)
|
|
xcrun simctl spawn booted log stream --predicate 'subsystem == "com.timesafari.dailynotification"'
|
|
|
|
# Save logs to file
|
|
xcrun simctl spawn booted log stream > device.log 2>&1
|
|
|
|
# View recent errors
|
|
xcrun simctl spawn booted log show --last 5m | grep -i "error\|failed\|DNP-"
|
|
|
|
# Validate log sequence
|
|
grep -E "\[DNP-(FETCH|SCHEDULER|PLUGIN)\]" device.log | ./scripts/validate-ios-logs.sh
|
|
|
|
# Check app logs only
|
|
xcrun simctl spawn booted log stream --predicate 'process == "App"'
|
|
```
|
|
|
|
---
|
|
|
|
## Log Levels and Filtering
|
|
|
|
**iOS Log Levels:**
|
|
- **Default:** Shows Info, Error, Fault
|
|
- **Debug:** Shows Debug, Info, Error, Fault
|
|
- **Error:** Shows Error, Fault only
|
|
|
|
**To see debug logs:**
|
|
- In Xcode: Product → Scheme → Edit Scheme → Run → Arguments → Environment Variables
|
|
- Add: `OS_ACTIVITY_MODE=disable` (shows all logs including debug)
|
|
|
|
**Or use Console.app:**
|
|
- Action menu → Include Info Messages
|
|
- Action menu → Include Debug Messages
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- **Testing Guide:** `doc/test-app-ios/IOS_PREFETCH_TESTING.md` - Comprehensive testing procedures
|
|
- **Test App Requirements:** `doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md` - Debugging section
|
|
- **Validation Script:** `scripts/validate-ios-logs.sh` - Automated log sequence validation
|
|
- **Main Directive:** `doc/directives/0003-iOS-Android-Parity-Directive.md` - Implementation details
|
|
|
|
---
|
|
|
|
**Status:** 🎯 **READY FOR USE**
|
|
**Maintainer:** Matthew Raymer
|
|
|