Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.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 tableviewdeleterows应用程序崩溃,即使数据已更新_Swift_Xcode - Fatal编程技术网

Swift tableviewdeleterows应用程序崩溃,即使数据已更新

Swift tableviewdeleterows应用程序崩溃,即使数据已更新,swift,xcode,Swift,Xcode,我目前有一段代码,可以删除一个表行 extension HomeController: SwipeTableViewCellDelegate { func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? { guard orientation == .rig

我目前有一段代码,可以删除一个表行

extension HomeController: SwipeTableViewCellDelegate {
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
    guard orientation == .right else { return nil }
    print("in delete")
    let deleteAction = SwipeAction(style: .destructive, title: "Delete") { [self] action, indexPath in
        print("currently deleting")
        userHabitData.remove(at: indexPath.section)
        tableView.deleteRows(at: [indexPath], with: .fade)
    }

    // customize the action appearance
    deleteAction.image = UIImage(named: "delete")

    return [deleteAction]
}
我确保在使用删除行之前更改数据源

userHabitData.remove(at: indexPath.section)
但是,代码仍然抛出此错误

线程1:“无效更新:节0中的行数无效。更新后现有节中包含的行数(1)必须等于更新前该节中包含的行数(1),加上或减去从该节插入或删除的行数(0插入,1删除)加上或减去移入或移出该节的行数(0移入,0移出)。”

这是我的完整视图控制器

//
//  ViewController.swift
//  Habit Tracker
//
//  Created by Alan Weng on 11/24/20.
//

import UIKit
import SwipeCellKit

class tableViewCell: SwipeTableViewCell {
    @IBOutlet weak var habitName: UILabel!
    @IBOutlet weak var habitCount: UILabel!
    
    
    var habit: Habit? {
        didSet {
            self.updateUI()
        }
    }
    
    func updateUI() {
        print("being run")
        habitName?.text = habit?.title
        habitCount?.text = habit?.detail
//        progressLabel?.observedProgress = habit?.progress
    }
    
}

class HomeController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var deno_label: UILabel!
    @IBOutlet weak var tableView: UITableView!
    let impactFeedbackgenerator = UIImpactFeedbackGenerator(style: .heavy)
    @IBOutlet weak var deno_img: UIImageView!
    var UserHabitDict: [String:String] = [:]
    var userHabitData = [HabitDict]()
    var userHabitName: String?
    var userHabitCount: String?
    let cellReuseID = "habitName"
    let cellSpacingHeight: CGFloat = 15
    let customRed = UIColor().customRed()
    let customBlue = UIColor().customBlue()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self
    }

    @IBAction func createNewGoal(_ sender: Any) {
        let goalVC = storyboard?.instantiateViewController(withIdentifier: cellReuseID) as! CreateGoalController
        impactFeedbackgenerator.prepare()
        impactFeedbackgenerator.impactOccurred()
        goalVC.habitDelegate = self
        present(goalVC, animated: true, completion: nil)
    }
    
    // Think of how ios settings have different sections w diff spacings
    func numberOfSections(in tableView: UITableView) -> Int {
        return UserHabitDict.count
    }
    
    // Adjusts cell spacing between habits
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return cellSpacingHeight
    }
    
    // Adjust row height
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 75
    }
    
    // Allows the table to keep expanding based on how many habits are in the array
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    // Make the background color show through
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let headerView = UIView()
        headerView.backgroundColor = UIColor.clear
        return headerView
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if habitIsEmpty() {
            deno_img.alpha = 0.0
            deno_label.alpha = 0.0
        }
        print("making habit")
        let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseID) as! tableViewCell
        let dictKey = userHabitData[indexPath.section].getName()
        let dictValue = userHabitData[indexPath.section].getCount()
        cell.delegate = self
        cell.backgroundColor = customBlue
        cell.layer.cornerRadius = 10
        cell.habit = Habit(title: dictKey, detail: dictValue)
        print(userHabitData)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
        var options = SwipeOptions()
        options.expansionStyle = .destructive
        options.transitionStyle = .border
        return options
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // note that indexPath.section is used rather than indexPath.row
//        print("You tapped cell number \(indexPath.section).")
//        let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseID) as! tableViewCell
//      cell.habit?.updateDetail()
//      tableView.reloadData()
//        let dictKey = userHabitData[indexPath.section].getName()
//        var dictValue = userHabitData[indexPath.section].getCount()
//        print("over here")
//        dictValue = String(Int(dictValue)! - 1)
//        print(dictValue)
//        cell.habit = Habit(title: dictKey, detail: dictValue)
//        tableView.reloadData()
        
    }
    
    func allowMultipleLines(tableViewCell: UITableViewCell) {
        tableViewCell.textLabel?.lineBreakMode = .byWordWrapping
    }
    
    func habitIsEmpty() -> Bool {
        if userHabitData.isEmpty {
            return false
        } else {
            return true
        }
    }
    
}

extension HomeController: CreateGoalDelegate {
    func didTapSave(name: String, count: String) {
        userHabitName = name
        userHabitCount = count
        UserHabitDict[name] = count
        userHabitData.append(HabitDict(habitName: name, habitCount: count))
//      tableView.insertRows(at: [IndexPath(row: userHabitData.count, section: 0)], with: .automatic)
        tableView.reloadData()
        print("in reload data")
    }
}

extension UIColor {
    func customRed() -> UIColor {
        return UIColor(red: 0.607, green: 0.160, blue: 0.282, alpha: 1.00)
    }
    func customBlue() -> UIColor {
        return UIColor(red: 0.509, green: 0.701, blue: 0.964, alpha: 1.00)
    }
}

struct HabitDict {
    let habitName: String
    let habitCount: String
    
    func getName() -> String {
        return habitName
    }
    
    func getCount() -> String {
        return habitCount
    }
}

extension HomeController: SwipeTableViewCellDelegate {
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
        guard orientation == .right else { return nil }
        print("in delete")
        let deleteAction = SwipeAction(style: .destructive, title: "Delete") { [self] action, indexPath in
            print("currently deleting")
            userHabitData.remove(at: indexPath.section)
            tableView.deleteRows(at: [indexPath], with: .fade)
        }

        // customize the action appearance
        deleteAction.image = UIImage(named: "delete")

        return [deleteAction]
    }
}

任何帮助都将不胜感激

问题在于您的数据源不一致

delete
方法中,数据源数组是
userHabitData
,但是在
numberOfSections
中,您使用的是
UserHabitDict
,在delete操作中不会更新

numberOfSections
替换为

func numberOfSections(in tableView: UITableView) -> Int {
    return userHabitData.count
}
然后删除部分(包括行)


请删除结构中的
getName
getCount
函数。它们是多余的。直接使用名称和计数成员。您还可以从名称中删除冗余信息习惯

Try而不是
deleteRows
您可以尝试
self.userHabitData.remove(位于:indexath.section)
?它仍然会给我相同的结果,我做了一些调试,发现删除后的数组计数实际上是0,而删除行之前的行计数是1。我相信这应该是正确的输出,这让我更加困惑,下面这行没有意义。同样,以下几行也没有意义。让dictKey=userHabitData[indexath.section].getName();让dictValue=userHabitData[indexPath.section].getCount()非常感谢您的回复!我应用了更改,但不幸的是,它仍然给我相同的错误消息。我还想知道为什么在tableView.deleteSections中有“at”,因为xcode在:“in call”处给了我一个错误“externeous argument label:”in call“不确定我是否遗漏了什么错误,请删除
at:
。如果数据源数组是一致的,那么代码应该可以工作。由于某种原因,我的代码在不使用swipecellkit的情况下工作正常,我使用了UITableViewCell.EditingStyle,它工作正常!
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { [self] action, indexPath in
    print("currently deleting")
    userHabitData.remove(at: indexPath.section)
    tableView.deleteSections([indexPath.section], with: .fade)
}