CKUserIdentity的nameComponents为空,如何获取iCloud用户名称?
问题
我的App要求用户开启并允许iCloud访问权限,原本打算通过CloudKit获取用户名,但通过以下代码从CKUserIdentity中得到的nameComponents为空:
var userParticipantIdentity: CKUserIdentity? = nil do { let userRecordID = try await container.userRecordID() let userParticipant = try await container.shareParticipant(forUserRecordID: userRecordID) userParticipantIdentity = userParticipant.userIdentity } catch { ... throw ... }
最终userParticipantIdentity.nameComponents返回的PersonNameComponents不含任何名称值。
进一步测试:创建一个使用CoreData+CloudKit的新Xcode项目,在ContentView中添加以下代码:
.task { let container = controller.cloudKitContainer do { try controller.container.initializeCloudKitSchema() } catch {} do { let userStatus = try await container.accountStatus() guard case .available = userStatus else { print("UserName: Error: No iCloud"); return } let userRecordID = try await container.userRecordID() let userParticipant = try await container.shareParticipant(forUserRecordID: userRecordID) let userParticipantIdentity = userParticipant.userIdentity guard let userParticipantNameComponents = userParticipantIdentity.nameComponents else { print("UserName: Error: No `nameComponents"); return } let userParticipantName = PersonNameComponentsFormatter().string(from: userParticipantNameComponents) print("UserName: Got: `\(userParticipantName)`") } catch { print("UserName: Error: \(error.localizedDescription)") } }
运行后输出为`UserName: Got: ```。
请问在依赖iCloud访问权限且多个iOS发现接口已废弃的情况下,该如何获取用户名称?
解决方案
1. 显式获取完整的用户身份信息
直接通过shareParticipant获取的CKUserIdentity可能未填充nameComponents字段,需要使用CKFetchUserIdentitiesOperation主动请求完整的用户身份数据:
let container = CKContainer.default() do { let userRecordID = try await container.userRecordID() let operation = CKFetchUserIdentitiesOperation(userRecordIDs: [userRecordID]) operation.fetchUserIdentitiesCompletionBlock = { identitiesByRecordID, error in if let error = error { print("获取用户身份失败:\(error.localizedDescription)") return } guard let userIdentity = identitiesByRecordID?[userRecordID] else { print("未找到用户身份") return } if let nameComponents = userIdentity.nameComponents { let userName = PersonNameComponentsFormatter().string(from: nameComponents) print("获取到用户名:\(userName)") } else { print("用户身份中无名称数据") } } container.add(operation) } catch { print("获取用户Record ID失败:\(error.localizedDescription)") }
2. 检查用户iCloud账户的名称设置
nameComponents为空可能是因为用户的Apple ID未设置全名。可以提示用户前往设置 > [自己的名字] > 姓名、电话号码、电子邮件中完善姓名信息,之后CloudKit才能返回有效的名称数据。
3. 读取CloudKit用户记录中的自定义字段
如果你的CloudKit容器配置了用户记录类型(默认是User类型),可以在该记录中添加自定义的名称字段(比如fullName),用户首次使用App时引导其填写,之后直接通过获取用户的CKRecord来读取名称:
let container = CKContainer.default() do { let userRecordID = try await container.userRecordID() let userRecord = try await container.publicCloudDatabase.record(withID: userRecordID) if let fullName = userRecord["fullName"] as? String { print("获取到用户名:\(fullName)") } else { // 引导用户填写姓名并保存到CloudKit userRecord["fullName"] = "用户填写的姓名" try await container.publicCloudDatabase.save(userRecord) } } catch { print("操作失败:\(error.localizedDescription)") }
内容的提问来源于stack exchange,提问作者GoZoner
相关产品推荐
相关产品推荐

