Skip to content

IMPORTANT: Here are some of the changes in version 7+. It will cause some code breaks. #553

@patchthecode

Description

@patchthecode

TLDR

  1. Please implement the willDisplayCell function as stated below.
  2. Do not use cell.isSelected I will be removing it. Instead use cellState.isSelected

.

Problem 1: UICollectionView cell pre-fetching enables your calendar to scroll smoothly. But some problems arise.

A case can arise where a cell is already pre-fetched, but is still not yet visible on the screen.
screen shot 2017-09-08 at 2 32 29 pm

In a case like this, lets say a user selects the Feb1 outDate.
screen shot 2017-09-08 at 2 32 29 pm

Then the Feb1st inDate on the other month has to also be updated to show a selection.
screen shot 2017-09-08 at 2 34 23 pm

Now If the cell is already prefetched, but still invisible, there is no way for JTAppleCalendar library to send you an instance of the already prefetched cell so that it can be updated.
The way I handled this in version 7.0.6 was to call reloadIndexPaths, but this invalidates the layout. In order to save the layout much code was done which caused subtle bugs to form.

According to Apple documentation ,

To avoid inconsistencies in the visual appearance, use the
collectionView:willDisplayCell:forItemAtIndexPath:
delegate method to update the cell to reflect visual state such as selection.

Therefore, in the 7.1.0 version of JTAppleCalendar, i'll be forcing you developers to implement this willDisplay function sadly. I did not want to do this because I think implementing 2 functions with the same code is silly, but it seems that I was coding against the grain. The contents of this function will be exactly the same as the code located in the cellForItemAtIndex function (except the cell dequeuing part). Therefore in order to avoid code duplication, you can create a common function that is run by both those functions.

If a developer can show me how to invalidate an already prefetched, but still hidden cell in a UICollectionView, then we would not have to do this.

Here is an example of what you developers should do when implementing this with a shared function to reduce code:

    func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
        // This function should have the same code as the cellForItemAt function
        let myCustomCell = cell as! CellView
        sharedFunctionToConfigureCell(myCustomCell: myCustomCell, cellState: cellState, date: date)
    }
    
    func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
        let myCustomCell = calendar.dequeueReusableCell(withReuseIdentifier: "CellView", for: indexPath) as! CellView
        sharedFunctionToConfigureCell(myCustomCell: myCustomCell, cellState: cellState, date: date)
        return myCustomCell
    }

    func sharedFunctionToConfigureCell(myCustomCell: CellView, cellState: CellState, date: Date) {
        myCustomCell.dayLabel.text = cellState.text
        if testCalendar.isDateInToday(date) {
            myCustomCell.backgroundColor = red
        } else {
            myCustomCell.backgroundColor = white
        }
        // more code configurations
        // ...
        // ...
        // ...
    }

OR as developer @boborbt mentioned below, you can just do all you setup inside the willDisplayCell function. And for your cellForIndexPath function, simply do this

func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
    let myCustomCell = calendar.dequeueReusableCell(withReuseIdentifier: "CellView", for: indexPath) as! CellView
    self.calendar(calendar, willDisplay: myCustomCell, forItemAt: date, cellState: cellState, indexPath: indexPath)
    return myCustomCell
}

Problem 2: UICollectionViewCell.isSelected may be out of sync.

I am thinking on removing the property of isSelected on a cell as it can incorrect.
In the library if the calendar is in single selection mode, if a user selects say Feb1, then I also cause its outDate counter part to be selected.

screen shot 2017-09-08 at 2 34 23 pm

Here 2 cells will be "selected" even though it is on single selection. I track this magic with the CellState struct. Therefore cellState.isSelected will always give you a correct value. But developers are used to using the Cell.isSelected property. And this causes confusion when a cell that is supposed to be selected gives an incorrect value.

Therefore I am going to make the Cell.isSelected property unavailable unless a developer can come up with a good alternative solution. Else, Users should only use the cellState inorder to determine if a cell is selected or not.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions