Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 允许SwiftUI导入所有联系人并删除特定联系人_Ios_Swift_Swiftui - Fatal编程技术网

Ios 允许SwiftUI导入所有联系人并删除特定联系人

Ios 允许SwiftUI导入所有联系人并删除特定联系人,ios,swift,swiftui,Ios,Swift,Swiftui,请原谅我缺乏知识,我正在尝试制作我的第一个iOS应用程序,我的目标是将我的所有联系人导入swiftui视图: //ContentView.swift import SwiftUI struct ContentView: View { var contact = contactData @ObservedObject var contacts = ContactList() var body: some View { NavigationView {

请原谅我缺乏知识,我正在尝试制作我的第一个iOS应用程序,我的目标是将我的所有联系人导入swiftui视图:

//ContentView.swift
import SwiftUI

struct ContentView: View {
    var contact = contactData
    @ObservedObject var contacts = ContactList()

    var body: some View {
        NavigationView {
            List {
                ForEach(contact) { item in
                    VStack(alignment: .leading) {
                        HStack {
                            Text(item.contactName)
                        }
                    }
                }
                .onDelete { index in
                    self.contacts.contact.remove(at: index.first!)
                }
            }
            .navigationBarTitle(Text("Contacts"))
            .navigationBarItems(
                trailing: EditButton()
            )
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

struct Contacts: Identifiable {
    var id = UUID()
    var contactName: String
}

let contactData = [
    Contacts(contactName: "Foo Bar"),
    Contacts(contactName: "Johnny Appleseed")
]

使用Combine API和.onDelete函数,我想删除多个当前在iOS中不具备功能的联系人,然后将其返回到contacts应用程序中

虽然我一直在拉联系人名单,但我已经尝试了多种不同的方法,比如:

但这似乎在没有抛出一系列错误的情况下无法正常工作。我现在不太担心删除,但更主要的是只导入联系人

有人知道使用SwiftUI和Contacts API是否有一种很好的方法可以做到这一点吗?或者至少能给我指出正确的方向?我知道我使用的是Xcode 11 Beta 5,这可能会导致不同API的弃用出现问题,但在Xcode 11中,联系人API似乎相对没有变化。

您通常使用ObserveObject进行模型/控制器交互。发布它们只允许我将结果分配给变量

它当前在onAppear async内部启动fetch,因为否则它将阻止UI加载,请求联系人将无法工作

缺少的是更好的授权处理—请参阅、刷新、在其他地方调用fetch和更全面的功能

条件允许我显示联系人或错误,这有助于快速发现错误

注意:您必须将隐私联系人描述添加到info.plist中,以使其不会崩溃。否则,它应该在不改变任何其他内容的情况下工作

注2:由于SwiftUI仅接线和UI更改为@dfd所述。如何检索联系人仍然完全一样

import Contacts
import SwiftUI
import os

class ContactStore: ObservableObject {
    @Published var contacts: [CNContact] = []
    @Published var error: Error? = nil

    func fetch() {
        os_log("Fetching contacts")
        do {
            let store = CNContactStore()
            let keysToFetch = [CNContactGivenNameKey as CNKeyDescriptor,
                               CNContactMiddleNameKey as CNKeyDescriptor,
                               CNContactFamilyNameKey as CNKeyDescriptor,
                               CNContactImageDataAvailableKey as CNKeyDescriptor,
                               CNContactImageDataKey as CNKeyDescriptor]
            os_log("Fetching contacts: now")
            let containerId = store.defaultContainerIdentifier()
            let predicate = CNContact.predicateForContactsInContainer(withIdentifier: containerId)
            let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keysToFetch)
            os_log("Fetching contacts: succesfull with count = %d", contacts.count)
            self.contacts = contacts
        } catch {
            os_log("Fetching contacts: failed with %@", error.localizedDescription)
            self.error = error
        }
    }
}

extension CNContact: Identifiable {
    var name: String {
        return [givenName, middleName, familyName].filter{ $0.count > 0}.joined(separator: " ")
    }
}

struct ContactsView: View {
    @EnvironmentObject var store: ContactStore

    var body: some View {
        VStack{
            Text("Contacts")
            if store.error == nil {
                List(store.contacts) { (contact: CNContact) in
                    return Text(contact.name)
                }.onAppear{
                    DispatchQueue.main.async {
                        self.store.fetch()
                    }
                }
            } else {
                Text("error: \(store.error!.localizedDescription)")
            }
        }
    }
}

struct ContactsViewOrError: View {
    var body: some View {
        ContactsView().environmentObject(ContactStore())
    }
}

一个礼貌的建议?SwiftUI需要iOS 13,而UIKit不需要。考虑到这一点,以及几乎所有与联系人打交道的目标实际上都属于您的模型——这不应该是您的UI的任何部分,不要。不要使用SwiftUI。首先让您的联系逻辑工作——UIKit有更多的文档,因为它已经存在十多年了。首先关注逻辑,然后才关注UI。这就是SwiftUI的真正含义——它只是一种传递逻辑的方法。谢谢!这非常有效,并且向我表明我需要学习更多的逻辑,就像@dfd所说的那样。你知道为什么我的列表中可能有空白联系人吗?它确实成功地返回了所有键。@BrettHolmes提取只提取给定的键,其中只有名称被放入文本视图。它只是意味着该条目没有在给定名称、中间名或姓氏中设置任何内容。通过获取更多字段并打印它们,您可能会了解它的用途。我也有这样一个条目:D。如果存在这样的条目,请查看联系人应用程序。
var contacts = [CNContact]()
let keys = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)]
let request = CNContactFetchRequest(keysToFetch: keys)

do {
    try self.contactStore.enumerateContactsWithFetchRequest(request) {             
        (contact, stop) in
        // Array containing all unified contacts from everywhere
        contacts.append(contact)
    }
} 
catch {
    print("unable to fetch contacts")
}
import Contacts
import SwiftUI
import os

class ContactStore: ObservableObject {
    @Published var contacts: [CNContact] = []
    @Published var error: Error? = nil

    func fetch() {
        os_log("Fetching contacts")
        do {
            let store = CNContactStore()
            let keysToFetch = [CNContactGivenNameKey as CNKeyDescriptor,
                               CNContactMiddleNameKey as CNKeyDescriptor,
                               CNContactFamilyNameKey as CNKeyDescriptor,
                               CNContactImageDataAvailableKey as CNKeyDescriptor,
                               CNContactImageDataKey as CNKeyDescriptor]
            os_log("Fetching contacts: now")
            let containerId = store.defaultContainerIdentifier()
            let predicate = CNContact.predicateForContactsInContainer(withIdentifier: containerId)
            let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keysToFetch)
            os_log("Fetching contacts: succesfull with count = %d", contacts.count)
            self.contacts = contacts
        } catch {
            os_log("Fetching contacts: failed with %@", error.localizedDescription)
            self.error = error
        }
    }
}

extension CNContact: Identifiable {
    var name: String {
        return [givenName, middleName, familyName].filter{ $0.count > 0}.joined(separator: " ")
    }
}

struct ContactsView: View {
    @EnvironmentObject var store: ContactStore

    var body: some View {
        VStack{
            Text("Contacts")
            if store.error == nil {
                List(store.contacts) { (contact: CNContact) in
                    return Text(contact.name)
                }.onAppear{
                    DispatchQueue.main.async {
                        self.store.fetch()
                    }
                }
            } else {
                Text("error: \(store.error!.localizedDescription)")
            }
        }
    }
}

struct ContactsViewOrError: View {
    var body: some View {
        ContactsView().environmentObject(ContactStore())
    }
}