patchthecode / JTAppleCalendar

The Unofficial Apple iOS Swift Calendar View. Swift calendar Library. iOS calendar Control. 100% Customizable
https://patchthecode.com
MIT License
7.55k stars 806 forks source link

wrong date retuned with gesture recognition. #1276

Open alexvaiman opened 4 years ago

alexvaiman commented 4 years ago

let cellState = calendarView.cellStatus(at: gesture.location(in: gesture.view!)) cellState.date, will always return the first section month, instead of the real month.

*I can see now that this is long time issue.. https://github.com/patchthecode/JTAppleCalendar/issues/253#issuecomment-439784680

alexvaiman commented 4 years ago

the code used.

 longPressGesture.minimumPressDuration = 1    // User has the flexibility to set the time
        calendarView.addGestureRecognizer(longPressGesture)
        self.addGestureRecognizer(longPressGesture)
@objc private func didStartLongPressing(gesture: UILongPressGestureRecognizer) {
        if gesture.state == .began {
            if let cellState = calendarView.cellStatus(at: gesture.location(in: gesture.view!)) {

                let dateType = cellState.date.getDateType(ranges: self.savedDatesRanges)
                if dateType.case != .none {
                    return
                }

                self.unsavedRange = PrivateCalendarRange(startDate: cellState.date, endDate: cellState.date)
                firstUserSelectedDate = nil
                secondUserSelectedDate = nil
                calendarView.deselectAllDates()
                calendarView.selectDates([cellState.date], triggerSelectionDelegate: false, keepSelectionIfMultiSelectionAllowed: true)
            }
        }
    }
alexvaiman commented 4 years ago

for me this is a very important thing - as in my implementation, long click on a date meaning the user wants this date as a "single date range"

alexvaiman commented 4 years ago

ok i can see the problem

   public func cellStatus(at point: CGPoint) -> CellState? {
        if let indexPath = indexPathForItem(at: point) {
            let cell = cellForItem(at: indexPath) as? JTACDayCell
            return cellStateFromIndexPath(indexPath, cell: cell)
        }
        return nil
    }

this function does not take the current month into the account what so ever... i will fix this. (i hope this will be fast...)

alexvaiman commented 4 years ago

ok it was actually easy

    public func cellStatus(at point: CGPoint) -> CellState? {
        guard let indexPath = indexPathForItem(at: point) else {
            return nil
        }

        let i = indexPath.item
        let row =  i / maxNumberOfDaysInWeek
        let col = i % maxNumberOfDaysInWeek
        return cellStatusForDate(at: row, column: col)
    }
alexvaiman commented 4 years ago

you are welcome to upload this fix in the next version

patchthecode commented 4 years ago

Can you let me know what date you are expecting, and what date you are receiving? Is it an off by 1 date error?

alexvaiman commented 4 years ago

"Can you let me know what date you are expecting, and what date you are receiving? Is it an off by 1 date error?"

I am expecting the day i am pressing on utc-0, start of day. I get totally wrong result - the offset depends on the month, each month farther from the calendar start date, the offset is bigger - but I have already fixed the issue - and sent a pull request.

alexvaiman commented 4 years ago

for me my solution works - it gives me the correct date, but the cellState.cell is still nil. I dont care about cell, at this stage. (I will handle the ui on shouldSelect if needed)

the problem is: let cell = cellForItem(at: indexPath) as? JTACDayCell will return nil - in any section other then section 0 (start month of the calendar). maybe later I will fix this as well. for now at least you get the correct statusCell info.

alexvaiman commented 4 years ago

ok i solved this as well.

 public func cellStatus(at point: CGPoint) -> CellState? {
        guard let indexPath = indexPathForItem(at: point) else {
            return nil
        }

        guard let section = currentSection() else {
            return nil
        }

        let i = indexPath.item
        let row =  i / maxNumberOfDaysInWeek
        let column = i % maxNumberOfDaysInWeek
        let convertedRow = (row * maxNumberOfDaysInWeek) + column
        let indexPathToFind = IndexPath(item: convertedRow, section: section)

        if let date = dateOwnerInfoFromPath(indexPathToFind) {
            let cell = cellForItem(at: indexPathToFind) as? JTACDayCell
            let stateOfCell = cellStateFromIndexPath(indexPathToFind, withDateInfo: date,cell: cell)
            return stateOfCell
        }

        return nil
    }
alexvaiman commented 4 years ago

also added new function, for those who care only for the cell data. (like my case of use)

 public func cellStatusForDate(at point: CGPoint) -> CellState? {
        guard let indexPath = indexPathForItem(at: point) else {
            return nil
        }

        return cellStatusForDate(at: indexPath.item / maxNumberOfDaysInWeek , column: indexPath.item % maxNumberOfDaysInWeek)
    }
patchthecode commented 4 years ago

leave open. i'll take a loo once i get the chance.

alexvaiman commented 4 years ago

no problem sorry.

alexvaiman commented 2 years ago

i am still using my fork, more then a year.. no new version?)

patchthecode commented 2 years ago

time is short these days. But i thought i had fixed this.

Can you tell me if the tutorial here fixes your issue? https://patchthecode.com/jtapplecalendar-home/ranged-selection/

patchthecode commented 2 years ago

It has code in there for getting the point of the gesture. Scroll down to the Dragging your finger to Ranged Selection section.

patchthecode commented 2 years ago

Or do you have a discord address? typing here is a bit slow.