2017-02-11 176 views
0

我有一个自定义的UITableView与部分中的单元格而不是行,总共5个单元格。每个单元格都有一个按钮,我希望第五个单元格按钮(tableButton)具有与其他标题不同的标题。Swift:意外的结果cellForRowAtIndexPath

这一切都工作正常,我有下面的代码,前4个单元格最初有正确的标题为每个代码。但是,当我向下滚动第5个单元格(其具有期望的标题),然后向后滚动到第一个单元格时,第一个单元格现在已经变为标题,以专用于第五个单元格。

我在if cell.tableButton.tag == 4条件中添加了打印语句,每次向下滚动到第五个单元格时都会打印它。

import UIKit 
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 

    @IBOutlet weak var tableView: UITableView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     tableView.delegate = self 
     tableView.dataSource = self 
    } 

    func numberOfSections(in tableView: UITableView) -> Int { 
     // #warning Incomplete implementation, return the number of sections 
     return 5 
    } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     // #warning Incomplete implementation, return the number of rows 
     return 1 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell 
     cell.layer.borderWidth = 1 
     cell.layer.borderColor = UIColor.gray.cgColor 

     cell.tableButton.tag = indexPath.section 
     if indexPath.section == 4 { 
      cell.tableTitle.isHidden = true 
      cell.tableButton.setTitle("Special", for: .normal) 
     } else { 
      cell.tableButton.setTitle("Normal", for: .normal) 
     } 

     return cell 
    } 


    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 
     let returnedView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: 15)) 
     returnedView.backgroundColor = UIColor.groupTableViewBackground 

     return returnedView 
    } 

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 
     return 15 
    } 
} 

CustomCell.swift:

import UIKit 
class CustomCell: UITableViewCell { 

    @IBOutlet weak var tableButton: UIButton! 
    @IBOutlet weak var tableTitle: UILabel! 

    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 
    } 

} 
+1

也许细胞的状态已经改变。在所有情况下用'[]'替换'.normal' – penatheboss

+0

你有5个单元,5个单元? – iAviator

+0

5个部分,每个1个细胞,共5个细胞。 –

回答

0

我想这是因为你使用的是dequeReusableCell方法。既然你在tableview中只有5个单元格,我认为如果你不再让单元格变为单元格,它不会损害你,而是每次创建一个你的单元格的新实例。这不是最佳做法,但它是一个简单的解决方案!

+1

这不是一个好方法......因为它会累积内存使用量。 – iAviator

+0

那么他也可以使用'prepareForReuse'方法,但由于他的tableview中的单元格数量是静态的,并且它只有5个单元格,所以对他来说这样更简单的解决方案而不会造成太大的伤害。 –

+0

他不应该使用'prepareForReuse'来设置单元格内容。该委托方法不是为了这个。 'tableView(_:cellForRowAt:)'中的表视图委托应该在重用单元时_always_重置所有内容。 –

0

我重新创建了你的场景,但是我没有让它工作的问题。我想这可能与CustomCell中的某些内容有关。

ViewController.swift:

import UIKit 

class ViewController: UIViewController { 
    @IBOutlet weak var tableView: UITableView! 
} 

extension ViewController: UITableViewDataSource { 

    func numberOfSections(in tableView: UITableView) -> Int { 
     return 5 
    } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return 1 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell 

     if indexPath.section == 4 { 
      cell.tableButton.setTitle("Special", for: .normal) 
     } else { 
      cell.tableButton.setTitle("Normal", for: .normal) 
     } 

     return cell 
    } 

} 

extension ViewController: UITableViewDelegate { 
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
     return 250 
    } 
} 

CustomCell.swift:

import UIKit 

class CustomCell: UITableViewCell { 

    @IBOutlet weak var tableButton: UIButton! 

    override func prepareForReuse() { 
     tableButton.setTitle("RESET", for: .normal) 
    }  
} 

当然,这种简化的实施UITableView,但增加更多的代码来的例子也许其他人可以看到或重新创建你的问题。

+0

如果我添加了两个不同的动作(一个用于“特殊”按钮,另一个用于称为specialAction和normalAction的“Normal”按钮),如何使用prepareForResuse使单元格像第一个单元格一致时那样工作两个行动! –

+0

不要担心我已经修复了它,我将prepareForReuse中的按钮从目标中删除了! –

+0

“PrepareForReuse”方法意味着将单元重置为适合重用的状态,而不是用于设置新数据。如果在最坏的情况下,你的单元格仍然行为不正确,你可以在'UITableView'的'willDisplayCell'委托方法中设置单元格的内容。对不起,回复晚了,_life_介于两者之间;) –

0

这看起来像一个细胞再利用的问题,因为你是用tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

重用你的细胞,在这里你有几种解决方案。首先是不重复使用并创建一个新的,但是这样做会影响性能,因为会使用更多的内存。

更好的解决方案是准备在tableViewCell中重用。您应该在自定义tableViewCell中覆盖方法prepareForReuse。在该方法中,将视图设置为初始状态(文本,alpha等)。请记得先拨打super.prepareForReuse

+0

这是一个非常好的方法来使用'prepareForReuse',但是这和_should_不是一个先决条件来实现它。 'UITableViewDelegate'应该调用'CellForRowAtIndexPath',它依次得到单元格(新的或者出列的)并且会改变'tableButton'的值。 –

+0

谢谢,此方法用于重置按钮标题。这怎么可能也用于按钮动作?如果我给“特殊”按钮一个不同于其他操作的操作,那么第一个单元实际上同时执行正常操作和特殊操作。 –

+0

你是如何设置按钮的动作?它在代码中不可见 –