我正在尝试创建重新订购指标。所以我试图做的是当用户拖动单元格时。在用户想要放置单元格的地方,其他单元格添加了背景。我已经做到了。但是当用户丢弃单元格时,需要删除指示符单元格,并且表格必须保持与用户期望的相同。
现在我有以下问题。当用户放下单元格时。指示器单元被正确移除,但掉落的单元突然位于另一个单元后面。
屏幕截图澄清:
我的代码:
import UIKit
import PureLayout
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(forAutoLayout: ())
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .SingleLine
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Default")
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Indicator")
tableView.tableFooterView = UIView()
return tableView
}()
private var data: [Int] = [Int]()
private var isIndicatorRowAddedInSection: Bool = false
private var lastIndicatorRowIndexPath: NSIndexPath?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero, excludingEdge: .Top)
self.tableView.autoPinEdgeToSuperviewEdge(.Top, withInset: 40)
for index in 0..<20 {
data.append(index)
}
self.tableView.editing = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Need to delete a row on section \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
self.lastIndicatorRowIndexPath = nil
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .Fade)
tableView.endUpdates()
}
let itemToMove = self.data[fromIndexPath.row]
self.data.removeAtIndex(fromIndexPath.row)
self.data.insert(itemToMove, atIndex: toIndexPath.row)
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .None
}
func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath,
toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Target indexpath indexpath to delete row \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .Fade)
tableView.endUpdates()
self.lastIndicatorRowIndexPath = nil
}
self.isIndicatorRowAddedInSection = true
self.lastIndicatorRowIndexPath = proposedDestinationIndexPath
tableView.beginUpdates()
print("Indicator view inserted at section \(proposedDestinationIndexPath.section) row \(proposedDestinationIndexPath.row)")
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: proposedDestinationIndexPath.row, inSection: proposedDestinationIndexPath.section)], withRowAnimation: .Automatic)
tableView.endUpdates()
return proposedDestinationIndexPath
}
}
extension ViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isIndicatorRowAddedInSection {
return self.data.count + 1
}
return self.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let indicatorIndexPath = self.lastIndicatorRowIndexPath where isIndicatorRowAddedInSection {
if indicatorIndexPath.section == indexPath.section && indicatorIndexPath.row == indexPath.row {
let cell = tableView.dequeueReusableCellWithIdentifier("Indicator", forIndexPath: indexPath)
return cell
}
}
let cell = tableView.dequeueReusableCellWithIdentifier("Default", forIndexPath: indexPath)
cell.textLabel?.text = String(self.data[indexPath.row])
return cell
}
}
我没有看到问题所在。有人能帮助我吗?
答案 0 :(得分:0)
我发现了问题。在moveRow中,它在线程1(主线程)上执行,但似乎不是。因为当你使用异步调度将它包装到主线程时,它才能正常工作。
完整的工作代码:
import UIKit
import PureLayout
class ViewController: UIViewController {
lazy var tableView: UITableView = {
let tableView = UITableView(forAutoLayout: ())
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .SingleLine
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Default")
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Indicator")
tableView.tableFooterView = UIView()
return tableView
}()
private var data: [Int] = [Int]()
private var isIndicatorRowAddedInSection: Bool = false
private var lastIndicatorRowIndexPath: NSIndexPath?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero, excludingEdge: .Top)
self.tableView.autoPinEdgeToSuperviewEdge(.Top, withInset: 40)
for index in 0..<5 {
data.append(index)
}
self.tableView.editing = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
let itemToMove = self.data[fromIndexPath.row]
self.data.removeAtIndex(fromIndexPath.row)
self.data.insert(itemToMove, atIndex: toIndexPath.row - 1)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Need to delete a row on section \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
self.lastIndicatorRowIndexPath = nil
tableView.beginUpdates()
// Need to put some logic if you pull to top it has to be + 1
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: lastIndexPath.row - 1, inSection: 0)], withRowAnimation: .Fade)
tableView.endUpdates()
}
})
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return .None
}
func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath,
toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
if let lastIndexPath = self.lastIndicatorRowIndexPath {
print("Target indexpath indexpath to delete row \(lastIndexPath.section) row \(lastIndexPath.row)")
self.isIndicatorRowAddedInSection = false
tableView.beginUpdates()
tableView.deleteRowsAtIndexPaths([lastIndexPath], withRowAnimation: .None)
tableView.endUpdates()
self.lastIndicatorRowIndexPath = nil
}
self.isIndicatorRowAddedInSection = true
self.lastIndicatorRowIndexPath = proposedDestinationIndexPath
tableView.beginUpdates()
print("Indicator view inserted at section \(proposedDestinationIndexPath.section) row \(proposedDestinationIndexPath.row)")
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: proposedDestinationIndexPath.row, inSection: proposedDestinationIndexPath.section)], withRowAnimation: .Automatic)
tableView.endUpdates()
return proposedDestinationIndexPath
}
}
extension ViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.isIndicatorRowAddedInSection {
return self.data.count + 1
}
return self.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let indicatorIndexPath = self.lastIndicatorRowIndexPath where isIndicatorRowAddedInSection {
if indicatorIndexPath.section == indexPath.section && indicatorIndexPath.row == indexPath.row {
let cell = tableView.dequeueReusableCellWithIdentifier("Indicator", forIndexPath: indexPath)
cell.textLabel?.text = "IndicatorView: ROW \(indexPath.row) SECTION = \(indexPath.section)"
print("Indictorview cell for row")
return cell
}
}
let cell = tableView.dequeueReusableCellWithIdentifier("Default", forIndexPath: indexPath)
cell.textLabel?.text = "ROW = \(indexPath.row) SECTION = \(indexPath.section)"
return cell
}
}