You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:11:10