fix(ios): resolve compilation errors and enable successful build

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.
This commit is contained in:
Matthew Raymer
2025-11-04 22:22:02 -08:00
parent 4be87acc14
commit 8ded555a21
17 changed files with 2000 additions and 196 deletions

View File

@@ -0,0 +1,106 @@
//
// AppDelegate.swift
// DailyNotification Test App
//
// Application delegate for the Daily Notification Plugin demo app.
// Registers the native content fetcher SPI implementation.
//
// @author Matthew Raymer
// @version 1.0.0
// @created 2025-11-04
//
import UIKit
import Capacitor
/**
* Application delegate for Daily Notification Plugin demo app
* Equivalent to PluginApplication.java on Android
*/
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Initialize Daily Notification Plugin demo fetcher
// Note: This is called before Capacitor bridge is initialized
// Plugin registration happens in ViewController
print("AppDelegate: Initializing Daily Notification Plugin demo app")
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Pause ongoing tasks
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Release resources when app enters background
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Restore resources when app enters foreground
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart paused tasks
}
func applicationWillTerminate(_ application: UIApplication) {
// Save data before app terminates
}
// MARK: - URL Scheme Handling
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
// Handle URL schemes (e.g., deep links)
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
// MARK: - Universal Links
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
// Handle universal links
return ApplicationDelegateProxy.shared.application(
application,
continue: userActivity,
restorationHandler: restorationHandler
)
}
// MARK: - Push Notifications
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
// Handle device token registration
NotificationCenter.default.post(
name: Notification.Name("didRegisterForRemoteNotifications"),
object: nil,
userInfo: ["deviceToken": deviceToken]
)
}
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
// Handle registration failure
print("AppDelegate: Failed to register for remote notifications: \(error)")
}
}

119
ios/App/App/Info.plist Normal file
View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- App Display Name -->
<key>CFBundleDisplayName</key>
<string>DailyNotification Test</string>
<!-- Bundle Identifier -->
<key>CFBundleIdentifier</key>
<string>com.timesafari.dailynotification</string>
<!-- Bundle Name -->
<key>CFBundleName</key>
<string>DailyNotification Test App</string>
<!-- Version -->
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<!-- Build Number -->
<key>CFBundleVersion</key>
<string>1</string>
<!-- Minimum iOS Version -->
<key>LSMinimumSystemVersion</key>
<string>13.0</string>
<!-- Device Family -->
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<!-- Supported Interface Orientations -->
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<!-- Supported Interface Orientations (iPad) -->
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<!-- Status Bar Style -->
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>
<!-- Status Bar Hidden -->
<key>UIStatusBarHidden</key>
<false/>
<!-- Launch Screen -->
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<!-- Privacy Usage Descriptions -->
<key>NSUserNotificationsUsageDescription</key>
<string>This app uses notifications to deliver daily updates and reminders.</string>
<!-- Background Modes -->
<key>UIBackgroundModes</key>
<array>
<string>background-fetch</string>
<string>background-processing</string>
<string>remote-notification</string>
</array>
<!-- Background Task Identifiers -->
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.timesafari.dailynotification.fetch</string>
<string>com.timesafari.dailynotification.notify</string>
</array>
<!-- App Transport Security -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSExceptionDomains</key>
<dict>
<!-- Add your callback domains here -->
</dict>
</dict>
<!-- Scene Configuration (iOS 13+) -->
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<!-- Background App Refresh -->
<key>UIApplicationExitsOnSuspend</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,61 @@
//
// SceneDelegate.swift
// DailyNotification Test App
//
// Scene delegate for iOS 13+ scene-based lifecycle.
// Handles scene creation and lifecycle events.
//
// @author Matthew Raymer
// @version 1.0.0
// @created 2025-11-04
//
import UIKit
/**
* Scene delegate for iOS 13+ scene-based lifecycle
* Required for modern iOS apps using scene-based architecture
*/
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
// Called when a new scene session is being created
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
self.window = window
// Create and configure the view controller
let viewController = ViewController()
window.rootViewController = viewController
window.makeKeyAndVisible()
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called when the scene is being released by the system
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from inactive to active state
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from active to inactive state
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called when the scene is about to move from background to foreground
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called when the scene has moved from background to foreground
}
}

View File

@@ -0,0 +1,69 @@
//
// ViewController.swift
// DailyNotification Test App
//
// Main view controller for the Daily Notification Plugin demo app.
// Equivalent to MainActivity.java on Android - extends Capacitor's bridge.
//
// @author Matthew Raymer
// @version 1.0.0
// @created 2025-11-04
//
import UIKit
import Capacitor
/**
* Main view controller extending Capacitor's bridge view controller
* Equivalent to MainActivity extends BridgeActivity on Android
*/
class ViewController: CAPBridgeViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Initialize Daily Notification Plugin demo fetcher
// This is called after Capacitor bridge is initialized
initializePlugin()
}
/**
* Initialize plugin and register native fetcher
* Equivalent to PluginApplication.onCreate() on Android
*/
private func initializePlugin() {
print("ViewController: Initializing Daily Notification Plugin")
// Note: Plugin registration happens automatically via Capacitor
// Native fetcher registration can be done here if needed
// Example: Register demo native fetcher (if implementing SPI)
// DailyNotificationPlugin.setNativeFetcher(DemoNativeFetcher())
print("ViewController: Daily Notification Plugin initialized")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
// MARK: - Memory Management
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated
}
}