我的表格视图都设置为使用联系人框架获取联系人。目前,我有以下表格视图:
我正在通过CNContactStore获取我的联系人。我能够从联系人中检索出我想要的所有数据。
我创建了以下包含 ExpandableNames 数组的结构,其中每个 ExpandableNames 包含一个isExpanded boolean和一个 FavoritableContact 数组。
struct ExpandableNames{
var isExpanded: Bool
var contacts: [FavoritableContact]
}
struct FavoritableContact {
let contact: CNContact
var hasFavorited: Bool
}
有了这个,我声明并初始化了以下数组:
var favoritableContacts = [FavoritableContact]()
以及:
var twoDimensionalArray = [ExpandableNames]()
初始化数组后,我创建了一个可以获取联系人的函数。
private func fetchContacts(){
let store = CNContactStore()
store.requestAccess(for: (.contacts)) { (granted, err) in
if let err = err{
print("Failed to request access",err)
return
}
if granted {
print("Access granted")
let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
let fetchRequest = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
var favoritableContacts = [FavoritableContact]()
fetchRequest.sortOrder = CNContactSortOrder.userDefault
do {
try store.enumerateContacts(with: fetchRequest, usingBlock: { ( contact, error) -> Void in
favoritableContacts.append(FavoritableContact(contact: contact, hasFavorited: false))
})
let names = ExpandableNames(isExpanded: true, contacts: favoritableContacts)
self.twoDimensionalArray = [names]
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch let error as NSError {
print(error.localizedDescription)
}
}else{
print("Access denied")
}
}
}
考虑到这一点,我有办法在群组中获取这些联系人。当我说组时,我的意思是从ContactsUI按字母顺序获取联系人,如下所示:
我尝试了其他方法,但我一直在同一个墙上,我需要考虑到标准英语字母表可能不是用户首选的设备语言,变音符号,符号,数字等等这一事实。因此,如果我可以按照来自contactsUI的方式检索它,那就太棒了。
谢谢你们!
注意:如果您想了解更多详情,请与我们联系!
答案 0 :(得分:4)
解决方案SWIFT 4
我能够在rmaddy的帮助下使用UILocalizedIndexedCollation类找到解决方案。
以下代码代表我的ConctactsVC:
import UIKit
import Contacts
class ContactsVC: UITableViewController {
let cellID = "cellID"
var contacts = [Contact]()
var contactsWithSections = [[Contact]]()
let collation = UILocalizedIndexedCollation.current() // create a locale collation object, by which we can get section index titles of current locale. (locale = local contry/language)
var sectionTitles = [String]()
private func fetchContacts(){
let store = CNContactStore()
store.requestAccess(for: (.contacts)) { (granted, err) in
if let err = err{
print("Failed to request access",err)
return
}
if granted {
print("Access granted")
let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
let fetchRequest = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
fetchRequest.sortOrder = CNContactSortOrder.userDefault
do {
try store.enumerateContacts(with: fetchRequest, usingBlock: { ( contact, error) -> Void in
guard let phoneNumber = contact.phoneNumbers.first?.value.stringValue else {return}
self.contacts.append(Contact(givenName: contact.givenName, familyName: contact.familyName, mobile: phoneNumber))
})
for index in self.contacts.indices{
print(self.contacts[index].givenName)
print(self.contacts[index].familyName)
print(self.contacts[index].mobile)
}
self.setUpCollation()
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch let error as NSError {
print(error.localizedDescription)
}
}else{
print("Access denied")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(dimissContactsVC))
navigationItem.title = "Contacts"
navigationController?.navigationBar.prefersLargeTitles = true
//Changing section index color
self.tableView.sectionIndexColor = UIColor.red
// need to register a custom cell
tableView.register(ContactsCell.self, forCellReuseIdentifier: cellID)
fetchContacts()
//Test
// let contact1 = Contact(name: "Anuska", mobile: "123434")
//
// let contact2 = Contact(name: "Anuj Sinha", mobile: "2321234")
//
// let contact3 = Contact(name: "Maria", mobile: "343434")
//
// let contact4 = Contact(name: "Jacob", mobile: "34454545")
//
// let contact5 = Contact(name: "Macculam", mobile: "455656")
//
// let contact6 = Contact(name: "Sophia", mobile: "4567890")
//
// self.contacts = [contact1, contact2, contact3, contact4, contact5, contact6]
}
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
@objc func setUpCollation(){
let (arrayContacts, arrayTitles) = collation.partitionObjects(array: self.contacts, collationStringSelector: #selector(getter: Contact.givenName))
self.contactsWithSections = arrayContacts as! [[Contact]]
self.sectionTitles = arrayTitles
print(contactsWithSections.count)
print(sectionTitles.count)
}
@objc func dimissContactsVC(){
dismiss(animated: true, completion: nil)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return sectionTitles.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contactsWithSections[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! ContactsCell
let cell = ContactsCell(style: .subtitle, reuseIdentifier: cellID)
cell.link = self // custom delegation
let contact = contactsWithSections[indexPath.section][indexPath.row]
cell.selectionStyle = .default
cell.textLabel?.text = contact.givenName + " " + contact.familyName
cell.detailTextLabel?.text = contact.mobile
return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionTitles[section]
}
//Changing color for the Letters in the section titles
override func tableView(_ tableView: UITableView, willDisplayHeaderView view:UIView, forSection: Int) {
if let headerTitle = view as? UITableViewHeaderFooterView {
headerTitle.textLabel?.textColor = UIColor.red
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 44
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return sectionTitles
}
}
extension UILocalizedIndexedCollation {
//func for partition array in sections
func partitionObjects(array:[AnyObject], collationStringSelector:Selector) -> ([AnyObject], [String]) {
var unsortedSections = [[AnyObject]]()
//1. Create a array to hold the data for each section
for _ in self.sectionTitles {
unsortedSections.append([]) //appending an empty array
}
//2. Put each objects into a section
for item in array {
let index:Int = self.section(for: item, collationStringSelector:collationStringSelector)
unsortedSections[index].append(item)
}
//3. sorting the array of each sections
var sectionTitles = [String]()
var sections = [AnyObject]()
for index in 0 ..< unsortedSections.count { if unsortedSections[index].count > 0 {
sectionTitles.append(self.sectionTitles[index])
sections.append(self.sortedArray(from: unsortedSections[index], collationStringSelector: collationStringSelector) as AnyObject)
}
}
return (sections, sectionTitles)
}
}
我还有一个名为Contact的模型文件:
@objc class Contact : NSObject {
@objc var givenName: String!
@objc var familyName: String!
@objc var mobile: String!
init(givenName: String, familyName: String, mobile: String) {
self.givenName = givenName
self.familyName = familyName
self.mobile = mobile
}
}
<强> PICTURE:强>
答案 1 :(得分:0)
我设法解决了这个问题。
//keys with fetching properties
NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactEmailAddressesKey];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
//Order contacts by Surname.
request.sortOrder = CNContactSortOrderFamilyName;
--OR YOU CAN--
//Order contacts by Name.
request.sortOrder = CNContactSortOrderGivenName;