You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Core Issue: JS side of the code updates key value to true but the native UserDefaults key value returns false (or nil). Any fix to the issue would be much appreciated.
JavaScript (Angular Side):
The Preferences.set() function successfully sets the key isSyncing to "true".
A subsequent Preferences.get() confirms the value as "true".
Native (iOS Side):
The UserDefaults.didChangeNotification is triggered, but the native code reads the isSyncing value as "false".
This suggests that the native UserDefaults is not properly synchronized with the value set by the Capacitor Preferences plugin.
Root Cause
The issue arises because the Capacitor Preferences plugin does not guarantee immediate synchronization with the UserDefaults system. By default, updates to UserDefaults are asynchronous, and changes made by the plugin might not propagate in time for the native code to detect.
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
private var photoSyncService: PhotoSyncService?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize Firebase
FirebaseApp.configure()
// Check current user authentication
if let currentUser = Auth.auth().currentUser {
print("User is authenticated in Native Code with UID: \(currentUser.uid)")
} else {
print("No user in Native Code currently authenticated.")
}
// Initialize the PhotoSyncService
photoSyncService = PhotoSyncService()
print("⚡️ PhotoSyncService initialized in AppDelegate.")
// Add observer for UserDefaults changes
NotificationCenter.default.addObserver(
self,
selector: #selector(handleSyncStateChange),
name: UserDefaults.didChangeNotification,
object: nil
)
return true
}
// Extract sync handling logic into a separate method
// Handle UserDefaults changes
@objc private func handleSyncStateChange() {
// Access the standard UserDefaults
let userDefaults = UserDefaults.standard
// Read the "isSyncing" key
let isSyncingString = userDefaults.string(forKey: "isSyncing") ?? "false"
let isSyncing = (isSyncingString.lowercased() == "true")
print("⚡️ [AppDelegate] Detected UserDefaults change for isSyncing.")
print("⚡️ [AppDelegate] isSyncing raw value: \(isSyncingString)")
print("⚡️ [AppDelegate] Parsed isSyncing state: \(isSyncing)")
// Update the PhotoSyncService based on isSyncing value
if isSyncing {
print("⚡️ [AppDelegate] Syncing is enabled. Starting PhotoSyncService...")
self.photoSyncService?.startServiceIfNeeded()
} else {
print("⚡️ [AppDelegate] Syncing is disabled. Stopping PhotoSyncService...")
self.photoSyncService?.stopService()
}
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// See https://github.com/capawesome-team/capacitor-firebase/tree/main/packages/authentication#installation
if Auth.auth().canHandle(url) {
return true
}
// Called when the app was launched with a url. Feel free to add additional processing here,
// but if you want the App API to support tracking app url opens, make sure to keep this call
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Called when the app was launched with an activity, including Universal Links.
// Feel free to add additional processing here, but if you want the App API to support
// tracking app url opens, make sure to keep this call
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
NotificationCenter.default.post(name: Notification.Name.init("didReceiveRemoteNotification"), object: completionHandler, userInfo: userInfo)
}
deinit {
// Remove observer to prevent memory leaks
NotificationCenter.default.removeObserver(self, name: UserDefaults.didChangeNotification, object: nil)
}
}
I have been through the docs and nothing seems to fix this issue. Any help would be great.
The text was updated successfully, but these errors were encountered:
Core Issue: JS side of the code updates key value to true but the native UserDefaults key value returns false (or nil). Any fix to the issue would be much appreciated.
JavaScript (Angular Side):
The Preferences.set() function successfully sets the key isSyncing to "true".
A subsequent Preferences.get() confirms the value as "true".
Native (iOS Side):
The UserDefaults.didChangeNotification is triggered, but the native code reads the isSyncing value as "false".
This suggests that the native UserDefaults is not properly synchronized with the value set by the Capacitor Preferences plugin.
Root Cause
The issue arises because the Capacitor Preferences plugin does not guarantee immediate synchronization with the UserDefaults system. By default, updates to UserDefaults are asynchronous, and changes made by the plugin might not propagate in time for the native code to detect.
Code:
JS:
private async setSyncingState(value: boolean): Promise {
try {
// Set the syncing state
await Preferences.set({ key: SYNC_KEY, value: value.toString() });
console.log(
[Angular] Preferences.set completed. Key: ${SYNC_KEY}, Value: ${value}
,);
}
async enableSync(): Promise {
console.log('[Angular] Enabling sync...');
await this.setSyncingState(true);
}
async disableSync(): Promise {
console.log('[Angular] Disabling sync...');
await this.setSyncingState(false);
}
async checkSyncStatus(): Promise {
try {
const { value } = await Preferences.get({ key: SYNC_KEY });
const isSyncing = value === 'true';
console.log(
[Angular] Current sync status: ${isSyncing}
);} catch (error) {
console.error('Error reading sync status from Preferences:', error);
}
}
App Delegate:
import UIKit
import Capacitor
import FirebaseCore
import FirebaseAuth
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
}
I have been through the docs and nothing seems to fix this issue. Any help would be great.
The text was updated successfully, but these errors were encountered: