FSCalendar(Swift 4)技术问题:指定周起始日期及周视图以今日为起点
Hey there! Let's break down your two FSCalendar requirements with practical, code-based solutions — I’ve tinkered with this library a lot, so I know the ins and outs here.
1. Set a Custom Week Start Day
FSCalendar has a built-in property to control which day kicks off the week, and this affects both month and week views directly. Here's how to implement it:
Swift Implementation
Drop this into your viewDidLoad (or wherever you configure your calendar instance):
// Initialize and add the calendar to your view let calendar = FSCalendar(frame: CGRect(x: 0, y: 100, width: view.frame.width, height: 300)) view.addSubview(calendar) // Set the first weekday: 1 = Sunday, 2 = Monday, 3 = Tuesday, ..., 7 = Saturday calendar.firstWeekday = 2 // Example: Make Monday the week start
Objective-C Implementation
FSCalendar *calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 300)]; [self.view addSubview:calendar]; // Set Monday as the week start calendar.firstWeekday = 2;
This overrides the default system locale's week start, so your calendar will consistently use the day you specify.
2. Lock Week View to Today's Full Week
To make the week view always show today's full 7-day week and stay anchored there, we'll calculate the current week's date range and configure the calendar to stick to it.
Step 1: Calculate Today's Week Range
First, write a helper method to get the start and end dates of the current week (match your custom week start if you set one):
Swift
func getCurrentWeekRange() -> (start: Date, end: Date) { // Use a calendar instance that matches your FSCalendar's week start var calendar = Calendar(identifier: .gregorian) calendar.firstWeekday = self.calendar.firstWeekday // Sync with your calendar's setting // Get the start of the current week guard let startOfWeek = calendar.date(from: calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date())) else { fatalError("Failed to calculate start of week") } // Add 6 days to get the end of the week let endOfWeek = calendar.date(byAdding: .day, value: 6, to: startOfWeek)! return (startOfWeek, endOfWeek) }
Objective-C
- (NSDate *)startOfCurrentWeek { NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; calendar.firstWeekday = self.calendar.firstWeekday; // Match your FSCalendar's week start NSDateComponents *weekComponents = [calendar components:NSCalendarUnitYearForWeekOfYear | NSCalendarUnitWeekOfYear fromDate:[NSDate date]]; return [calendar dateFromComponents:weekComponents]; } - (NSDate *)endOfCurrentWeek { NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; return [calendar dateByAddingUnit:NSCalendarUnitDay value:6 toDate:[self startOfCurrentWeek] options:0]; }
Step 2: Configure the Week View
Now set up the calendar to display only today's week, with optional locks to prevent scrolling away:
Swift
// Switch to week view mode calendar.scope = .week let weekRange = getCurrentWeekRange() // Jump directly to the start of today's week calendar.setCurrentPage(weekRange.start, animated: false) // Optional: Block users from scrolling outside today's week calendar.minimumDate = weekRange.start calendar.maximumDate = weekRange.end // Optional: Auto-revert to today's week if user tries to scroll away func calendarCurrentPageDidChange(_ calendar: FSCalendar) { let weekRange = getCurrentWeekRange() let currentPage = calendar.currentPage // Check if the current page is outside the week bounds if !calendar.date(weekRange.start, isEqualOrAfter: currentPage) || !calendar.date(weekRange.end, isEqualOrBefore: currentPage) { calendar.setCurrentPage(weekRange.start, animated: true) } }
Objective-C
// Switch to week view self.calendar.scope = FSCalendarScopeWeek; NSDate *startOfWeek = [self startOfCurrentWeek]; NSDate *endOfWeek = [self endOfCurrentWeek]; // Scroll to today's week [self.calendar setCurrentPage:startOfWeek animated:NO]; // Optional: Lock to this week self.calendar.minimumDate = startOfWeek; self.calendar.maximumDate = endOfWeek; // Optional: Auto-revert to today's week on scroll - (void)calendarCurrentPageDidChange:(FSCalendar *)calendar { NSDate *startOfWeek = [self startOfCurrentWeek]; NSDate *endOfWeek = [self endOfCurrentWeek]; NSDate *currentPage = calendar.currentPage; if (![calendar date:startOfWeek isEqualOrAfter:currentPage] || ![calendar date:endOfWeek isEqualOrBefore:currentPage]) { [calendar setCurrentPage:startOfWeek animated:YES]; } }
Hope these solutions fit your needs perfectly! If you hit any edge cases (like handling locale changes or leap years), feel free to tweak the helper methods to match your app's specific behavior.
内容的提问来源于stack exchange,提问作者kakubei

