9

我正在尝试在我的一个项目中使用FSCalendar来选择日期范围。

我发现这个库有 Swift 版本,但是范围选择版本仅适用于 Objective-C。所以我试图做的是使用桥接,但是我无法在 Swift 中使用RangePickerViewController

有没有人为 Swift 实现了这个库来使用日期范围?(例如,我想选择 2 个日期作为航班应用程序的范围,其中我选择了出发和返回航班日期。)

4

3 回答 3

32

虽然 FSCalendar 不直接支持范围选择,但它确实允许多选,这意味着在某些时候您可以自己处理范围选择。

因此,viewDidLoad()您必须确保将 calendarallowsMultipleSelection属性设置为true

private weak var calendar: FSCalendar!

override func viewDidLoad() {
    super.viewDidLoad()

    calendar.allowsMultipleSelection = true
}

视图控制器应符合FSCalendarDelegate处理选择/取消选择范围的逻辑的协议。

到目前为止,我们需要的是声明范围的两个日期(起始日期和结束日期):

// first date in the range
private var firstDate: Date?
// last date in the range
private var lastDate: Date?

firstDate还有一个日期数组,用于在和之间保存值日期lastDate

private var datesRange: [Date]?

然后将didSelect datedidDeselect date委托方法实现为:

func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
    // nothing selected:
    if firstDate == nil {
        firstDate = date
        datesRange = [firstDate!]

        print("datesRange contains: \(datesRange!)")

        return
    }

    // only first date is selected:
    if firstDate != nil && lastDate == nil {
        // handle the case of if the last date is less than the first date:
        if date <= firstDate! {
            calendar.deselect(firstDate!)
            firstDate = date
            datesRange = [firstDate!]

            print("datesRange contains: \(datesRange!)")

            return
        }

        let range = datesRange(from: firstDate!, to: date)

        lastDate = range.last

        for d in range {
            calendar.select(d)
        }

        datesRange = range

        print("datesRange contains: \(datesRange!)")

        return
    }

    // both are selected:
    if firstDate != nil && lastDate != nil {
        for d in calendar.selectedDates {
            calendar.deselect(d)
        }

        lastDate = nil
        firstDate = nil

        datesRange = []

        print("datesRange contains: \(datesRange!)")
    }
}

func calendar(_ calendar: FSCalendar, didDeselect date: Date, at monthPosition: FSCalendarMonthPosition) {
    // both are selected:

    // NOTE: the is a REDUANDENT CODE:
    if firstDate != nil && lastDate != nil {
        for d in calendar.selectedDates {
            calendar.deselect(d)
        }

        lastDate = nil
        firstDate = nil

        datesRange = []
        print("datesRange contains: \(datesRange!)")
    }
}

datesRange方法呢?

我没有在我的答案中提到它以使其更短,您所要做的就是从这个答案中复制粘贴它。

输出:

在此处输入图像描述

于 2018-04-17T07:09:01.197 回答
3

你好,这是我的方法。

class CalendarDelegate: NSObject, FSCalendarDelegate {

func calendar(_ calendar: FSCalendar, shouldDeselect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
    performDateDeselect(calendar, date: date)
    return true
}

func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
    performDateSelection(calendar)
}

private func performDateDeselect(_ calendar: FSCalendar, date: Date) {
    let sorted = calendar.selectedDates.sorted { $0 < $1 }
    if let index = sorted.firstIndex(of: date)  {
        let deselectDates = Array(sorted[index...])
        calendar.deselectDates(deselectDates)
    }
}

private func performDateSelection(_ calendar: FSCalendar) {
    let sorted = calendar.selectedDates.sorted { $0 < $1 }
    if let firstDate = sorted.first, let lastDate = sorted.last {
        let ranges = datesRange(from: firstDate, to: lastDate)
        calendar.selectDates(ranges)
    }
}

func datesRange(from: Date, to: Date) -> [Date] {
    if from > to { return [Date]() }
    var tempDate = from
    var array = [tempDate]
    while tempDate < to {
        tempDate = Calendar.current.date(byAdding: .day, value: 1, to: tempDate)!
        array.append(tempDate)
    }
    return array
}

}

于 2020-01-27T18:07:12.950 回答
0

我将@Ahmed F 的代码转换为Objective C。

创建以下变量

NSDate *firstDate;
NSDate *lastDate;
NSMutableArray *datesRange;

在 viewDidLoad 中添加以下行

datesRange = [NSMutableArray array];
calendar.allowsMultipleSelection = YES;

FSCalendar 和函数

- (NSArray <NSDate *> *)datesRange:(NSDate *)from andTo:(NSDate *)to {
    if([from isLaterThan:to]) {
        return [NSArray array];
    }
    NSDate *tempDate = from;
    NSMutableArray <NSDate *> *arrDates = [NSMutableArray array];
    [arrDates addObject:tempDate];
    NSDateComponents *component = [[NSDateComponents  alloc] init];
    component.day = 1;
    while ([tempDate isEarlierThan:to]) {
        tempDate  = [[NSCalendar currentCalendar] dateByAddingComponents:component toDate:tempDate options:0];
        [arrDates addObject:tempDate];
    }
    return [NSArray arrayWithArray:arrDates];
}

- (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition {
    if (firstDate == nil) {
        firstDate = date;
        datesRange = [NSMutableArray arrayWithObject:firstDate];
        return;
    }
    
    if(firstDate != nil && lastDate == nil) {
        if ([date isEarlierThan:firstDate]) {
            [calendar deselectDate:firstDate];
            firstDate = date;
            datesRange = [NSMutableArray arrayWithObject:firstDate];
            return;
        }
        
        NSArray<NSDate *> *range = [self datesRange:firstDate andTo:date];
        lastDate = [range lastObject];
        
        for (NSDate *d in range) {
            [calendar selectDate:d];
        }
        datesRange = [NSMutableArray arrayWithArray:range];
        return;
    }
    
    if (firstDate != nil && lastDate != nil) {
        for (NSDate *d in calendar.selectedDates) {
            [calendar deselectDate:d];
        }
        lastDate = nil;
        firstDate = nil;
        [datesRange removeAllObjects];
    }
}

- (void)calendar:(FSCalendar *)calendar didDeselectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition {
    if (firstDate != nil && lastDate != nil) {
        for (NSDate *d in calendar.selectedDates) {
            [calendar deselectDate:d];
        }
        lastDate = nil;
        firstDate = nil;
        [datesRange removeAllObjects];
    }
}
于 2021-08-10T13:29:57.317 回答