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

如何在SwiftUI的ListView中正确显示通讯录电话号码?

如何在SwiftUI的ListView中正确显示通讯录联系人的电话号码?

现有代码已成功从通讯录获取并显示联系人的名字(givenName)与姓氏(familyName),但无法正确显示电话号码。以下是问题分析和修复方案:

当前代码

struct ContentView: View {
    @State var contacts:[CNContact] = []
    
    var body: some View {
        VStack {
            Text("Conctacts")
                .font(.title)
            List {
                ForEach(contacts, id:\.self) { contact in
                    VStack{
                        HStack{
                            Text("\(contact.givenName)")
                            Text("\(contact.familyName)")
                                .fontWeight(.bold)
                            Spacer()
                            Button {
                                print("Edit button was tapped")
                            } label: {
                                Image(systemName:"person.crop.circle.fill.badge.plus")
                                    .font(.title3)
                                    .foregroundColor(.yellow)
                            }
                            .buttonStyle(.plain)
                        }
                        Text("\(contact.phoneNumbers[0])")
                    }
                }
            }
            .onAppear{
                Task.init{
                    await fetchAllContacts()
                }
            }
        }
        .padding()
    }
    
    func fetchAllContacts() async{
        let store = CNContactStore()
        let keys = [CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactFamilyNameKey] as [CNKeyDescriptor]
        let fetchRequest = CNContactFetchRequest(keysToFetch: keys)
        
        do{
            try store.enumerateContacts(with: fetchRequest, usingBlock: { contact, result in
                
                contacts.append(contact)
            })
        }
        catch{
           print ("Error")
        }
    }
}

问题原因

CNContact.phoneNumbers是[CNLabeledValue<CNPhoneNumber>]类型数组,直接访问contact.phoneNumbers[0]并转成字符串,会输出CNLabeledValue的结构体信息而非实际电话号码。此外,直接取索引0还会有数组越界风险(如果联系人没有电话号码)。

修复方案

1. 提取电话号码字符串

每个CNLabeledValue的value属性是CNPhoneNumber类型,通过value.stringValue可以获取格式化后的电话号码。

2. 处理无号码的情况

先判断phoneNumbers数组是否为空,避免崩溃。

3. 可选:显示号码标签(如移动电话、家庭电话)

可以通过CNLabeledValue.label获取号码类型标签,用CNLabeledValue.localizedString(forLabel:)转成本地化显示文本。

修改后的代码

将原来的电话号码显示部分替换为以下内容,即可实现正常显示:

var body: some View {
    VStack {
        Text("Contacts")
            .font(.title)
        List {
            ForEach(contacts, id:\.self) { contact in
                VStack(alignment: .leading, spacing: 4) {
                    HStack{
                        Text("\(contact.givenName)")
                        Text("\(contact.familyName)")
                            .fontWeight(.bold)
                        Spacer()
                        Button {
                            print("Edit button was tapped")
                        } label: {
                            Image(systemName:"person.crop.circle.fill.badge.plus")
                                .font(.title3)
                                .foregroundColor(.yellow)
                        }
                        .buttonStyle(.plain)
                    }
                    
                    // 显示所有关联的电话号码及标签
                    ForEach(contact.phoneNumbers, id: \.self) { phone in
                        let phoneNumber = phone.value.stringValue
                        let label = CNLabeledValue.localizedString(forLabel: phone.label ?? "")
                        Text("\(label): \(phoneNumber)")
                            .font(.subheadline)
                            .foregroundColor(.gray)
                    }
                    
                    // 无电话号码时显示提示
                    if contact.phoneNumbers.isEmpty {
                        Text("无电话号码")
                            .font(.subheadline)
                            .foregroundColor(.gray)
                    }
                }
            }
        }
        .onAppear{
            Task{
                await fetchAllContacts()
            }
        }
    }
    .padding()
}

额外优化点

  • 修正了标题拼写错误:"Conctacts"改为"Contacts"
  • 调整VStack的对齐方式和间距,让布局更紧凑美观

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:42:48