ContactsViewController.swift 7.39 KB
Newer Older
Javier Heisekce committed
1 2 3 4 5 6 7 8 9 10 11 12 13
//
//  ContactsViewController.swift
//  ContactsApp
//
//  Created by User on 3/13/20.
//  Copyright © 2020 jheisecke. All rights reserved.
//

import UIKit
import ContactsUI

class ContactsViewController: UIViewController {
    
14
    @IBOutlet weak var searchBar: UISearchBar!
Javier Heisekce committed
15
    @IBOutlet weak var contactsTable: UITableView!
16
    var contactStructArray = [ContactStruct]()
17
    var contactAux = [ContactStruct]()
18
    var contactStruct : ContactStruct?
Javier Heisekce committed
19 20 21 22
    let contactStore = CNContactStore()
    
    override func viewDidLoad() {
        super.viewDidLoad()
23
        contactsTable.register(UINib(nibName: "ContactSection", bundle: nil), forHeaderFooterViewReuseIdentifier: "headerId")
Javier Heisekce committed
24
        importContacts()
25
        searchBar.delegate = self
Javier Heisekce committed
26
        contactsTable.tableFooterView = UIView(frame: .zero)
27
        searchBar.placeholder = NSLocalizedString("Nombre...", comment: "")
Javier Heisekce committed
28 29 30
    }
    
    func importContacts() {
31
        self.contactStructArray = []
32
        let keys = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactImageDataKey] as [Any]
33
        let request = CNContactFetchRequest( keysToFetch: keys as! [CNKeyDescriptor])
Javier Heisekce committed
34 35
        request.sortOrder = CNContactSortOrder.givenName
        do {
36 37 38
            var auxLetter = ""
            var contacts = [CNContact]()
            var isNotTheFirst = false
Javier Heisekce committed
39 40
            try self.contactStore.enumerateContacts(with: request) {
                (contact, stop) in
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
                if contact.givenName.prefix(1) == auxLetter {
                    contacts.append(contact)
                } else {
                    if isNotTheFirst {
                        let contactsExpandables = ContactStruct(isExpanded: true, contacts: contacts, letter: auxLetter)
                        self.contactStructArray.append(contactsExpandables) //guardamos el contacto expandible anterior
                        auxLetter = String(contact.givenName.prefix(1)) //guardamos la nueva letra
                        contacts = [CNContact]() //inicializamos nuevamente el array de contactos
                        contacts.append(contact) //guardamos el nuevo contacto
                    } else {
                        contacts.append(contact)
                        auxLetter = String(contact.givenName.prefix(1)) //auxLetter tiene la primera letra del nombre
                        isNotTheFirst = true //la siguiente vez que las letras no sean iguales guardara en el array
                    }
                }
Javier Heisekce committed
56
            }
57
            self.contactStructArray.append(ContactStruct(isExpanded: true, contacts: contacts, letter: auxLetter)) //agregamos el ultimo nombre
58
            self.contactAux = self.contactStructArray
Javier Heisekce committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
        }
        catch {
            print("unable to fetch contacts")
        }
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let singleContactVC = segue.destination as? SingleContactViewController {
            if let selectedCnt = sender as? CNContact {
                singleContactVC.selectedContact = selectedCnt
            }
        }
    }
}
extension ContactsViewController: UITableViewDelegate, UITableViewDataSource {
74 75 76 77 78
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return contactStructArray.count
    }
    
Javier Heisekce committed
79
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
80
        if !contactStructArray[section].isExpanded {
Javier Heisekce committed
81 82 83
            return 0
        }
        
84
        return contactStructArray[section].contacts.count
Javier Heisekce committed
85 86
    }
    
Javier Heisekce committed
87
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {        
Javier Heisekce committed
88
        let cell = tableView.dequeueReusableCell(withIdentifier: "contactName")!
89
        let contactCell = contactStructArray[indexPath.section].contacts[indexPath.row]
90 91 92 93 94 95 96 97 98 99 100
        
        let givenName = "\(contactCell.givenName) "
        let familyName: NSMutableAttributedString = NSMutableAttributedString(string: contactCell.familyName)
        
        let attributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.boldSystemFont(ofSize: 15)
        ]
        let fullName = NSMutableAttributedString(string: givenName, attributes: attributes)
        fullName.append(familyName)
        
        cell.textLabel?.attributedText = fullName
Javier Heisekce committed
101
        
Javier Heisekce committed
102 103 104 105
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
106
        let selectedContact = contactStructArray[indexPath.section].contacts[indexPath.row]
Javier Heisekce committed
107 108 109
        performSegue(withIdentifier: "gotocontact", sender: selectedContact)
    }
    
110 111 112 113 114
    func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
        return 40
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
115 116 117 118 119 120 121 122 123
        let header = contactsTable.dequeueReusableHeaderFooterView(withIdentifier: "headerId") as! ContactSectionView
        header.contentView.backgroundColor = .systemGray4
        header.labelExpandable.setTitle("Λ", for: .normal)
        header.labelExpandable.setTitleColor(.black, for: .normal)
        header.labelExpandable.titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
        header.labelExpandable.addTarget(self, action: #selector(interactSection), for: .touchUpInside)
        header.labelExpandable.tag = section
        header.labelLetter.text = contactStructArray[section].letter
        return header//ʌΛ
124 125
    }
    
126
    @objc func interactSection(button : UIButton) {
Javier Heisekce committed
127 128
        //contactsBackup = contacts
        let section = button.tag
129 130
        
        var indexPaths = [IndexPath]()
131
        for row in contactStructArray[section].contacts.indices {
132 133 134
            let indexPath = IndexPath(row: row, section: section)
            indexPaths.append(indexPath)
        }
Javier Heisekce committed
135

136 137
        let isExpanded = contactStructArray[section].isExpanded
        contactStructArray[section].isExpanded = !isExpanded
Javier Heisekce committed
138 139 140 141 142 143 144 145 146
        
        button.setTitle(isExpanded ? "V" : "Λ", for: .normal)
        
        if isExpanded {
            contactsTable.deleteRows(at: indexPaths, with: .top)
        } else {
            contactsTable.insertRows(at: indexPaths, with: .bottom)
        }
        
147
    }
Javier Heisekce committed
148
}
149 150 151 152

extension ContactsViewController: UISearchBarDelegate, UISearchDisplayDelegate, UISearchResultsUpdating {
    
    func updateSearchResults(for searchController: UISearchController) {
153 154 155
        
    }
    
156
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
157
        contactStructArray = contactAux
158 159
    }
    
160
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
161 162 163
        var foundContacts = [ContactStruct]()
        
        if searchText == "" {
164
            contactStructArray = contactAux
165 166
            contactsTable.reloadData()
        } else {
167 168 169 170 171 172 173
            for indexContact in contactAux.indices{
                let contactFound = contactAux[indexContact].contacts.filter(
                    {
                    let fullName = "\($0.givenName) \($0.familyName)"
                    return fullName.lowercased().contains(searchText.lowercased())
                    }
                )
174 175
                
                if !contactFound.isEmpty {
176
                    foundContacts.append(ContactStruct(isExpanded: true, contacts: contactFound, letter: contactAux[indexContact].letter))
177 178 179 180 181
                }
            }
            contactStructArray = foundContacts
            contactsTable.reloadData()
        }
182
    }
183
}