重置 UITableViewCell 无法正常工作/未选择的单元格在滚动后显示为选中
Resetting UITableViewCell Not working properly / Unselected Cells appears selected after scrolling
问题是当我在选择 collectionViewCell(日期 28 上的紫色)后滚动 tableview 时。 tableview 底部的几个 CollectionViewCells 似乎被选中(这里 CollectionView 存在于 TableView 内部)。
代码是这样的:
class ViewController: UIViewController {
@IBOutlet weak var tblView: UITableView!
var storedOffsets = [Int: CGFloat]() // Will be used by JTAppleCalender
let formatter = DateFormatter() // NSDateFormatter
override func viewDidLoad() {
super.viewDidLoad()
self.tblView.delegate = self
self.tblView.dataSource = self
self.tblView.reloadData()
}
func handleCellConfiguration(cell: JTAppleCell?, cellState: CellState) {
handleCellSelection(view: cell, cellState: cellState)
}
func handleCellSelection(view: JTAppleCell?, cellState: CellState) {
guard let myCustomCell = view as? CalenderCell else {return }
if cellState.isSelected {
myCustomCell.contentView.layer.cornerRadius = 10
myCustomCell.contentView.backgroundColor = UIColor.init(red: 0.26, green: 0.10, blue: 0.39, alpha: 1.0)
} else {
myCustomCell.contentView.layer.cornerRadius = 0
myCustomCell.contentView.backgroundColor = UIColor.clear
}
}
}
UITableViewCell :
class TableCell: UITableViewCell{
@IBOutlet weak var lbldate: UILabel!
@IBOutlet weak var collectionViewDate: JTAppleCalendarView!
override func prepareForReuse() {
super.prepareForReuse()
}
}
extension TableCell {
func setCollectionViewDataSourceDelegate<D: JTAppleCalendarViewDataSource & JTAppleCalendarViewDelegate>(_ dataSourceDelegate: D, forRow row: Int) {
collectionViewDate.calendarDelegate = dataSourceDelegate
collectionViewDate.calendarDataSource = dataSourceDelegate
collectionViewDate.tag = row
collectionViewDate.setContentOffset(collectionViewDate.contentOffset, animated:false)
collectionViewDate.reloadData()
}
var collectionViewOffset: CGFloat {
set { collectionViewDate.contentOffset.x = newValue }
get { return collectionViewDate.contentOffset.x }
}
}
extension ViewController : UITableViewDataSource, UITableViewDelegate{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tblView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
cell.lbldate.text = "date "+"\(indexPath.row)"
return cell
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? TableCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? TableCell else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
}
class CalenderCell: JTAppleCell{
@IBOutlet weak var lblDate: UILabel!
}
extension ViewController: JTAppleCalendarViewDataSource , JTAppleCalendarViewDelegate {
func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
let myCustomCell = cell as! CalenderCell
sharedFunctionToConfigureCell(myCustomCell: myCustomCell, cellState: cellState, date: date)
}
func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "CalenderCell", for: indexPath) as! CalenderCell
cell.lblDate.text = cellState.text
self.calendar(calendar, willDisplay: cell, forItemAt: date, cellState: cellState, indexPath: indexPath)
return cell
}
func calendar(_ calendar: JTAppleCalendarView, didDeselectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
handleCellConfiguration(cell: cell, cellState: cellState)
}
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
handleCellConfiguration(cell: cell, cellState: cellState)
}
func sharedFunctionToConfigureCell(myCustomCell: CalenderCell, cellState: CellState, date: Date) {
handleCellConfiguration(cell: myCustomCell, cellState: cellState)
}
func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
let currentDate = Date()
let endDate = Calendar.current.date(byAdding: .month, value: 4, to: Date())
let parameters = ConfigurationParameters(startDate: currentDate,
endDate: endDate!,
numberOfRows: 1,
generateInDates: .forFirstMonthOnly,
generateOutDates: .off,
hasStrictBoundaries: false)
calendar.scrollToDate(currentDate, triggerScrollToDateDelegate: false, animateScroll: false)
return parameters
}
func configureVisibleCell(myCustomCell: CalenderCell, cellState: CellState, date: Date) {
handleCellConfiguration(cell: myCustomCell, cellState: cellState)
}
}
如果我需要添加任何其他内容,请告诉我。
请检查特定索引路径处的值是否存在,或者 not.if 值是否存在所选择的品牌将消除您的重叠问题
只需在 (cellForRowAt indexPath: IndexPath) 方法中更改颜色,而不是 handleCellSelection(view: JTAppleCell?, cellState: CellState)
像这样:-
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tblView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
cell.lbldate.text = "date "+"\(indexPath.row)"
if cell.isSelected == true
{
cell.contentView.layer.cornerRadius = 10
cell.contentView.backgroundColor = UIColor.init(red: 0.26, green: 0.10, blue: 0.39, alpha: 1.0)
}
else
{
cell.contentView.layer.cornerRadius = 0
cell.contentView.backgroundColor = UIColor.clear
}
return cell
}
并编写代码以在 didSelect 方法上选择单元格。
这不是使用 JTAppleCalendar CollectionView 的推荐方式。
您必须将日期 selected 存储在某个数据源变量中以及单元格何时为 Selected/Deselected。重新加载时,根据此存储值,您必须相应地突出显示单元格。
//This will store the selected dates against the cell rows.
var selectedDatesVsIndex = [Int : Date]()
在 JTAppleCalendar 委托的 select/ deselect 方法上,将 selected 日期添加到维护 rowIndex -> DateSelected 的 localDictionary。
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
cell?.isSelected = true
selectedDatesVsIndex.merge([calendar.tag : date]) { (d1, d2) -> Date in return d1 }
calendar.reloadData()
// handleCellConfiguration(cell: cell, cellState: cellState)
}
func calendar(_ calendar: JTAppleCalendarView, didDeselectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
cell?.isSelected = false
selectedDatesVsIndex.removeValue(forKey: calendar.tag)
calendar.reloadData()
// handleCellConfiguration(cell: cell, cellState: cellState)
}
除此之外,我在 TableViewCells.Also 中将标签设置为 indexpath.row 添加集合视图的重新加载方法。像这样
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tblView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
cell.tag = indexPath.row
cell.collectionViewDate.tag = indexPath.row
cell.collectionViewDate.reloadData()
cell.lbldate.text = "date "+"\(indexPath.row)"
return cell
}
显示 selected 背景颜色的单元格自定义应在 CellForRowAt Index 中完成。
func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "CalenderCell", for: indexPath) as! CalenderCell
cell.lblDate.text = cellState.text
cell.backgroundColor = UIColor.clear
if selectedDatesVsIndex.keys.index(of: calendar.tag) != nil {
if let object = selectedDatesVsIndex[calendar.tag] , object.compare(date) == .orderedSame {
cell.backgroundColor = UIColor.gray
}
}
// self.calendar(calendar, willDisplay: cell, forItemAt: date, cellState: cellState, indexPath: indexPath)
return cell
}
请删除其他混乱的方法,例如
override func prepareForReuse() {
super.prepareForReuse()
// let hasContentView = self.subviews .contains(self.contentView)
// if(hasContentView){
// self.contentView.removeFromSuperview()
// }
}
问题是当我在选择 collectionViewCell(日期 28 上的紫色)后滚动 tableview 时。 tableview 底部的几个 CollectionViewCells 似乎被选中(这里 CollectionView 存在于 TableView 内部)。
代码是这样的:
class ViewController: UIViewController {
@IBOutlet weak var tblView: UITableView!
var storedOffsets = [Int: CGFloat]() // Will be used by JTAppleCalender
let formatter = DateFormatter() // NSDateFormatter
override func viewDidLoad() {
super.viewDidLoad()
self.tblView.delegate = self
self.tblView.dataSource = self
self.tblView.reloadData()
}
func handleCellConfiguration(cell: JTAppleCell?, cellState: CellState) {
handleCellSelection(view: cell, cellState: cellState)
}
func handleCellSelection(view: JTAppleCell?, cellState: CellState) {
guard let myCustomCell = view as? CalenderCell else {return }
if cellState.isSelected {
myCustomCell.contentView.layer.cornerRadius = 10
myCustomCell.contentView.backgroundColor = UIColor.init(red: 0.26, green: 0.10, blue: 0.39, alpha: 1.0)
} else {
myCustomCell.contentView.layer.cornerRadius = 0
myCustomCell.contentView.backgroundColor = UIColor.clear
}
}
}
UITableViewCell :
class TableCell: UITableViewCell{
@IBOutlet weak var lbldate: UILabel!
@IBOutlet weak var collectionViewDate: JTAppleCalendarView!
override func prepareForReuse() {
super.prepareForReuse()
}
}
extension TableCell {
func setCollectionViewDataSourceDelegate<D: JTAppleCalendarViewDataSource & JTAppleCalendarViewDelegate>(_ dataSourceDelegate: D, forRow row: Int) {
collectionViewDate.calendarDelegate = dataSourceDelegate
collectionViewDate.calendarDataSource = dataSourceDelegate
collectionViewDate.tag = row
collectionViewDate.setContentOffset(collectionViewDate.contentOffset, animated:false)
collectionViewDate.reloadData()
}
var collectionViewOffset: CGFloat {
set { collectionViewDate.contentOffset.x = newValue }
get { return collectionViewDate.contentOffset.x }
}
}
extension ViewController : UITableViewDataSource, UITableViewDelegate{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tblView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
cell.lbldate.text = "date "+"\(indexPath.row)"
return cell
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? TableCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? TableCell else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
}
class CalenderCell: JTAppleCell{
@IBOutlet weak var lblDate: UILabel!
}
extension ViewController: JTAppleCalendarViewDataSource , JTAppleCalendarViewDelegate {
func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
let myCustomCell = cell as! CalenderCell
sharedFunctionToConfigureCell(myCustomCell: myCustomCell, cellState: cellState, date: date)
}
func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "CalenderCell", for: indexPath) as! CalenderCell
cell.lblDate.text = cellState.text
self.calendar(calendar, willDisplay: cell, forItemAt: date, cellState: cellState, indexPath: indexPath)
return cell
}
func calendar(_ calendar: JTAppleCalendarView, didDeselectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
handleCellConfiguration(cell: cell, cellState: cellState)
}
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
handleCellConfiguration(cell: cell, cellState: cellState)
}
func sharedFunctionToConfigureCell(myCustomCell: CalenderCell, cellState: CellState, date: Date) {
handleCellConfiguration(cell: myCustomCell, cellState: cellState)
}
func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
let currentDate = Date()
let endDate = Calendar.current.date(byAdding: .month, value: 4, to: Date())
let parameters = ConfigurationParameters(startDate: currentDate,
endDate: endDate!,
numberOfRows: 1,
generateInDates: .forFirstMonthOnly,
generateOutDates: .off,
hasStrictBoundaries: false)
calendar.scrollToDate(currentDate, triggerScrollToDateDelegate: false, animateScroll: false)
return parameters
}
func configureVisibleCell(myCustomCell: CalenderCell, cellState: CellState, date: Date) {
handleCellConfiguration(cell: myCustomCell, cellState: cellState)
}
}
如果我需要添加任何其他内容,请告诉我。
请检查特定索引路径处的值是否存在,或者 not.if 值是否存在所选择的品牌将消除您的重叠问题
只需在 (cellForRowAt indexPath: IndexPath) 方法中更改颜色,而不是 handleCellSelection(view: JTAppleCell?, cellState: CellState)
像这样:-
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tblView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
cell.lbldate.text = "date "+"\(indexPath.row)"
if cell.isSelected == true
{
cell.contentView.layer.cornerRadius = 10
cell.contentView.backgroundColor = UIColor.init(red: 0.26, green: 0.10, blue: 0.39, alpha: 1.0)
}
else
{
cell.contentView.layer.cornerRadius = 0
cell.contentView.backgroundColor = UIColor.clear
}
return cell
}
并编写代码以在 didSelect 方法上选择单元格。
这不是使用 JTAppleCalendar CollectionView 的推荐方式。 您必须将日期 selected 存储在某个数据源变量中以及单元格何时为 Selected/Deselected。重新加载时,根据此存储值,您必须相应地突出显示单元格。
//This will store the selected dates against the cell rows.
var selectedDatesVsIndex = [Int : Date]()
在 JTAppleCalendar 委托的 select/ deselect 方法上,将 selected 日期添加到维护 rowIndex -> DateSelected 的 localDictionary。
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
cell?.isSelected = true
selectedDatesVsIndex.merge([calendar.tag : date]) { (d1, d2) -> Date in return d1 }
calendar.reloadData()
// handleCellConfiguration(cell: cell, cellState: cellState)
}
func calendar(_ calendar: JTAppleCalendarView, didDeselectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
cell?.isSelected = false
selectedDatesVsIndex.removeValue(forKey: calendar.tag)
calendar.reloadData()
// handleCellConfiguration(cell: cell, cellState: cellState)
}
除此之外,我在 TableViewCells.Also 中将标签设置为 indexpath.row 添加集合视图的重新加载方法。像这样
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tblView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! TableCell
cell.tag = indexPath.row
cell.collectionViewDate.tag = indexPath.row
cell.collectionViewDate.reloadData()
cell.lbldate.text = "date "+"\(indexPath.row)"
return cell
}
显示 selected 背景颜色的单元格自定义应在 CellForRowAt Index 中完成。
func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "CalenderCell", for: indexPath) as! CalenderCell
cell.lblDate.text = cellState.text
cell.backgroundColor = UIColor.clear
if selectedDatesVsIndex.keys.index(of: calendar.tag) != nil {
if let object = selectedDatesVsIndex[calendar.tag] , object.compare(date) == .orderedSame {
cell.backgroundColor = UIColor.gray
}
}
// self.calendar(calendar, willDisplay: cell, forItemAt: date, cellState: cellState, indexPath: indexPath)
return cell
}
请删除其他混乱的方法,例如
override func prepareForReuse() {
super.prepareForReuse()
// let hasContentView = self.subviews .contains(self.contentView)
// if(hasContentView){
// self.contentView.removeFromSuperview()
// }
}