2017-08-21 9 views
0

tableViewcellForRowAtIndexPathはそうのようになります。テーブルビュー内の行を削除sender.tagを使用している間

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: CheckoutAppointmentCell.reuseIdentifier) as! CheckoutAppointmentCell 
    cell.appointment = appointments[indexPath.row] 
    cell.checkoutButton.tag = indexPath.row 
    cell.checkoutButton.addTarget(self, action: #selector(checkoutButtonTapped), for: .touchUpInside) 
    return cell 
} 

そして私はそうのようなtableViewdataSourceから予定を削除します。

func checkoutButtonTapped(sender: UIButton) { 
    appointments.remove(at: sender.tag) 
    print(sender.tag) 
    //self.tableView.beginUpdates() 
    self.tableView.deleteRows(at: [IndexPath(row:sender.tag, section: 0)], with: .automatic) 
    //self.tableView.endUpdates() 
} 

初めて私は予定を削除し、それは正常に動作します。 sender.tag値は正しい値で、正しい行はtableViewから削除されます。

最初の行を削除した後に、間違った行が削除されたように見えます。

deleteRowsを呼び出した後、私はreloadData()を呼び出してみましたが、アニメーションはもう発生しません。 beginUpdates()endUpdates()でも違いはないようです。

+1

この行が実際に意味するもの:最初の行を削除した後、間違った行が削除されたようです。後で何をするのか少し説明できますか? –

+0

したがって、 'checkoutButton'をタップすると、' checkoutButtonTapped'が呼び出されます。 'sender.tag'は行を最初に削除したときの正しい値です。たとえば、2行目のcheckoutButtonをタップすると、sender.tagは2になり、テーブルビューから2行目が削除されます。最初の削除後、sender.tagは正しい値ではなくなりました。たとえば、3行目と対話するかもしれませんが、 'sender.tag'値は4行目になります。 – luke

+0

タグを使ってインデックスパスを表現しないでください。ここで見てきたように、テーブルビューで行を削除、挿入、または移動すると、残りのすべての行に間違ったインデックスパスタグが残ります。 – rmaddy

答えて

3

タグを使用してインデックスパスを追跡することは一般的ですが、非常に貧弱な方法です。 reloadDataを使用してテーブルビューが完全に再ロードされない限り、残りのセルに無効なタグがあるため、行を削除、挿入、または移動できるようにするテーブルビューでは失敗します。

reloadDataを使用しなくても、タグを最新の状態に保つより良いソリューションは、ボタンの位置に基づいてセルのボタンのindexPathを特定することです。

func checkoutButtonTapped(sender: UIButton) { 
    let hitPoint = sender.convert(CGPoint.zero, to: tableView) 
    if let indexPath = tableView.indexPathForRow(at: hitPoint) { 
     // use indexPath to get needed data 
    } 
} 
+0

'hitPoint'は型が' CGPoint'型です。オートコンプリートから 'indexPathForRow(at:point:)'が見つかりました。私はそれがこれであることを意味していると思いますか? – luke

+0

それはタイプミスでした。回答は修正されました。 – rmaddy

0

タグを使用することは良いアイデアではないだけでなく、私はそれは良い考えであるかどうかわかりませんが、それはまたCallBack Closuresを使用して正常に動作するようです。

@rmaddyによって提案されたいくつかの点で私はそれに応じて答えを更新しました。

CustomCellクラス - :

import UIKit 

class testingCell: UITableViewCell { 

    var deleteCallBack : ((testingCell)->())?// CallBack function 

    @IBOutlet weak var parentlabel: UILabel! 

    @IBAction func deleteButton(_ sender: UIButton) { 
     // Call your closure 
     if let callBack = deleteCallBack{ 
      callBack(self) 
     } 
    } 
    override func awakeFromNib() { 
     super.awakeFromNib() 
     // Initialization code 
    } 

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

     // Configure the view for the selected state 
    } 

} 

コントローラクラス - は:

extension ViewController : UITableViewDelegate,UITableViewDataSource{ 

func numberOfSections(in tableView: UITableView) -> Int { 
    return 1 
}// Default is 1 if not implemented 

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ 
    // return number of rows in section 
    return data.count 
} 


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! testingCell 
    cell.textLabel?.text = data[indexPath.row] 

    cell.deleteCallBack = { [weak self] tableCell in 
     //Print indexPath for selected Cell 
     print(self?.dataTableView.indexPath(for: tableCell) as Any) 

     if let selectedIndex = self?.dataTableView.indexPath(for: tableCell) { 
      // Print selected row 
      print(selectedIndex.row) 
      // delete row from array 
      self?.data.remove(at: selectedIndex.row) 
      // Get index row to be deleted from table 
      let indePath = NSIndexPath(item: selectedIndex.row, section: selectedIndex.section) 
      // delete row from table 
      self?.dataTableView.deleteRows(at: [indePath as IndexPath], with: UITableViewRowAnimation.automatic) 
     } 

    } 
    return cell 
} 


public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{ 
    // Return cell height 
    return 100 
} 

それは確かに削除後、正しいインデックスをプリントアウトされます。

+0

1. 'deleteCallBack'の展開を強制しないでください。アプリが設定されていないとクラッシュします。 2.コールバックへの引数としてセルを渡す必要があります。 3。ある行を削除するために 'reloadData'を呼び出さないでください。 – rmaddy

+0

@rmaddyありがとう私はあなたの意見を持って、私は答えを更新します。 –

関連する問題