2016-06-07 96 views
0

我有一個UITableView包含自定義單元格。這些單元格可以手動移動。另外,單元上的開關導致它被移動到底部。如果與拖動到重新排序分開使用,交換機工作正常。但是,如果我拖動到重新排序第一,然後用一個開關,我得到以下錯誤:如果手動先移動UITableViewCell編程移動失敗

*** 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觸發器時,該方法中的斷點不會被擊中。

回答

0

愚蠢的錯誤。此行self.eventTypes.removeObject(sourceIndexPath.row)應該是self.eventTypes.removeObject(object)。該對象從未被刪除,因此,當重新加載或更新完成被調用時,它無法正確確定項目的數量,因爲它隨着每次移動而增長。