1

enter image description here

Problem is when I am scrolling the tableview after selecting a collectionViewCell (violet color on date 28). Few CollectionViewCells at the bottom of tableview appears to be selected (Here CollectionView is present inside TableView).

Code is like this :

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)
    }

}

Let me know if i need to add anything else.

Shivam Tripathi
  • 1,405
  • 3
  • 19
  • 37
  • 1
    Your code doesn't make sense. Why would you remove the content view from the cell? Don't do that whatever your reason. Elaborate what you are trying to achieve. I'm pretty sure there are cleaners ways to do it. – Desdenova Jul 25 '18 at 08:44
  • Absolutely crazy code. You need just to change background color. – oxigen Jul 25 '18 at 08:51
  • @Desdenova I removed it. I did that while trying to solve the issue but nothing happened by trying that. Let me know what are the ways in which i can resolve the issue. – Shivam Tripathi Jul 25 '18 at 10:18

3 Answers3

1

This is not the recommended way of working with JTAppleCalendar CollectionView. You have to store the dates selected in some datasource variable and when a cell is Selected/Deselected. On reload, based on this stored values, you have to highlight the cell accordingly.

//This will store the selected dates against the cell rows.
var selectedDatesVsIndex = [Int : Date]()

On select/ deselect methods of JTAppleCalendar delegate, add the selected dates to the localDictionary which maintains rowIndex -> DateSelected.

   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)
    }

Apart from that, I set the tag as indexpath.row in TableViewCells.Also add reload method of collection view. Like this

 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
    }

The cell customization to show selected background color should be done in 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
    }

Please remove other clutter methods like

 override func prepareForReuse() {
        super.prepareForReuse()

//        let hasContentView = self.subviews .contains(self.contentView)
//        if(hasContentView){
//            self.contentView.removeFromSuperview()
//        }
    }
Jen Jose
  • 3,995
  • 2
  • 19
  • 36
0

Please check for value at particular indexpath is present or not.if value present the make that as selected it will remove your overlapping problem

-1

Just change color in (cellForRowAt indexPath: IndexPath) method instead of handleCellSelection(view: JTAppleCell?, cellState: CellState)

Like This :-

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
 }

And make code to get cell selected on didSelect method.

  • This Code is Using a library named "JTAppleCalender" and all the methods are related with this library. Here u wont get indexpath in DidSelect() method. So the method used are proper and according to the requirement. – Shivam Tripathi Jul 25 '18 at 11:15