You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS模拟器11.2中Keychain无法存储数据问题求助(附Xamarin代码)

排查iOS模拟器11.2中Xamarin Keychain存储失败的问题

我来帮你定位和解决这个问题,结合你的代码和iOS模拟器11.2的特性,常见的问题点和修复方案如下:

1. 先尝试重置模拟器缓存(最容易忽略的点)

iOS模拟器11.2的Keychain存在一些已知的沙盒缓存bug,有时候会导致数据无法正常写入或读取。你可以先做以下操作:

  • 打开Xcode,点击顶部菜单的 Window > Devices and Simulators
  • 在Simulators列表中选中你的iOS 11.2模拟器,右键选择 Erase All Content and Settings
  • 等待模拟器重置完成后,重新运行你的应用测试

2. 优化SecRecord的唯一性标识

你的代码中仅用GenericLabel来定位Keychain记录,这在某些场景下可能不够唯一,导致删除或添加操作匹配不到正确的记录。建议添加Service字段(用你的应用Bundle ID相关的字符串),增强记录的唯一性:

// 替换成你的应用实际的Bundle ID前缀,比如"com.yourcompany.yourapp"
var serviceIdentifier = "com.yourteam.yourapp.keychain";
var record = new SecRecord(SecKind.GenericPassword) { 
    ValueData = string.IsNullOrEmpty(userstring) ? NSData.Empty : NSData.FromString(userstring), 
    Generic = NSData.FromString(key), 
    Label = "Sanket",
    Service = serviceIdentifier // 新增Service字段,确保记录唯一
}; 

3. 添加错误日志排查具体问题

你的代码没有处理SecKeyChain.RemoveSecKeyChain.Add的返回状态,这很难定位到底是删除失败还是添加失败。建议添加日志输出,查看具体的错误码:

// 执行删除并检查状态
var removeStatus = SecKeyChain.Remove(record);
if (removeStatus != SecStatusCode.Success && removeStatus != SecStatusCode.ItemNotFound)
{
    Console.WriteLine($"Keychain 删除失败: {removeStatus}");
}

// 执行添加并检查状态
var addStatus = SecKeyChain.Add(record);
if (addStatus != SecStatusCode.Success)
{
    Console.WriteLine($"Keychain 添加失败: {addStatus}");
}

常见的错误码说明:

  • SecStatusCode.DuplicateItem: 记录已存在,说明之前的删除操作未匹配到记录
  • SecStatusCode.ItemNotFound: 删除时找不到对应记录(属于正常情况,比如首次存储时)
  • SecStatusCode.AuthFailed: 权限问题,需要检查Entitlements配置

4. 检查应用的Keychain权限配置

如果上述操作都无效,需要确认你的应用Entitlements配置是否正确:

  • 打开项目的Entitlements.plist文件(如果没有,右键项目>Add>New File>iOS>Entitlements)
  • 确保keychain-access-groups包含你的应用的Bundle ID,格式为$(AppIdentifierPrefix)com.yourcompany.yourapp$(AppIdentifierPrefix)会自动替换为你的开发者团队ID)
  • 在Xamarin项目的iOS Build设置中,确保Custom Entitlements选项指向这个Entitlements文件

修改后的完整示例代码

void StoreKeysInKeychain(string key, string value) { 
    var user = Settings.CurrentUser; 
    var userstring = JsonConvert.SerializeObject(user); 
    if (value == "logout") { 
        userstring = string.Empty; 
    }; 

    var serviceIdentifier = "com.yourteam.yourapp.keychain";
    var record = new SecRecord(SecKind.GenericPassword) { 
        ValueData = string.IsNullOrEmpty(userstring) ? NSData.Empty : NSData.FromString(userstring), 
        Generic = NSData.FromString(key), 
        Label = "Sanket",
        Service = serviceIdentifier
    }; 

    var removeStatus = SecKeyChain.Remove(record);
    if (removeStatus != SecStatusCode.Success && removeStatus != SecStatusCode.ItemNotFound)
    {
        Console.WriteLine($"Keychain 删除失败: {removeStatus}");
    }

    var addStatus = SecKeyChain.Add(record);
    if (addStatus != SecStatusCode.Success)
    {
        Console.WriteLine($"Keychain 添加失败: {addStatus}");
    }
} 

按照这个步骤排查,应该能解决iOS模拟器11.2下的Keychain存储问题。

内容的提问来源于stack exchange,提问作者Sanket

火山引擎 最新活动