Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 在cellForRowAt方法中刷新indexPath.row时,返回的值不正确_Swift_Uitableview - Fatal编程技术网

Swift 在cellForRowAt方法中刷新indexPath.row时,返回的值不正确

Swift 在cellForRowAt方法中刷新indexPath.row时,返回的值不正确,swift,uitableview,Swift,Uitableview,我是一名iOS开发实习生,所以有些事情我还不太了解。 我正在创建一个联系人应用程序,其中的姓名显示在部分中,就像原来的一样,但添加了删除功能 我有以下问题: 如果我有一个联系人单独在一个部分,就像我在刷卡时删除它一样,一切都很好。但是,如果我在设备的联系人应用程序中添加相同的联系人,然后返回到我的应用程序并下拉刷新以添加更新我的应用程序中的表,我会得到致命错误:索引超出范围,应用程序崩溃并被活动指示器加载卡住 代码如下: 我如何在manager类中填充数据源 func addContactsTo

我是一名iOS开发实习生,所以有些事情我还不太了解。 我正在创建一个联系人应用程序,其中的姓名显示在部分中,就像原来的一样,但添加了删除功能

我有以下问题:

如果我有一个联系人单独在一个部分,就像我在刷卡时删除它一样,一切都很好。但是,如果我在设备的联系人应用程序中添加相同的联系人,然后返回到我的应用程序并下拉刷新以添加更新我的应用程序中的表,我会得到致命错误:索引超出范围,应用程序崩溃并被活动指示器加载卡住

代码如下:

我如何在manager类中填充数据源

func addContactsToDictionary(from arrayOfContacts: [Contact]) {
    for contact in arrayOfContacts {
        let contactsKey = String(contact.firstName.prefix(1))       // Getting each given name's first letter
        if var contactsValue = contactsDictionary[contactsKey] {    // if there's already a value for the current key
            contactsValue.append(contact)     // Creating a value array of given names for the dictionary
            contactsDictionary[contactsKey] = contactsValue     // Adding a value array of given names to the current key in the dictionary
        } else {
            contactsDictionary[contactsKey] = [contact]
        }
    }
    createAndSortSectionsArray()
}

func createAndSortSectionsArray() {
    sectionTitles = [String](contactsDictionary.keys)
    sectionTitles = sectionTitles.sorted(by: { $0 < $1})
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let contactKey = contactManager.sectionTitles[section]
    guard let contactValues = contactManager.contactsDictionary[contactKey] else { return nil }

    return contactValues.isEmpty ? nil : contactManager.sectionTitles[section]
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let contactKey = contactManager.sectionTitles[section]
    guard let contactValues = contactManager.contactsDictionary[contactKey] else { return 0 }

    return contactValues.isEmpty ? 0 : contactValues.count
}
数据源的表视图控制器扩展

extension ContactsTableViewController {

override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    let contactsInitialAsKey = contactManager.sectionTitles[indexPath.section]

    if editingStyle == .delete {
        contactManager.deleteContacts(at: indexPath)
        contactManager.contactsDictionary[contactsInitialAsKey]!.remove(at: indexPath.row)

        tableView.deleteRows(at: [indexPath], with: .automatic)


        if indexPath.row == 0 && contactManager.contactsDictionary[contactsInitialAsKey]!.isEmpty {
            contactManager.contactsDictionary[contactsInitialAsKey] = nil
            contactManager.sectionTitles.remove(at: indexPath.section)
            tableView.reloadData()
        }
    }
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    contactManager.sectionTitles[section]
}

override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
    return contactManager.sectionTitles
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return contactManager.sectionTitles.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let contactKey = contactManager.sectionTitles[section]
    guard let contactValues = contactManager.contactsDictionary[contactKey] else { return 0 }
    print(contactValues.map({ $0.firstName }), contactValues.count)
    return contactValues.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath) as! ContactCell
    let contactKey = contactManager.sectionTitles[indexPath.section]

    cell.contactsViewController = self
    cell.setStarButton()
    cell.setImageView()

    if let contacts = contactManager.contactsDictionary[contactKey] {
        print(contactKey, contacts.map { $0.firstName }, indexPath.section, indexPath.row) 
        cell.setDataToContactCell(contactData: contacts[indexPath.row]) // Where I get the Thread 1: Fatal error: Index out of range

    }
    return cell
  }
}
到目前为止,我只能通过以下操作找到可能的问题:

打印(contactKey,contacts.map{$0.firstName},indexPath.section,indexPath.row)

看看发生了什么,这就是日志显示给我的

Attempting to refresh data
Attempting to fetch contacts today...
Access granted
G ["Guga"] 2 1 //Here I noticed that for some reason the indexPath.row is not returning the correct value
Fatal error: Index out of range
2020-01-10 07:10:59.976537+0300 myContacts[12858:351184] Fatal error: Index out of range
我看了很多类似的文章,但在大多数文章中,indexPath.row的问题与单击按钮获取有关。所以我没有找到合适的解决方案,也不知道如何解决这个问题

如果你能帮助我,我将非常感激。
谢谢大家!

您需要像这样更新handleRefresh()代码。仅当您成功获得响应时,才从联系人字典中删除数据。收到响应并存储在Contacts Dictionary中后,重新加载tableview

@objc func handleRefresh() {
    print("Attempting to refresh data")
    let delay = 1

    self.contactManager.fetchContacts { (response, error) in
      if let errorToCatch = error {
        UITableViewController.Alert.showFetchingErrorAlert(on: self, message: errorToCatch.localizedDescription)
      } else if let contactsArray = response {
        self.contactManager.contactsDictionary.removeAll()  // To avoid duplicated data
        self.contactManager.addContactsToDictionary(from: contactsArray)
        self.tableView.reloadData()
        self.myRefreshControl.endRefreshing()
    }

  }
}

通过对数据源扩展进行以下更改,我能够修复此问题

1。从“提交编辑样式方法”中删除联系人字典中空值数组的验证

2.将其移动到标题部分,并“隐藏”这些部分的标题

func addContactsToDictionary(from arrayOfContacts: [Contact]) {
    for contact in arrayOfContacts {
        let contactsKey = String(contact.firstName.prefix(1))       // Getting each given name's first letter
        if var contactsValue = contactsDictionary[contactsKey] {    // if there's already a value for the current key
            contactsValue.append(contact)     // Creating a value array of given names for the dictionary
            contactsDictionary[contactsKey] = contactsValue     // Adding a value array of given names to the current key in the dictionary
        } else {
            contactsDictionary[contactsKey] = [contact]
        }
    }
    createAndSortSectionsArray()
}

func createAndSortSectionsArray() {
    sectionTitles = [String](contactsDictionary.keys)
    sectionTitles = sectionTitles.sorted(by: { $0 < $1})
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let contactKey = contactManager.sectionTitles[section]
    guard let contactValues = contactManager.contactsDictionary[contactKey] else { return nil }

    return contactValues.isEmpty ? nil : contactManager.sectionTitles[section]
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let contactKey = contactManager.sectionTitles[section]
    guard let contactValues = contactManager.contactsDictionary[contactKey] else { return 0 }

    return contactValues.isEmpty ? 0 : contactValues.count
}
3。并将其移动到numberOfRowsInSection方法,并为这些部分返回0

func addContactsToDictionary(from arrayOfContacts: [Contact]) {
    for contact in arrayOfContacts {
        let contactsKey = String(contact.firstName.prefix(1))       // Getting each given name's first letter
        if var contactsValue = contactsDictionary[contactsKey] {    // if there's already a value for the current key
            contactsValue.append(contact)     // Creating a value array of given names for the dictionary
            contactsDictionary[contactsKey] = contactsValue     // Adding a value array of given names to the current key in the dictionary
        } else {
            contactsDictionary[contactsKey] = [contact]
        }
    }
    createAndSortSectionsArray()
}

func createAndSortSectionsArray() {
    sectionTitles = [String](contactsDictionary.keys)
    sectionTitles = sectionTitles.sorted(by: { $0 < $1})
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let contactKey = contactManager.sectionTitles[section]
    guard let contactValues = contactManager.contactsDictionary[contactKey] else { return nil }

    return contactValues.isEmpty ? nil : contactManager.sectionTitles[section]
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let contactKey = contactManager.sectionTitles[section]
    guard let contactValues = contactManager.contactsDictionary[contactKey] else { return 0 }

    return contactValues.isEmpty ? 0 : contactValues.count
}

这可能是因为在用户使用表视图删除一行后,您没有对数据源进行更改。您能告诉我怎么做吗@ElTomato@ElTomato我不是在commit editingStyle方法中这样做的吗?对数据源的更改。或者应该在另一个地方完成?但是如果我想延迟刷新?不。如果你这样做,你将恢复到原始的日期设置,然后返回到第一个。你的建议导致了相反的结果。已删除的所有联系人以及仅显示最近添加的联系人。打印(contactsArray)或放置断点以检查contactsArray的计数