0

我有一个字符串数组,我想根据 indexPath 数组中的值删除元素,该数组是从表格行上的 2 指平移手势生成的。循环重复次数取决于字符串数组的大小,每次循环都会删除相关的字符串数组元素。

下面的代码:

if let indexPaths = languagesTable.indexPathsForSelectedRows {
    rowCount = rowCount - (indexPaths.count)     
    controllerData.deleteWordsForLanguage(languages: languages, indexPaths: indexPaths)        
    for indexPath in indexPaths {
        print("inside 1st for loop in clearSelectedLanguages, indexPaths are: \(indexPaths)")
        print("languages.count in clearSelectedLanguages in languagesView os: \(languages.count)")
        for language in 0..<languages.count 
            print("indexPath.row == language is: \(indexPath.row == language) && indexPath.section == 0 is: \(indexPath.section == 0)")
            if indexPath.row == language && indexPath.section == 0 {
                print("inside 2nd for loop in clearSelectedLanguages in languages")
                print("languages in clearSelectedLanguages before languages.remove in languagesView are: \(languages)")
                languages.remove(at: language)
                print("languages in clearSelectedLanguages in languagesView are: \(languages)")
                }
            }
        }
    }
    controllerData.saveLanguages(languagesToSave: languages)
    languagesTable.setEditing(false, animated: true)
    languagesTable.reloadData()
    enableSort()
    enableDelete()
}

当我要求应用程序删除(按删除按钮)字符串数组的所有元素时,它会删除除一个元素之外的所有元素。我试过以不同的顺序排列字符串数组元素,它似乎不是特定于字符串元素值的,如果它是一个 3 元素数组,它总是中间元素。

我怀疑从数组中删除元素(其原始大小定义了所需的循环数)会导致第二个 for 循环出现问题。

一些调试控制台输出:

inside 1st for loop in clearSelectedLanguages, indexPaths are: [[0, 0], [0, 1], [0, 2]]
indexPath.row == language is: true && indexPath.section == 0 is: true
inside 2nd for loop in clearSelectedLanguages in languages
languages in clearSelectedLanguages in languagesView are: ["french", "spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]
indexPath.row == language is: false && indexPath.section == 0 is: true
indexPath.row == language is: false && indexPath.section == 0 is: true
inside 1st for loop in clearSelectedLanguages, indexPaths are: [[0, 0], [0, 1], [0, 2]]
indexPath.row == language is: false && indexPath.section == 0 is: true
indexPath.row == language is: true && indexPath.section == 0 is: true
inside 2nd for loop in clearSelectedLanguages in languages
languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish"]
inside 1st for loop in clearSelectedLanguages, indexPaths are: [[0, 0], [0, 1], [0, 2]]
indexPath.row == language is: false && indexPath.section == 0 is: true
languages in saveLanguages in dataModel are: ["spanish"]

如您所见,第二组 if 条件失败,并且字符串数组的最后一个元素永远不会被删除。然后程序退出所有 for 循环并调用包含最终调试打印语句的方法。

4

1 回答 1

1

使用循环通过索引删除元素常常会让我们感到困惑,因为目标索引会在执行循环时发生变化。

indexPaths给定as和as [[0, 0], [0, 1], [0, 2]]languages["french", "spanish", "german"]

  • [0, 0]为了"french"
  • [0, 1]为了"spanish"
  • [0, 2]为了"german"

删除第一个 indexPath[0, 0]时,可能没问题:

languages in clearSelectedLanguages in languagesView are: ["french", "spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]

它删除相应的元素"french"

但是在删除第二个 indexPath 时[0, 1],您可能需要仔细检查输出。

languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish"]

它删除(最初)第三个元素"german"而不是第二个元素"spanish"。因为一旦删除了一个元素,数组中每个元素的索引就会改变。

因此,当您想要删除第三个 indexPath[0, 2]时,什么都不会发生,因为单个元素 Array["spanish"]没有 index 元素2


处理这种情况的一种方法是以相反的顺序从下到上移除。

    for indexPath in indexPaths.reversed() {
        //...
    }

但是双循环不是一种有效的方法,我会写如下:

        if let indexPaths = languagesTable.indexPathsForSelectedRows {
            rowCount = rowCount - (indexPaths.count)
            controllerData.deleteWordsForLanguage(languages: languages, indexPaths: indexPaths)

            print("indexPaths are: \(indexPaths)")
            let rowsToRemove = Set(indexPaths.filter{$0.section == 0}.map{$0.row})
            print("languages before filter are: \(languages)")
            languages = languages.enumerated().filter{row,_ in !rowsToRemove.contains(row)}.map{$1}
            print("languages after filter are: \(languages)")

            controllerData.saveLanguages(languagesToSave: languages)
            //...
        }

请尝试一下。

于 2020-04-03T14:20:51.640 回答