Fixed critical compilation errors preventing iOS plugin build: - Updated logger API calls from logger.debug(TAG, msg) to logger.log(.debug, msg) across all iOS plugin files to match DailyNotificationLogger interface - Fixed async/await concurrency in makeConditionalRequest using semaphore pattern - Fixed NotificationContent immutability by creating new instances instead of mutation - Changed private access control to internal for extension-accessible methods - Added iOS 15.0+ availability checks for interruptionLevel property - Fixed static member references using Self.MEMBER_NAME syntax - Added missing .scheduling case to exhaustive switch statement - Fixed variable initialization in retry state closures Added DailyNotificationStorage.swift implementation matching Android pattern. Updated build scripts with improved error reporting and full log visibility. iOS plugin now compiles successfully. All build errors resolved.
6.0 KiB
6.0 KiB
iOS Native Interface Structure
Author: Matthew Raymer
Date: November 4, 2025
Overview
The iOS native interface mirrors the Android structure, providing the same functionality through iOS-specific implementations.
Directory Structure
ios/App/App/
├── AppDelegate.swift # Application lifecycle (equivalent to PluginApplication.java)
├── ViewController.swift # Main view controller (equivalent to MainActivity.java)
├── SceneDelegate.swift # Scene-based lifecycle (iOS 13+)
├── Info.plist # App configuration (equivalent to AndroidManifest.xml)
├── capacitor.config.json # Capacitor configuration
├── config.xml # Cordova compatibility
└── public/ # Web assets (equivalent to assets/public/)
├── index.html
├── capacitor.js
└── capacitor_plugins.js
File Descriptions
AppDelegate.swift
Purpose: Application lifecycle management
Equivalent: PluginApplication.java on Android
- Handles app lifecycle events (launch, background, foreground, termination)
- Registers for push notifications
- Handles URL schemes and universal links
- Initializes plugin demo fetcher (equivalent to Android's
PluginApplication.onCreate())
Key Methods:
application(_:didFinishLaunchingWithOptions:)- App initializationapplicationDidEnterBackground(_:)- Background handlingapplicationWillEnterForeground(_:)- Foreground handlingapplication(_:didRegisterForRemoteNotificationsWithDeviceToken:)- Push notification registration
ViewController.swift
Purpose: Main view controller extending Capacitor's bridge
Equivalent: MainActivity.java on Android
- Extends
CAPBridgeViewController(Capacitor's bridge view controller) - Initializes plugin and registers native fetcher
- Handles view lifecycle events
Key Methods:
viewDidLoad()- View initializationinitializePlugin()- Plugin registration (equivalent to Android's plugin registration)
SceneDelegate.swift
Purpose: Scene-based lifecycle management (iOS 13+)
Equivalent: None on Android (iOS-specific)
- Handles scene creation and lifecycle
- Manages window and view controller setup
- Required for modern iOS apps using scene-based architecture
Info.plist
Purpose: App configuration and permissions
Equivalent: AndroidManifest.xml on Android
Key Entries:
CFBundleIdentifier- App bundle IDNSUserNotificationsUsageDescription- Notification permission descriptionUIBackgroundModes- Background modes (fetch, processing, remote-notification)BGTaskSchedulerPermittedIdentifiers- Background task identifiersUIApplicationSceneManifest- Scene configuration
Comparison: Android vs iOS
| Component | Android | iOS |
|---|---|---|
| Application Class | PluginApplication.java |
AppDelegate.swift |
| Main Activity | MainActivity.java |
ViewController.swift |
| Config File | AndroidManifest.xml |
Info.plist |
| Web Assets | assets/public/ |
public/ |
| Lifecycle | onCreate(), onResume(), etc. |
viewDidLoad(), viewWillAppear(), etc. |
| Bridge | BridgeActivity |
CAPBridgeViewController |
Plugin Registration
Android
public class PluginApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
NativeNotificationContentFetcher demoFetcher = new DemoNativeFetcher();
DailyNotificationPlugin.setNativeFetcher(demoFetcher);
}
}
iOS
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Plugin registration happens in ViewController after Capacitor bridge is initialized
return true
}
}
class ViewController: CAPBridgeViewController {
override func viewDidLoad() {
super.viewDidLoad()
initializePlugin()
}
private func initializePlugin() {
// Register demo native fetcher if implementing SPI
// DailyNotificationPlugin.setNativeFetcher(DemoNativeFetcher())
}
}
Build Process
- Swift Compilation: Compiles
AppDelegate.swift,ViewController.swift,SceneDelegate.swift - Capacitor Integration: Links with Capacitor framework and plugin
- Web Assets: Copies
public/directory to app bundle - Info.plist: Processes app configuration and permissions
- App Bundle: Creates
.appbundle for installation
Permissions
Android (AndroidManifest.xml)
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
iOS (Info.plist)
<key>NSUserNotificationsUsageDescription</key>
<string>This app uses notifications to deliver daily updates and reminders.</string>
<key>UIBackgroundModes</key>
<array>
<string>background-fetch</string>
<string>background-processing</string>
<string>remote-notification</string>
</array>
Background Tasks
Android
- Uses
WorkManagerandAlarmManager - Declared in
AndroidManifest.xmlreceivers
iOS
- Uses
BGTaskSchedulerandUNUserNotificationCenter - Declared in
Info.plistwithBGTaskSchedulerPermittedIdentifiers
Next Steps
- Ensure Xcode project includes these Swift files
- Configure build settings in Xcode project
- Add app icons and launch screen
- Test plugin registration and native fetcher
- Verify background tasks work correctly