【问题标题】:Terminating app due to uncaught exception 'NSInternalInconsistencyException',- Swift 3由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,-Swift 3
【发布时间】:2018-06-05 01:50:36
【问题描述】:

这是我的全部错误

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for rect at invalid index path (<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})

我的 numberOfRows 有此代码

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if monthlyExpenses.count == 0{
        noExpenseLabel.isHidden = false
    }
    return monthlyExpenses.count
} 

这是我的 cellForRowAtIndexPath 的代码

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "monthlyCell", for: indexPath) as! MonthlyExpenseTableViewCell

    //var newMode2:Bool? = nil

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 64

    let expense = monthlyExpenses[indexPath.row]

    let date = expense.modificationDate
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "EEEE d MMMM"
    let dateString = dateFormatter.string(from: date! as Date).uppercased()

    for expense in monthlyExpenses {
        if expense.modificationDate?.convertToMonth() != monthDisplayed.text{
            if let expenseSorter = monthlyExpenses.index(of: expense) {
                monthlyExpenses.remove(at: expenseSorter)
            }
        }
    }
    CoreDataHelper.save()
    if indexPath.row == 0{
        newMode = true
    }
    if indexPath.row>=1{
        monthlyExpenses.sorted(by: { $0.modificationDate as! Date > $1.modificationDate as! Date})
      let previousExpensesData = monthlyExpenses[indexPath.row - 1].modificationDate
        let day = Calendar.current.component(.day, from: monthlyExpenses[indexPath.row].modificationDate as! Date) // Do not add above 'date' value here, you might get some garbage value. I know the code is redundant. You can adjust that.
        let previousDay = Calendar.current.component(.day, from: monthlyExpenses[indexPath.row - 1].modificationDate! as Date)
        if day == previousDay {
            newMode = false
        } else {
            newMode = true
        }
    }


    var expenseAmountCalculating:Double = Double(expense.amount!)!
    var expenseAmountDisplayed:String = convertToMoney(expenseAmountCalculating)

    var finalDisplayed:String = expense.currencySymbol! + " " + expenseAmountDisplayed
    let screenSize: CGRect = UIScreen.main.bounds
    cell.dateLabel.text = dateString
    cell.expenseName2.text = expense.name
    cell.expenseAmount2.text = finalDisplayed
    cell.expenseCategory2.text = expense.category
    cell.expenseCollection2.text = expense.collection
                if (expense.expense) {
                    cell.expenseAmount2.textColor = UIColor.red
                }


                else if (expense.income){
                    cell.expenseAmount2.textColor = UIColor.green
                }

                if (expense.cash) && (expense.expense){
                    cell.cashOrCredit.image = #imageLiteral(resourceName: "Cash-Expense Icon")

                }
                else if (expense.cash) && (expense.income){
                    cell.cashOrCredit.image = #imageLiteral(resourceName: "Cash-Income Icon")

                }
                else if (expense.credit) && (expense.income){
                    cell.cashOrCredit.image = #imageLiteral(resourceName: "Credit-Income Icon")

                }
                else if (expense.credit) && (expense.income){
                    cell.cashOrCredit.image = #imageLiteral(resourceName: "Credit-Expense Icon")

                }
    if newMode == false{
        cell.dateLabel.isHidden = true
        tableView.rowHeight = 64
        cell.expenseName2.frame.origin = CGPoint(x: 60, y: 11)
        cell.expenseCategory2.frame.origin = CGPoint(x: 61, y: 33)
        cell.expenseCollection2.frame.origin = CGPoint(x: 108, y: 33)


    }
    else if newMode == true{
        tableView.estimatedRowHeight = 64

    }

return cell

}

我尝试在 CoreDataHelper.save() 之后执行代码 有条件

if monthlyExpense.count>=1

但这似乎没有任何作用。理想情况下,在没有费用的一个月内,它应该不打印任何内容,并且一个名为 NoExpenseLabel 的默认视图应该是可见的。 为什么我会收到此错误。

这是我拥有的年视图控制器,每当我单击一个单元格时,它都会执行上面的代码。因此,如果单击 7 月,则仅显示 7 月的费用。这就是为什么我有每月费用(删除:)代码的原因。

enter image description here

【问题讨论】:

  • 你犯了一个致命的错误:你不能改变cellForRow中数据源项的数量。此方法仅用于将内容分配给 UI 元素。在模型或控制器中进行昂贵的计算。而在numberOfRowsInSection 中,返回数据源数组中的项目数,仅此而已。
  • 我在哪里更改数据源项的数量?
  • monthlyExpenses.remove(at: 减少数据源项的数量
  • 我在上面添加了一张图片,以及我为什么要每月支出的原因。remove() 有没有其他方法可以做到这一点?
  • 请学习理解MVC(模型-视图-控制器)模式的工作原理。

标签: ios uitableview swift3 sigabrt


【解决方案1】:

请不要删除cellForRowAt indexPath 中的monthlyExpenses。因为当 tableView 再次调用cellForRowAt indexPath 时,数组中的元素将少于您在numberOfRowsInSection 中所说的元素。您需要先删除数组的元素,然后再调用reloadData

【讨论】:

  • 我删除monthlyExpenses的原因是只显示与特定月份相关的费用。
  • 是的,但不在cellForRowAt indexPath 中。试试这个:创建一个函数来检查你的数组并删除你不想显示的元素。在viewDidLoad 或您获得数据的地方调用它。如果您需要有关此功能的帮助,请将您的代码复制到您获取数据的位置。 =)
  • 所有数据都由这个数组接收,因为它是由 coreData 填充的 varmonthlyExpenses = [Expense]()
  • 好吧,在你填充数组var monthlyExpenses = [Expense]()之后,你必须删除你不想显示的元素。
猜你喜欢
  • 2014-01-05
  • 2012-07-28
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
相关资源
最近更新 更多