skip to Main Content

Sorry, I’m a noob,

I am a bit stuck. I have been researching this for awhile and cannot find anything to help.

So, my problems is:

I have a Table View controller with a bunch of Cells (Depending on users contact address book). These Cells contain the users contacts information (Name and #) users can select up to 3 cells (Contacts).

That all works fine, I just need to know how to get the name and # labels data from each cell so I can display that information in another View Controller (CAContactsList) when I press the "Done" button (which I’m also stumped with).

My Current Table View Controller Class:

class AddContactsListTableView: UITableViewController {

  var contacts = [FetchedContact]()

  override func viewDidLoad() {
    super.viewDidLoad()
    
    fetchContacts()
  }

  private func fetchContacts() {
    print("Attempting to fetch contacts")
    
    let store = CNContactStore()
    store.requestAccess(for: .contacts) { (granted, error) in
      if let error = error {
        print("failed to request access", error)
        return
      }
        
      if granted {
        print("access granted")
            
        let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
        let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
            
        do {
          try store.enumerateContacts(with: request, usingBlock: { (contact, stopPointer) in
            print(contact.givenName)
            self.contacts.append(FetchedContact(firstName: contact.givenName, lastName: contact.familyName, telephone: contact.phoneNumbers.first?.value.stringValue ?? ""))
          })
        } catch let error {
          print("Failed to enumerate contact", error)
        }
      } else {
        print("access denied")
      }
    }
  }

  // MARK: - Table view data source
  override func numberOfSections(in tableView: UITableView) -> Int {
    // return the number of sections
    return 1
  }

  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // return the number of rows
    return contacts.count
  }

  override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    //Max Number of contacts allowed to be selected
    let limit = 3
    if let selectedRows = tableView.indexPathsForSelectedRows {
      if selectedRows.count == limit {
        let alertController = UIAlertController(title: "Oops", message: "Sorry, but you are limited to only (limit) Contacts", preferredStyle: UIAlertController.Style.alert)
        alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: {action in}))
        self.present(alertController, animated: true, completion: nil)
     
        return nil
      }
    }

    return indexPath
  }

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cellIdentifier = "AddContactsCell"
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? AddContactsCell 
    
    // Configure the cell...
    cell?.NamesLabel.text = contacts[indexPath.row].firstName + " " + contacts[indexPath.row].lastName
    cell?.NumberLabel.text = contacts[indexPath.row].telephone
    
    return cell!
  }
}

My Current Cell Class:

class AddContactsCell: UITableViewCell {
  //Mark Properties
  @IBOutlet weak var NamesLabel: UILabel!
  @IBOutlet weak var NumberLabel: UILabel!
  @IBOutlet weak var ButtonSelector: UIButton!
  
  override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
  }

  override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    
    // update UI with Checkmark when Selected
    accessoryType = selected ? .checkmark : .none
  }
}

And my Fetched Contacts Class

struct FetchedContact {
  var firstName: String
  var lastName: String
  var telephone: String
}

Any help would be Greatly Appreciated!

2

Answers


  1. So basically you are already on the right track querying the table view’s indexPathsForSelectedRows since it will contain the indices you need to filter your contacts for. The selected contacts should be:

    guard let selectedIndices = tableView.indexPathsForSelectedRows else { return }
    let selectedContacts = selectedIndices.map { contacts[$0.item] }
    

    [Edit]: Use a more concise version

    Login or Signup to reply.
  2. Override the prepare(for segue: UIStoryboardSegue, sender: Any?) in the AddContactsListTableView class where you can pass the selected contacts to the next view controller.

        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            // Pass the selected object to the new view controller.
            if let selectedRows = tableView.indexPathsForSelectedRows {
                let selectedContacts = selectedRows.map{contacts[$0.row]}
                let newVC = segue.destination as! NewViewController
                newVC.contacts = selectedContacts
            }
        }
    

    See this tutorial for more.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search