我有一个UITableView包含自定义单元格。这些单元格可以手动移动。此外,单元格上的开关会使它移到底部。如果将其与按拖动顺序分开使用,则该开关可以正常工作。但是,如果我先拖动以重新排序,然后使用开关,则会出现以下错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'


控制器具有与该表有关的以下代码:

//Table Delegate/Datasource
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
    let object = self.eventTypes[sourceIndexPath.row]
    self.eventTypes.insertObject(object, atIndex: sourceIndexPath.row)
    self.eventTypes.removeObject(sourceIndexPath.row)
}

func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}

func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return false
}

func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
    return UITableViewCellEditingStyle.None
}

func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell:S360SEventTypeTableCell? = tableView.dequeueReusableCellWithIdentifier(XIBFiles.EVENTTYPETABLECELL) as? S360SEventTypeTableCell

    if ((cell == nil)){
        tableView.registerNib(UINib(nibName: XIBFiles.EVENTTYPETABLECELL, bundle: nil), forCellReuseIdentifier: XIBFiles.EVENTTYPETABLECELL)
        cell = tableView.dequeueReusableCellWithIdentifier(XIBFiles.EVENTTYPETABLECELL) as? S360SEventTypeTableCell
    }

    let eventType = eventTypes[indexPath.row]

    cell!.iconImg.image = Images.get_event_image(eventType["title"]! as! String)
    cell!.titleLbl.text = (eventType["title"]! as! String)


    return cell!
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return eventTypes.count
}


自定义单元格具有以下代码:

 @IBOutlet var iconImg:UIImageView!
@IBOutlet var titleLbl:UILabel!
@IBOutlet var timeField:UITextField!
@IBOutlet var activeSwtch:UISwitch!
@IBOutlet var durationLbl:UILabel!
@IBOutlet var minsLbl:UILabel!

override func awakeFromNib() {
    super.awakeFromNib()

}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
}

override func layoutSubviews() {
    super.layoutSubviews()

    //Styling
    timeField.layer.borderColor = Colors.REALLIGHTGREY.CGColor
    timeField.layer.borderWidth = Numbers.BORDERREG
    timeField.layer.cornerRadius = Numbers.CORNERRADIUS
    timeField.tintColor = Colors.REDNESS

    activeSwtch.onTintColor = Colors.REDNESS

    self.showsReorderControl = true
}

func getTableView() -> UITableView?{
    var tableView:UITableView? = nil
    var view:UIView = self

    while !view.isKindOfClass(UITableView.self) && view.superview != nil {
        view = view.superview!
    }

    if view.isKindOfClass(UITableView.self) {
        tableView = (view as! UITableView)
    }

    return tableView
}

@IBAction func activeSwtchTouch(){

    if self.activeSwtch.on{
        self.titleLbl.enabled = true
        self.timeField.enabled = true
        self.durationLbl.enabled = true
        self.minsLbl.enabled = true
        self.iconImg.alpha = 1.0
        self.showsReorderControl = true
    }
    else{
        let tableView = self.getTableView()

        if tableView != nil {
            let fromPath = tableView!.indexPathForCell(self)!
            let toPath = NSIndexPath(forRow: tableView!.numberOfRowsInSection(fromPath.section) - 1, inSection: fromPath.section)
            print("FROM: " + String(fromPath.row) + ":" + String(fromPath.section))
            print("TO: " + String(toPath.row) + ":" + String(toPath.section))
            print("SECTIONS: " + String(tableView!.numberOfSections))
            print("ROWS: " + String(tableView!.numberOfRowsInSection(fromPath.section)))
            tableView!.moveRowAtIndexPath(fromPath, toIndexPath: toPath)
            self.titleLbl.enabled = false
            self.timeField.enabled = false
            self.durationLbl.enabled = false
            self.minsLbl.enabled = false
            self.iconImg.alpha = 0.5
            self.showsReorderControl = false
        }
    }
}


注意:moveRowAtIndexPath的自定义委托方法似乎仅在使用拖动到重新排序时被调用,而在UISwitch触摸触发时不被调用。至少,使用UISwitch触摸触发器时,该方法中的断点不会被命中。

最佳答案

愚蠢的错误。此行self.eventTypes.removeObject(sourceIndexPath.row)应为self.eventTypes.removeObject(object)。该对象从未删除过,因此,当调用重新加载或更新完成时,由于每次移动都在增长,因此无法正确确定项目的数量。

关于ios - 如果先手动移动,则以编程方式移动UITableViewCell失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37684629/

10-12 01:41
查看更多