Ios Swiftには Contacts Framework があり、連絡先を取得できますが、それぞれにアクセスできるすべての連絡先を一緒に取得する方法が見つかりません連絡先を取得するためのすべてのメソッドには、何らかの条件が必要なようですが、すべての連絡先をまとめることができる方法はありますか?
ありがとう
Contact Frameworkの質問に対する多くの回答は、さまざまなコンテナ(アカウント)を反復処理することを示唆しています。ただし、Appleのドキュメントでは、「Unified Contact」について次のように説明しています。
同じ人物を表す異なるアカウントの連絡先は、自動的にリンクされる場合があります。リンクされた連絡先は、OS XおよびiOSアプリで統合連絡先として表示されます。統合連絡先は、1つの連絡先にマージされるリンクされた連絡先のセットのメモリ内の一時的なビューです。
デフォルトでは、Contactsフレームワークは統合された連絡先を返します。フェッチされた各統合連絡先(CNContact)オブジェクトには、リンクされた連絡先セット内の個々の連絡先の識別子とは異なる独自の一意の識別子があります。統合された連絡先の再取得は、その識別子を使用して行う必要があります。 ソース
単一の配列で(キーに基づいて部分的に)連絡先のリストを取得する最も簡単な方法は、次のとおりです。
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")
}
Swift 4および5。クラスPhoneContactsを作成しました。 NSContactsUsageDescriptionキーをinfo.plistファイルに追加してください
import Foundation
import ContactsUI
class PhoneContacts {
class func getContacts(filter: ContactsFilter = .none) -> [CNContact] { // ContactsFilter is Enum find it below
let contactStore = CNContactStore()
let keysToFetch = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactPhoneNumbersKey,
CNContactEmailAddressesKey,
CNContactThumbnailImageDataKey] as [Any]
var allContainers: [CNContainer] = []
do {
allContainers = try contactStore.containers(matching: nil)
} catch {
print("Error fetching containers")
}
var results: [CNContact] = []
for container in allContainers {
let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
do {
let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
results.append(contentsOf: containerResults)
} catch {
print("Error fetching containers")
}
}
return results
}
}
別のクラスで上記のメソッドを呼び出す
import ContactsUI
func phoneNumberWithContryCode() -> [String] {
let contacts = PhoneContacts.getContacts() // here calling the getContacts methods
var arrPhoneNumbers = [String]()
for contact in contacts {
for ContctNumVar: CNLabeledValue in contact.phoneNumbers {
if let fulMobNumVar = ContctNumVar.value as? CNPhoneNumber {
//let countryCode = fulMobNumVar.value(forKey: "countryCode") get country code
if let MccNamVar = fulMobNumVar.value(forKey: "digits") as? String {
arrPhoneNumbers.append(MccNamVar)
}
}
}
}
return arrPhoneNumbers // here array has all contact numbers.
}
今、連絡先の電子メールと電話を取得
enum ContactsFilter {
case none
case mail
case message
}
var phoneContacts = [PhoneContact]() // array of PhoneContact(It is model find it below)
var filter: ContactsFilter = .none
self.loadContacts(filter: filter) // Calling loadContacts methods
fileprivate func loadContacts(filter: ContactsFilter) {
phoneContacts.removeAll()
var allContacts = [PhoneContact]()
for contact in PhoneContacts.getContacts(filter: filter) {
allContacts.append(PhoneContact(contact: contact))
}
var filterdArray = [PhoneContact]()
if self.filter == .mail {
filterdArray = allContacts.filter({ $0.email.count > 0 }) // getting all email
} else if self.filter == .message {
filterdArray = allContacts.filter({ $0.phoneNumber.count > 0 })
} else {
filterdArray = allContacts
}
phoneContacts.append(contentsOf: filterdArray)
for contact in phoneContacts {
print("Name -> \(contact.name)")
print("Email -> \(contact.email)")
print("Phone Number -> \(contact.phoneNumber)")
}
let arrayCode = self.phoneNumberWithContryCode()
for codes in arrayCode {
print(codes)
}
DispatchQueue.main.async {
self.tableView.reloadData() // update your tableView having phoneContacts array
}
}
}
PhoneContactモデルクラス
import Foundation
import ContactsUI
class PhoneContact: NSObject {
var name: String?
var avatarData: Data?
var phoneNumber: [String] = [String]()
var email: [String] = [String]()
var isSelected: Bool = false
var isInvited = false
init(contact: CNContact) {
name = contact.givenName + " " + contact.familyName
avatarData = contact.thumbnailImageData
for phone in contact.phoneNumbers {
phoneNumber.append(phone.value.stringValue)
}
for mail in contact.emailAddresses {
email.append(mail.value as String)
}
}
override init() {
super.init()
}
}
Swift 4の更新
let contactStore = CNContactStore()
var contacts = [CNContact]()
let keys = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactPhoneNumbersKey,
CNContactEmailAddressesKey
] as [Any]
let request = CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])
do {
try contactStore.enumerateContacts(with: request){
(contact, stop) in
// Array containing all unified contacts from everywhere
contacts.append(contact)
for phoneNumber in contact.phoneNumbers {
if let number = phoneNumber.value as? CNPhoneNumber, let label = phoneNumber.label {
let localizedLabel = CNLabeledValue<CNPhoneNumber>.localizedString(forLabel: label)
print("\(contact.givenName) \(contact.familyName) tel:\(localizedLabel) -- \(number.stringValue), email: \(contact.emailAddresses)")
}
}
}
print(contacts)
} catch {
print("unable to fetch contacts")
}
// You may add more "keys" to fetch referred to official documentation
let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)]
// The container means
// that the source the contacts from, such as Exchange and iCloud
var allContainers: [CNContainer] = []
do {
allContainers = try store.containersMatchingPredicate(nil)
} catch {
print("Error fetching containers")
}
var contacts: [CNContact] = []
// Loop the containers
for container in allContainers {
let fetchPredicate = CNContact.predicateForContactsInContainerWithIdentifier(container.identifier)
do {
let containerResults = try store.unifiedContactsMatchingPredicate(fetchPredicate, keysToFetch: keysToFetch)
// Put them into "contacts"
contacts.appendContentsOf(containerResults)
} catch {
print("Error fetching results for container")
}
}
すべての連絡先を取り込むためのSwift 4.0の実装。
let contactStore = CNContactStore()
var contacts = [CNContact]()
let keys = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]
let request = CNContactFetchRequest(keysToFetch: keys)
do {
try contactStore.enumerateContacts(with: request) { (contact, stop) in
contacts.append(contact)
}
} catch {
print(error.localizedDescription)
}
これにより、連絡先を保存するローカルプロパティが作成され、contactStore
に対する列挙を介して入力されます。
上記の回答に基づいて特定の改善を加えた私の回答をご覧ください。
ポッドファイル内
source 'https://github.com/CocoaPods/Specs.git'
pod 'PhoneNumberKit', '~> 2.6'
ポッドインストールを実行
その後、ViewControllerファイルで
import Contacts
import PhoneNumberKit
import UIKit
override func viewDidLoad() {
super.viewDidLoad()
let contactStore = CNContactStore()
var contacts = [CNContact]()
let keys = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactPhoneNumbersKey,
CNContactEmailAddressesKey,
] as [Any]
let request = CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])
do {
try contactStore.enumerateContacts(with: request) {
contact, _ in
// Array containing all unified contacts from everywhere
contacts.append(contact)
for phoneNumber in contact.phoneNumbers {
if let number = phoneNumber.value as? CNPhoneNumber, let label = phoneNumber.label {
let localizedLabel = CNLabeledValue<CNPhoneNumber>.localizedString(forLabel: label)
// Get The Name
let name = contact.givenName + " " + contact.familyName
print(name)
// Get The Mobile Number
var mobile = number.stringValue
mobile = mobile.replacingOccurrences(of: " ", with: "")
// Parse The Mobile Number
let phoneNumberKit = PhoneNumberKit()
do {
let phoneNumberCustomDefaultRegion = try phoneNumberKit.parse(mobile, withRegion: "IN", ignoreType: true)
let countryCode = String(phoneNumberCustomDefaultRegion.countryCode)
let mobile = String(phoneNumberCustomDefaultRegion.nationalNumber)
let finalMobile = "+" + countryCode + mobile
print(finalMobile)
} catch {
print("Generic parser error")
}
// Get The Email
var email: String
for mail in contact.emailAddresses {
email = mail.value as String
print(email)
}
}
}
}
} catch {
print("unable to fetch contacts")
}
}
以下の機能を試してください、それはあなたを助けます(Swift 4)
import UIKit
import Contacts
import ContactsUI
override func viewDidLoad() {
super.viewDidLoad()
// `contacts` Contains all details of Phone Contacts
let contacts = self.getContactFromCNContact()
for contact in contacts {
print(contact.middleName)
print(contact.familyName)
print(contact.givenName)
}
}
func getContactFromCNContact() -> [CNContact] {
let contactStore = CNContactStore()
let keysToFetch = [
CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactGivenNameKey,
CNContactMiddleNameKey,
CNContactFamilyNameKey,
CNContactEmailAddressesKey,
] as [Any]
//Get all the containers
var allContainers: [CNContainer] = []
do {
allContainers = try contactStore.containers(matching: nil)
} catch {
print("Error fetching containers")
}
var results: [CNContact] = []
// Iterate all containers and append their contacts to our results array
for container in allContainers {
let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)
do {
let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
results.append(contentsOf: containerResults)
} catch {
print("Error fetching results for container")
}
}
return results
}