# iOS Test App Setup Guide
**Author**: Matthew Raymer
**Date**: 2025-11-12
**Status**: Active
## Overview
This guide explains how to set up the standalone iOS test app for the DailyNotification plugin. The iOS test app mirrors the Android test app (`android-test-app`) functionality and provides a comprehensive testing environment for all plugin features.
## Prerequisites
### Required
- **macOS** (iOS development requires macOS)
- **Xcode 15.0+** with Command Line Tools
```bash
xcode-select --install # If not installed
```
- **Ruby 3.1+** (required for CocoaPods)
- Check version: `ruby --version`
- If using system Ruby and version < 3.1, use rbenv (recommended)
- **CocoaPods** (dependency manager)
- **Node.js 18+** and npm (for Capacitor CLI)
- **UTF-8 encoding** (required for CocoaPods)
### Recommended
- **rbenv** (Ruby version manager) - Makes Ruby/CocoaPods setup easier
- **Homebrew** (package manager) - Simplifies installation
### Quick Requirements Check
Run the requirements checker:
```bash
cd test-apps/ios-test-app
./scripts/check-requirements.sh
```
This will verify all prerequisites and provide installation instructions for missing items.
## Quick Start
### Option 1: Use Existing Structure (Recommended)
If `ios/App` already exists, copy it:
```bash
# From project root
cd test-apps/ios-test-app
cp -r ../../ios/App ./App
cd App
export LANG=en_US.UTF-8
~/.rbenv/shims/pod install # or: pod install if in PATH
```
Then update configuration files (see Configuration section below).
### Option 2: Generate with Capacitor CLI
```bash
cd test-apps/ios-test-app
npx @capacitor/create-app@latest App --template blank
```
Then follow the configuration steps below.
## Configuration
### Step 1: Podfile Configuration
Edit `App/Podfile`:
```ruby
platform :ios, '13.0'
use_frameworks!
source 'https://cdn.cocoapods.org/'
def capacitor_pods
pod 'Capacitor', :path => '../../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../../node_modules/@capacitor/ios'
pod 'DailyNotificationPlugin', :path => '../../../ios'
end
target 'App' do
capacitor_pods
end
```
### Step 2: Install CocoaPods Dependencies
**First, check requirements:**
```bash
cd test-apps/ios-test-app
./scripts/check-requirements.sh
```
**Then install CocoaPods dependencies:**
```bash
cd test-apps/ios-test-app/App
export LANG=en_US.UTF-8 # Required for CocoaPods
# Use the pod command found by check-requirements.sh, or:
# If using rbenv:
~/.rbenv/shims/pod install
# If using system Ruby:
pod install
# If using Homebrew:
pod install
```
**Note**: The build script will automatically detect and use the correct `pod` command location.
### Step 3: Capacitor Configuration
Edit `App/App/capacitor.config.json`:
```json
{
"appId": "com.timesafari.dailynotification",
"appName": "DailyNotification Test App",
"webDir": "public",
"server": {
"iosScheme": "capacitor"
},
"plugins": {
"DailyNotification": {
"fetchUrl": "https://api.example.com/daily-content",
"scheduleTime": "09:00",
"enableNotifications": true,
"debugMode": true
}
}
}
```
### Step 4: Info.plist Configuration
Edit `App/App/Info.plist` to include required permissions and background modes:
```xml
UIBackgroundModes
background-fetch
background-processing
remote-notification
BGTaskSchedulerPermittedIdentifiers
com.timesafari.dailynotification.fetch
com.timesafari.dailynotification.notify
NSUserNotificationsUsageDescription
This app uses notifications to deliver daily updates and reminders.
```
**Key iOS Permissions** (equivalent to Android):
- **Notifications**: `NSUserNotificationsUsageDescription` (like Android's `POST_NOTIFICATIONS`)
- **Background Fetch**: `UIBackgroundModes` with `background-fetch` (like Android's WorkManager)
- **Background Processing**: `UIBackgroundModes` with `background-processing`
- **Exact Alarms**: Always supported on iOS via `UNUserNotificationCenter` (no permission needed)
### Step 5: Copy Test Interface
Copy the test HTML from Android test app:
```bash
# From project root
cp test-apps/android-test-app/app/src/main/assets/public/index.html \
test-apps/ios-test-app/App/App/public/index.html
```
The test interface provides:
- Plugin availability testing
- Configuration management
- Status checking
- Notification scheduling
- Permission management
- Channel/notification settings (iOS: app-level)
- Comprehensive status checks
## Build and Run
### Using Xcode (Recommended for Development)
```bash
cd test-apps/ios-test-app/App
open App.xcworkspace
# Then build and run in Xcode (⌘R)
```
**Important**: Always open the `.xcworkspace` file, not the `.xcodeproj` file, when using CocoaPods.
### Using Command Line
```bash
cd test-apps/ios-test-app/App
export LANG=en_US.UTF-8
# List available simulators
xcrun simctl list devices available | grep -i iphone
# Build for simulator
xcodebuild -workspace App.xcworkspace \
-scheme App \
-configuration Debug \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
clean build
# Build and run on simulator
xcodebuild -workspace App.xcworkspace \
-scheme App \
-configuration Debug \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
build \
&& xcrun simctl boot "iPhone 17 Pro" 2>/dev/null || true \
&& xcrun simctl install booted "$(xcodebuild -workspace App.xcworkspace -scheme App -configuration Debug -sdk iphonesimulator -showBuildSettings | grep -m 1 "BUILT_PRODUCTS_DIR" | sed 's/.*= *//')/App.app" \
&& xcrun simctl launch booted com.timesafari.dailynotification
```
### Using Build Script
```bash
cd test-apps/ios-test-app
./scripts/build-and-deploy.sh
```
## Plugin Registration
The plugin is automatically registered via Capacitor when included in `Podfile`. No manual registration needed in:
- `AppDelegate.swift` (Android equivalent: `PluginApplication.java`)
- `ViewController.swift` (Android equivalent: `MainActivity.java`)
Capacitor automatically discovers and registers plugins from CocoaPods.
## Test Interface Features
The test interface (`App/App/public/index.html`) provides comprehensive testing for:
### Basic Plugin Tests
- **Test Plugin**: Verify plugin is loaded and accessible
- **Configure Plugin**: Set plugin configuration
- **Check Status**: Get current plugin status
### Notification Tests
- **Test Notification**: Send immediate test notification
- **Schedule Notification**: Schedule daily notification
- **Show Reminder**: Display reminder notification
### Permission Management
- **Check Permissions**: Check notification authorization status
- **Request Permissions**: Request notification permissions
- **Exact Alarm Settings**: Open notification settings (iOS: app-level settings)
### Channel Management (iOS: App-Level)
- **Check Channel Status**: Check if notifications are enabled
- **Open Channel Settings**: Open app notification settings
- **Comprehensive Status**: Get full status including permissions, schedules, and battery
## iOS-Specific Considerations
### Background Execution
iOS handles background execution differently than Android:
- **Background Fetch**: Uses `BGTaskScheduler` (similar to Android's WorkManager)
- **Background Processing**: Limited time budget (typically 30 seconds)
- **Background App Refresh**: User-controlled system setting (cannot be checked programmatically)
### Notification Scheduling
- **UNUserNotificationCenter**: Always supports exact alarms (no permission needed)
- **Daily Repeats**: Use `UNCalendarNotificationTrigger` with `repeats: true`
- **Background Tasks**: Use `BGAppRefreshTask` for prefetch operations
### Permissions
- **Notifications**: Single app-level permission (no channels like Android)
- **Exact Alarms**: Always supported, no permission needed
- **Battery Optimization**: Not applicable (Background App Refresh is system setting)
### Storage
- **UserDefaults**: For schedules and configuration (like Android's SharedPreferences)
- **Core Data**: For content cache and history (like Android's Room database)
## Code Signing
### Simulator Builds (Default)
**No signing required** - The build scripts automatically disable signing for simulator builds:
```bash
CODE_SIGN_IDENTITY=''
CODE_SIGNING_REQUIRED=NO
CODE_SIGNING_ALLOWED=NO
```
This is handled automatically by the build scripts.
### Device Builds
**For physical devices, you need proper signing:**
1. **Open project in Xcode:**
```bash
cd test-apps/ios-test-app/App
open App.xcworkspace
```
2. **Configure signing:**
- Select project in navigator
- Select target "App"
- Go to "Signing & Capabilities" tab
- Check "Automatically manage signing"
- Select your Team (Apple Developer account)
3. **Build for device:**
```bash
xcodebuild -workspace App.xcworkspace \
-scheme App \
-sdk iphoneos \
-configuration Debug \
-destination 'generic/platform=iOS' \
CODE_SIGN_STYLE=Automatic \
DEVELOPMENT_TEAM="YOUR_TEAM_ID" \
clean build
```
**See `docs/IOS_CODE_SIGNING.md` for complete signing guide.**
## Troubleshooting
### Plugin Not Found
1. **Ensure plugin is built**:
```bash
cd ../../ios
export LANG=en_US.UTF-8
xcodebuild -workspace DailyNotificationPlugin.xcworkspace \
-scheme DailyNotificationPlugin \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
GENERATE_INFOPLIST_FILE=YES \
clean build
```
2. **Verify Podfile includes plugin**:
```bash
grep DailyNotificationPlugin test-apps/ios-test-app/App/Podfile
```
3. **Check plugin registration**:
```bash
# Plugin should be in Pods project
ls -la test-apps/ios-test-app/App/Pods/Local\ Podspecs/
```
### CocoaPods Issues
1. **Encoding errors**:
```bash
export LANG=en_US.UTF-8
~/.rbenv/shims/pod install
```
2. **Clean reinstall**:
```bash
cd test-apps/ios-test-app/App
pod deintegrate
rm -rf Pods Podfile.lock
pod install
```
3. **Ruby version issues**:
```bash
# Ensure Ruby 3.1+ is available
ruby --version
# Use rbenv if needed
rbenv install 3.1.0
rbenv local 3.1.0
```
### Build Errors
1. **Clean build folder**:
```bash
# In Xcode: Product > Clean Build Folder (⌘⇧K)
# Or command line:
xcodebuild clean -workspace App.xcworkspace -scheme App
```
2. **Delete derived data**:
```bash
rm -rf ~/Library/Developer/Xcode/DerivedData
```
3. **Reset CocoaPods cache**:
```bash
pod cache clean --all
pod install
```
4. **Info.plist errors**:
- Ensure `GENERATE_INFOPLIST_FILE=YES` is set for framework targets
- Verify all required keys are present in `Info.plist`
### Runtime Issues
1. **Notifications not appearing**:
- Check notification permissions in iOS Settings
- Verify Background App Refresh is enabled
- Check console logs for errors
2. **Background tasks not running**:
- Background App Refresh must be enabled in iOS Settings
- Tasks have limited execution time (typically 30 seconds)
- System may delay or skip tasks based on usage patterns
3. **Plugin methods not found**:
- Verify plugin is built and included in Pods
- Check Capacitor bridge is initialized
- Review console logs for registration errors
## Project Structure
```
test-apps/ios-test-app/
├── App/
│ ├── App/
│ │ ├── AppDelegate.swift # App lifecycle (Android: PluginApplication.java)
│ │ ├── ViewController.swift # Main view (Android: MainActivity.java)
│ │ ├── SceneDelegate.swift # Scene lifecycle (iOS 13+)
│ │ ├── Info.plist # Permissions & config (Android: AndroidManifest.xml)
│ │ ├── capacitor.config.json # Capacitor config
│ │ └── public/
│ │ └── index.html # Test interface
│ ├── App.xcworkspace # Workspace (includes Pods)
│ ├── Podfile # CocoaPods dependencies
│ └── Podfile.lock # Locked versions
├── scripts/
│ └── build-and-deploy.sh # Build automation
├── README.md # Overview
└── SETUP.md # This file
```
## Dependencies
The iOS test app requires:
- **Capacitor**: Core framework
- **CapacitorCordova**: Cordova compatibility
- **DailyNotificationPlugin**: The plugin being tested
Additional iOS dependencies (managed by plugin):
- **UserNotifications**: Notification scheduling
- **BackgroundTasks**: Background execution
- **CoreData**: Persistent storage
## Comparison with Android Test App
| Feature | Android | iOS |
|---------|---------|-----|
| **App Entry** | `MainActivity.java` | `ViewController.swift` |
| **Lifecycle** | `PluginApplication.java` | `AppDelegate.swift` |
| **Manifest** | `AndroidManifest.xml` | `Info.plist` |
| **Build System** | Gradle | Xcode + CocoaPods |
| **Dependencies** | `build.gradle` | `Podfile` |
| **Permissions** | Runtime + Manifest | Info.plist + Runtime |
| **Background** | WorkManager | BGTaskScheduler |
| **Notifications** | NotificationManager | UNUserNotificationCenter |
| **Storage** | Room + SharedPreferences | Core Data + UserDefaults |
| **Channels** | Multiple channels | App-level only |
## Next Steps
1. **Build plugin**:
```bash
cd ../../ios
./scripts/build-native.sh --platform ios
```
2. **Set up test app**:
```bash
cd test-apps/ios-test-app
# Follow Quick Start section above
```
3. **Install dependencies**:
```bash
cd App
export LANG=en_US.UTF-8
~/.rbenv/shims/pod install
```
4. **Build and run**:
```bash
open App.xcworkspace
# Build and run in Xcode
```
5. **Test functionality**:
- Use test interface to verify all plugin methods
- Test notification scheduling
- Verify permissions work correctly
- Test background tasks (requires Background App Refresh enabled)
## Additional Resources
- [iOS Plugin Implementation Guide](../../docs/IOS_IMPLEMENTATION_COMPLETE.md)
- [iOS Build Quick Reference](../../docs/IOS_BUILD_QUICK_REFERENCE.md)
- [CocoaPods Installation Guide](../../docs/COCOAPODS_INSTALLATION.md)
- [iOS Setup Requirements](../../docs/IOS_SETUP_REQUIREMENTS.md)
- [Android Test App](../../android-test-app/) - For comparison
## Support
For issues or questions:
1. Check troubleshooting section above
2. Review iOS plugin documentation
3. Compare with Android test app implementation
4. Check Xcode console logs for detailed errors