2016-05-27 13 views
0

並べ替えのインジケーターを作成しようとしています。だから私がしようとしているのは、ユーザーがセルをドラッグしているときです。ユーザーがセルをドロップしたい場所では、他のセルにバックグラウンドが追加されます。私はすでにそれを達成しました。しかし、ユーザーがセルをドロップすると、インジケーターセルを削除する必要があり、ユーザーが意図したように表が同じままでなければなりません。並べ替えの後にセルが別のセルの後ろにある

今私は以下の問題があります。ユーザーがセルをドロップしたとき。インジケータセルは正しく削除されますが、ドロップされたセルは別のセルの後ろに突然あります。

明確にするスクリーンショット:

Begin state End state View hierarchy in xcode in endstate

マイコード:

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 

    } 
} 

私は、問題が表示されません。誰か助けてくれますか?

+1

私はまだ問題が表示されていない - なぜ細胞のビューの順序は重要ではありませんか?あなたのアプリケーションに悪影響を及ぼしますか? – luk2302

+0

これは数字の例として作成されましたが、実際のデータセットは異なります。ユーザーは並べ替えができ、その注文はバックエンドに保存されます。しかし、私が知っている唯一の問題は、ドロップされたセルが別のセルの後ろにあることだけです。 – user1007522

答えて

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 

    } 
} 
関連する問題