按字母组

时间:2018-01-06 22:05:57

标签: ios arrays swift

我的表格视图都设置为使用联系人框架获取联系人。目前,我有以下表格视图:

enter image description here

我正在通过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按字母顺序获取联系人,如下所示:

enter image description here

我尝试了其他方法,但我一直在同一个墙上,我需要考虑到标准英语字母表可能不是用户首选的设备语言,变音符号,符号,数字等等这一事实。因此,如果我可以按照来自contactsUI的方式检索它,那就太棒了。

谢谢你们!

注意:如果您想了解更多详情,请与我们联系!

2 个答案:

答案 0 :(得分:4)

解决方案SWIFT 4

我能够在rmaddy的帮助下使用UILocalizedIndexedCollat​​ion类找到解决方案。

以下代码代表我的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:

enter image description here

答案 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;