Florentin Lupascu
Florentin Lupascu

Reputation: 993

When I insert a new record is not displayed in the UITableview

I created a Contact App populated with dummy data and when I try to insert a new contact is not appearing in my UITableView but if I printout my array is showing me that is there. Also my delete is not working very well. Is deleting the whole section instead to delete my selected row. Can you help me to fix my insert function and my delete function ? Thanks.

Here is my code:

class Contact {
    var fullName: String
    var phoneNumber: String?

    init(fullName: String, phoneNumber: String) {
        self.fullName = fullName
        self.phoneNumber = phoneNumber
    }
}


var contactsArray = [Contact]()

var sections = [[Contact]]()

// Logic functionality for my "Contact" application
class ContactViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var nameTextField: UITextField!
    @IBOutlet var phoneTextField: UITextField!
    @IBOutlet var contactsTableView: UITableView!


    override func viewDidLoad() {
        super.viewDidLoad()

 contactsTableView.delegate = self
        contactsTableView.dataSource = self
        phoneTextField.delegate = self

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        contactsTableView.reloadData()
    }
}

extension ContactViewController: UITableViewDelegate, UITableViewDataSource{

    // Add a new contact to the end of list
    @IBAction func insertNewContact(_ sender: UIButton) {

        if nameTextField.text != nil && nameTextField.text != "" {

            contactsArray.append(Contact(fullName: nameTextField.text!, phoneNumber: phoneTextField.text!))
            contactsTableView.reloadData()


        }

    }

    // Return no of sections from your list
    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    // Return no of rows in each section from your list
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section].count
    }

    // Insert a custom cell in your table view
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let contact = sections[indexPath.section][indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
        cell.configContact(contact)
        return cell
    }


    // Delete a section when you swipe from right to left
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

        if editingStyle == UITableViewCellEditingStyle.delete{
            sections.remove(at: indexPath.row)
            contactsTableView.reloadData() // xCode is confused sometimes and because my outlet var was named "tableView" and not "contactsTableView" it was trying to reload data from the parameter "tableView" of function and delete wasn't working at all. Now is deleting the whole section but I still need to work on it.
        }
    }


}

Screenshot

Upvotes: 0

Views: 338

Answers (1)

vacawama
vacawama

Reputation: 154691

Your data is contained in contactsArray, but your table's data source is sections array. You need to update the sections array when contactsArray is changed.

Move your code that creates the sections array into its own method. Call it after inserting data into contactsArray and before calling reloadData() on the table:

func createSectionsArray() {
    let firstLetters = contactsArray.map { $0.titleFirstLetter }
    let uniqueFirstLetters = Array(Set(firstLetters))

    sortedFirstLetters = uniqueFirstLetters.sorted()
    sections = sortedFirstLetters.map { firstLetter in
        return contactsArray
            .filter { $0.titleFirstLetter == firstLetter }
            .sorted { $0.fullName < $1.fullName }
    }
}

You'll also want to call it from viewDidLoad() in place of the code you removed to create the function.


Deleting:

For deleting, first make your Contact class conform to Equatable:

class Contact: Equatable {
    static func == (lhs: Contact, rhs: Contact) -> Bool {
        return lhs.fullName == rhs.fullName && lhs.phoneNumber == rhs.phoneNumber
    }

    var fullName: String
    var phoneNumber: String?

    init(fullName: String, phoneNumber: String) {
        self.fullName = fullName
        self.phoneNumber = phoneNumber
    }
}

Then, when an item is deleted, use indexPath.section and indexPath.row to look up the contact, find the contact in the contactsArray and remove it, regenerate the sections array, then reload the table:

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {
        let contact = sections[indexPath.section][indexPath.row]

        if let index = contactsArray.index(of: contact) {
            contactsArray.remove(at: index)
            createSectionsArray()
            contactsTableView.reloadData()
        }
    }
}

Upvotes: 1

Related Questions