Xamarin.Forms中iOS数据无法存储至内存问题求助(含接口代码)
Xamarin.Forms iOS 无法存储设备令牌到本地内存的排查与解决
嘿,我来帮你捋捋这个存储设备令牌的问题!你在AppDelegate的RegisteredForRemoteNotifications方法里尝试把设备令牌存入NSUserDefaults但失败,大概率是这几个细节没处理好,咱们一个个来解决:
1. 设备令牌的字符串处理不完整
你当前的代码只去掉了令牌两端的尖括号,但deviceToken.Description返回的格式通常是<abc 123 def 456>,里面包含空格,直接存储会导致令牌格式错误,后续对比也会出问题。
修正后的令牌处理代码:
var deviceTokenStr = deviceToken.Description.Trim('<', '>').Replace(" ", string.Empty);
2. 未手动同步NSUserDefaults的写入操作
NSUserDefaults的写入默认是异步延迟持久化到磁盘的,如果写入后立刻读取,可能拿不到最新值。咱们可以手动调用同步方法确保数据写入完成。
添加同步操作:
NSUserDefaults.StandardUserDefaults.SetString(deviceTokenStr, "token"); NSUserDefaults.StandardUserDefaults.Synchronize(); // 确保写入磁盘
3. 线程安全问题(避免后台线程操作)
虽然NSUserDefaults是线程安全的,但RegisteredForRemoteNotifications方法可能在非主线程执行,切换到主线程操作能避免一些意外的存储失败。
切换到主线程执行存储:
Device.BeginInvokeOnMainThread(() => { NSUserDefaults.StandardUserDefaults.SetString(deviceTokenStr, "token"); NSUserDefaults.StandardUserDefaults.Synchronize(); });
4. 补全你的逻辑代码(避免截断导致未执行存储)
你的代码片段看起来没写完,完整的令牌对比+存储逻辑应该是这样的:
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { // 1. 正确解析设备令牌 var deviceTokenStr = deviceToken.Description.Trim('<', '>').Replace(" ", string.Empty); if (string.IsNullOrWhiteSpace(deviceTokenStr)) { Console.WriteLine("⚠️ 设备令牌解析失败"); return; } // 2. 获取之前存储的令牌 var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("token"); // 3. 令牌变化或首次存储时更新 if (string.IsNullOrEmpty(oldDeviceToken) || !oldDeviceToken.Equals(deviceTokenStr)) { Device.BeginInvokeOnMainThread(() => { NSUserDefaults.StandardUserDefaults.SetString(deviceTokenStr, "token"); NSUserDefaults.StandardUserDefaults.Synchronize(); Console.WriteLine("✅ 设备令牌已更新并存储"); }); } else { Console.WriteLine("ℹ️ 设备令牌未变化,无需更新"); } }
验证存储是否成功
你可以在FinishedLaunching方法里加一段代码,启动时读取存储的令牌,验证是否存储成功:
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { // ...其他初始化代码 var storedToken = NSUserDefaults.StandardUserDefaults.StringForKey("token"); if (!string.IsNullOrWhiteSpace(storedToken)) { Console.WriteLine("已存储的设备令牌:" + storedToken); } else { Console.WriteLine("未找到存储的设备令牌"); } // ...其他初始化代码 return base.FinishedLaunching(app, options); }
另外提一句:iOS 13+苹果推荐用UNUserNotificationCenter管理推送权限,但RegisteredForRemoteNotifications的调用逻辑还是不变的,上面的代码依然适用。
内容的提问来源于stack exchange,提问作者Joyce de Lanna
相关产品推荐
相关产品推荐

