Я создаю входящую в систему часть приложения, которая заставляет контакты пользователя проверять, у кого уже есть приложение для добавления в друзья. Я использую фреймворк CNContact. Я создал несколько методов, которые использую, чтобы получить полный список контактов пользователей, проверить, есть ли у них приложение, и перечислить их в UITableView. Однако при загрузке представления приложение аварийно завершает работу с ошибкой «Не запрашивалось свойство при получении контакта». Я уже делаю запрос на выборку с ключами CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, ad 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!) }
Это также указывает на строка let f = FetchedContact (cnContact: c, numsInFirebase: nums) в массиве контактов createFetched и, наконец, при моем завершении вызова (numsInFirebase) в getNumsInFirestore.