【发布时间】:2020-07-14 15:49:31
【问题描述】:
我正在创建一个应用程序的入门部分,它可以让用户的联系人检查哪些已经有应用程序添加为朋友。我正在使用 CNContact 框架。我创建了几种方法来获取用户联系人的完整列表,检查他们是否有应用程序,并在 UITableView 中枚举它们。但是,当视图加载时,应用程序崩溃并显示错误“获取联系人时未请求属性”。我已经使用 CNContactGivenNameKey、CNContactFamilyNameKey、CNContactPhoneNumbersKey 和 CNContactImageDataKey 键发出了获取请求。我在这里包含了我的所有代码:
import Foundation
import Contacts
import PhoneNumberKit
struct ContactService {
static func createContactArray() -> [CNContact] {
var tempContacts = [CNContact]()
let store = CNContactStore()
store.requestAccess(for: .contacts) { (granted, error) in
if let _ = error {
print("failed to request access to contacts")
return
}
if granted {
let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey]
let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
request.sortOrder = CNContactSortOrder.familyName
do {
try store.enumerateContacts(with: request, usingBlock: { (contact, stop) in
tempContacts.append(contact)
})
} catch {
print("unable to fetch contacts")
}
print("created contact list")
}
}
return tempContacts
}
static func createFetchedContactArray(contactArray: [CNContact], completion: @escaping ([FetchedContact]?) -> Void) -> Void {
var temp = [FetchedContact]()
getNumsInFirestore { (nums) in
if let nums = nums {
for c in contactArray {
let f = FetchedContact(cnContact: c, numsInFirebase: nums)
temp.append(f)
}
return completion(temp)
} else {
print("Error retrieving numbers")
}
}
return completion(nil)
}
static func getNumsInFirestore(_ completion: @escaping (_ nums : [String]?) -> Void ) -> Void {
var numsInFirebase = [String]()
let db = FirestoreService.db
db.collection(Constants.Firestore.Collections.users).getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting user documents: \(err)")
completion(nil)
} else {
for doc in querySnapshot!.documents {
let dict = doc.data()
numsInFirebase.append(dict[Constants.Firestore.Keys.phone] as! String)
}
completion(numsInFirebase)
}
}
}
static func getPhoneStrings(contact: CNContact) -> [String] {
var temp = [String]()
let cnPhoneNums = contact.phoneNumbers
for n in cnPhoneNums {
temp.append(n.value.stringValue)
}
return temp
}
static func hasBump(contact: CNContact, completion: @escaping (_ h: Bool) -> Void ) -> Void {
let contactNums = ContactService.getPhoneStrings(contact: contact)
ContactService.getNumsInFirestore { (nums) in
if let nums = nums {
return completion(contactNums.contains(where: nums.contains))
} else {
print("Error retrieving numbers from firestore")
return completion(false)
}
}
}
static func anyContactsWithBump(completion: @escaping (_ yes: Bool) -> Void) {
let contacts = createContactArray()
var tempBool = false
let workgroup = DispatchGroup()
for c in contacts {
workgroup.enter()
hasBump(contact: c) { (has) in
if has {
tempBool = true
}
workgroup.leave()
}
}
workgroup.notify(queue: .main) {
completion(tempBool)
}
}
}
然后我调用视图控制器类中的方法:
import UIKit
import Contacts
import FirebaseDatabase
import Firebase
import FirebaseFirestore
class AddContactsVC: UIViewController {
var fetchedContactsWithBump: [FetchedContact] = []
override func viewDidLoad() {
let cnContacts = ContactService.createContactArray()
var contactsWithBump = [CNContact]()
let workgroup = DispatchGroup()
for contact in cnContacts {
workgroup.enter()
ContactService.hasBump(contact: contact) { (has) in
if has {
contactsWithBump.append(contact)
}
workgroup.leave()
}
}
workgroup.notify(queue: .main) {
print("Number of contacts with Bump: \(contactsWithBump.count)")
ContactService.createFetchedContactArray(contactArray: contactsWithBump) { (fetchedContacts) in
if let fetchedContacts = fetchedContacts {
self.fetchedContactsWithBump = fetchedContacts
} else {
print("Error creating fetchedContacts array.")
}
}
}
我还在控制台中收到消息“创建 fetchedContacts 数组时出错”,所以我知道该方法出了点问题,我只是不确定是什么。任何帮助表示赞赏!
编辑:异常在 3 点处引发:1 在我的 FetchedContact 初始化方法的第一行,如下所示:
init(cnContact: CNContact, numsInFirebase: [String]) {
if cnContact.imageDataAvailable { self.image = UIImage(data: cnContact.imageData!) }
它还指向 createFetched 联系人数组中的 let f = FetchedContact(cnContact: c, numsInFirebase: nums) 行,最后在 getNumsInFirestore 中的完成(numsInFirebase)调用。
【问题讨论】:
-
你在哪一行得到错误?
-
它没有给我一行,只是在 AppDelegate 类的顶部这么说。
-
尝试在您的项目中添加“异常断点”。
-
好的,它在 3 点显示异常:1 在我的 FetchedContact init 方法的第一行,如下所示:``` init(cnContact: CNContact, numsInFirebase: [String]) { if cnContact.imageDataAvailable { self.image = UIImage(data: cnContact.imageData!) } ``` 它还指向 createFetched 联系人数组中的
let f = FetchedContact(cnContact: c, numsInFirebase: nums)行,最后在 getNumsInFirestore 中的完成(numsInFirebase)调用。 -
请在您的问题中添加其他信息 - 在 cmets 中很难阅读。
标签: swift asynchronous contacts