Increase fps
This commit is contained in:
parent
7968899471
commit
2c3bcbbcb2
|
|
@ -49,6 +49,9 @@
|
|||
30CEF9011C950C1F008EAFB1 /* FSCalendarAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30CEF8FF1C950C1F008EAFB1 /* FSCalendarAnimator.m */; };
|
||||
30CEF9021C950C1F008EAFB1 /* FSCalendarAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30CEF8FF1C950C1F008EAFB1 /* FSCalendarAnimator.m */; };
|
||||
30D55B101C90240000BB43D5 /* HidePlaceholderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30D55B0F1C90240000BB43D5 /* HidePlaceholderViewController.m */; };
|
||||
30DBE3C41DC641AD005A22B7 /* FSCalendarCalculator.h in Headers */ = {isa = PBXBuildFile; fileRef = 30DBE3C21DC641AD005A22B7 /* FSCalendarCalculator.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
30DBE3C51DC641AD005A22B7 /* FSCalendarCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30DBE3C31DC641AD005A22B7 /* FSCalendarCalculator.m */; };
|
||||
30DBE3C61DC641AD005A22B7 /* FSCalendarCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30DBE3C31DC641AD005A22B7 /* FSCalendarCalculator.m */; };
|
||||
30F5D8561B9FC33400C1C201 /* FSCalendar.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BAC01B8D8E22004B9476 /* FSCalendar.m */; };
|
||||
30F5D85A1B9FC4BB00C1C201 /* MultipleSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30F5D8591B9FC4BB00C1C201 /* MultipleSelectionViewController.m */; };
|
||||
30FCB3961BAAD112002B87AD /* FSCalendarStickyHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 30FCB3941BAAD112002B87AD /* FSCalendarStickyHeader.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
|
|
@ -135,6 +138,8 @@
|
|||
30CEF8FF1C950C1F008EAFB1 /* FSCalendarAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSCalendarAnimator.m; sourceTree = "<group>"; };
|
||||
30D55B0E1C90240000BB43D5 /* HidePlaceholderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HidePlaceholderViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
30D55B0F1C90240000BB43D5 /* HidePlaceholderViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HidePlaceholderViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
30DBE3C21DC641AD005A22B7 /* FSCalendarCalculator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSCalendarCalculator.h; sourceTree = "<group>"; };
|
||||
30DBE3C31DC641AD005A22B7 /* FSCalendarCalculator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSCalendarCalculator.m; sourceTree = "<group>"; };
|
||||
30F5D8581B9FC4BB00C1C201 /* MultipleSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MultipleSelectionViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
30F5D8591B9FC4BB00C1C201 /* MultipleSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MultipleSelectionViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
30FCB3941BAAD112002B87AD /* FSCalendarStickyHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSCalendarStickyHeader.h; sourceTree = "<group>"; };
|
||||
|
|
@ -226,6 +231,8 @@
|
|||
30B0BAC21B8D8E22004B9476 /* FSCalendarAppearance.m */,
|
||||
303105F11DC241D9002F802F /* FSCalendarDelegateProxy.h */,
|
||||
303105F21DC241D9002F802F /* FSCalendarDelegateProxy.m */,
|
||||
30DBE3C21DC641AD005A22B7 /* FSCalendarCalculator.h */,
|
||||
30DBE3C31DC641AD005A22B7 /* FSCalendarCalculator.m */,
|
||||
309225381B905C4300123031 /* FSCalendarConstants.h */,
|
||||
309225391B905C4300123031 /* FSCalendarConstants.m */,
|
||||
3065CA941CD31B81006C218D /* FSCalendarScopeHandle.h */,
|
||||
|
|
@ -405,6 +412,7 @@
|
|||
3065CA961CD31B81006C218D /* FSCalendarScopeHandle.h in Headers */,
|
||||
3095398F1C38D66C00BD37AA /* FSCalendarCollectionViewLayout.h in Headers */,
|
||||
3055B1C21DA9323A002AFA13 /* FSCalendarExtensions.h in Headers */,
|
||||
30DBE3C41DC641AD005A22B7 /* FSCalendarCalculator.h in Headers */,
|
||||
30CEF9001C950C1F008EAFB1 /* FSCalendarAnimator.h in Headers */,
|
||||
30B0BB031B8D9B6D004B9476 /* FSCalendarDynamicHeader.h in Headers */,
|
||||
);
|
||||
|
|
@ -558,6 +566,7 @@
|
|||
files = (
|
||||
EE638CCE1B89DBD80006DD1A /* StoryboardExampleViewController.m in Sources */,
|
||||
EECA10F81BA9C0E400945B83 /* FullScreenExampleViewController.m in Sources */,
|
||||
30DBE3C51DC641AD005A22B7 /* FSCalendarCalculator.m in Sources */,
|
||||
EE638CC91B89DB940006DD1A /* CalendarConfigViewController.m in Sources */,
|
||||
30B0BAD01B8D8E23004B9476 /* FSCalendar.m in Sources */,
|
||||
3065CAA81CD3506A006C218D /* FSCalendar+Deprecated.m in Sources */,
|
||||
|
|
@ -595,6 +604,7 @@
|
|||
EEC9C03B1BDC9E7000383A07 /* FSCalendarCollectionView.m in Sources */,
|
||||
3065CAA91CD3506A006C218D /* FSCalendar+Deprecated.m in Sources */,
|
||||
30B0BAF71B8D9AC1004B9476 /* FSCalendarCell.m in Sources */,
|
||||
30DBE3C61DC641AD005A22B7 /* FSCalendarCalculator.m in Sources */,
|
||||
30B0BAF81B8D9AC1004B9476 /* FSCalendarHeader.m in Sources */,
|
||||
3092253C1B905C4300123031 /* FSCalendarConstants.m in Sources */,
|
||||
3055B1C41DA9323A002AFA13 /* FSCalendarExtensions.m in Sources */,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>classNames</key>
|
||||
<dict>
|
||||
<key>FSCalendarTests</key>
|
||||
<dict>
|
||||
<key>testIndexPathForDatePerformance</key>
|
||||
<dict>
|
||||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -35,6 +35,18 @@
|
|||
<string>com.apple.platform.iphonesimulator</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>621090AF-4CF3-4245-99AD-46AD956ACA82</key>
|
||||
<dict>
|
||||
<key>targetArchitecture</key>
|
||||
<string>arm64</string>
|
||||
<key>targetDevice</key>
|
||||
<dict>
|
||||
<key>modelCode</key>
|
||||
<string>iPhone8,4</string>
|
||||
<key>platformIdentifier</key>
|
||||
<string>com.apple.platform.iphoneos</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>A165CA85-3EFC-487B-954E-5AD1DC2EB21D</key>
|
||||
<dict>
|
||||
<key>localComputer</key>
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@
|
|||
#import <XCTest/XCTest.h>
|
||||
#import "FSCalendar.h"
|
||||
#import "FSCalendarDynamicHeader.h"
|
||||
#import "FSCalendarExtensions.h"
|
||||
|
||||
@interface FSCalendarTests : XCTestCase
|
||||
@interface FSCalendarTests : XCTestCase <FSCalendarDataSource,FSCalendarDelegate>
|
||||
|
||||
@property (strong, nonatomic) FSCalendar *calendar;
|
||||
@property (strong, nonatomic) NSDate *date;
|
||||
@property (strong, nonatomic) NSIndexPath *indexPath;
|
||||
@property (strong, nonatomic) NSMutableArray<NSIndexPath *> *indexPaths;
|
||||
@property (strong, nonatomic) NSDateFormatter *formatter;
|
||||
|
||||
@end
|
||||
|
|
@ -25,13 +27,29 @@
|
|||
{
|
||||
[super setUp];
|
||||
self.calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, 0, 320, 300)];
|
||||
[self.calendar.calculator reloadSections];
|
||||
self.indexPath = [NSIndexPath indexPathForItem:25 inSection:0];
|
||||
self.date = [self.calendar dateForIndexPath:self.indexPath];
|
||||
|
||||
self.indexPaths = [NSMutableArray array];
|
||||
for (int i = 0; i < 42; i++) {
|
||||
[self.indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:0]];
|
||||
}
|
||||
self.formatter = [[NSDateFormatter alloc] init];
|
||||
self.formatter.dateFormat = @"yyyy-MM-dd";
|
||||
self.date = [self.formatter dateFromString:@"1900-11-11"];
|
||||
|
||||
}
|
||||
|
||||
- (NSDate *)minimumDateForCalendar:(FSCalendar *)calendar
|
||||
{
|
||||
return [self.formatter dateFromString:@"1900-01-01"];
|
||||
}
|
||||
|
||||
- (NSDate *)maximumDateForCalendar:(FSCalendar *)calendar
|
||||
{
|
||||
return [self.formatter dateFromString:@"2300-01-01"];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
[super tearDown];
|
||||
|
|
@ -48,13 +66,15 @@
|
|||
|
||||
- (void)testIndexPathForDatePerformance {
|
||||
[self measureBlock:^{
|
||||
[self.calendar indexPathForDate:self.date scope:FSCalendarScopeMonth];
|
||||
[self.calendar.calculator indexPathForDate:self.date scope:FSCalendarScopeMonth];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)testDateForIndexPathPerformance {
|
||||
[self measureBlock:^{
|
||||
[self.calendar dateForIndexPath:self.indexPath];
|
||||
[self.indexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
[self.calendar.calculator dateForIndexPath:obj];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#import "FSCalendarAnimator.h"
|
||||
#import "FSCalendarDelegateProxy.h"
|
||||
#import "FSCalendarCalculator.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
|
@ -65,8 +66,9 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
@property (weak , nonatomic) FSCalendarCollectionView *collectionView;
|
||||
@property (weak , nonatomic) FSCalendarCollectionViewLayout *collectionViewLayout;
|
||||
|
||||
@property (strong, nonatomic) FSCalendarAnimator *animator;
|
||||
@property (strong, nonatomic) FSCalendarDelegateProxy *proxy;
|
||||
@property (strong, nonatomic) FSCalendarAnimator *animator;
|
||||
@property (strong, nonatomic) FSCalendarDelegateProxy *proxy;
|
||||
@property (strong, nonatomic) FSCalendarCalculator *calculator;
|
||||
|
||||
@property (weak , nonatomic) FSCalendarHeader *header;
|
||||
@property (weak , nonatomic) FSCalendarHeaderTouchDeliver *deliver;
|
||||
|
|
@ -92,13 +94,8 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
|
||||
- (void)orientationDidChange:(NSNotification *)notification;
|
||||
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath;
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath scope:(FSCalendarScope)scope;
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date;
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date scope:(FSCalendarScope)scope;
|
||||
- (CGSize)sizeThatFits:(CGSize)size scope:(FSCalendarScope)scope;
|
||||
|
||||
- (NSInteger)numberOfHeadPlaceholdersForMonth:(NSDate *)month;
|
||||
- (NSInteger)numberOfRowsInMonth:(NSDate *)month;
|
||||
|
||||
- (void)scrollToDate:(NSDate *)date;
|
||||
|
|
@ -133,8 +130,6 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
|
||||
- (void)requestBoundingDatesIfNecessary;
|
||||
|
||||
- (NSDate *)safeDateForDate:(NSDate *)date;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FSCalendar
|
||||
|
|
@ -264,6 +259,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
// Assistants
|
||||
self.animator = [[FSCalendarAnimator alloc] initWithCalendar:self];
|
||||
self.proxy = [[FSCalendarDelegateProxy alloc] initWithCalendar:self];
|
||||
self.calculator = [[FSCalendarCalculator alloc] initWithCalendar:self];
|
||||
|
||||
// Gestures
|
||||
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self.animator action:@selector(handlePan:)];
|
||||
|
|
@ -483,20 +479,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
|
||||
{
|
||||
[self requestBoundingDatesIfNecessary];
|
||||
if (self.animator.transition == FSCalendarTransitionWeekToMonth) {
|
||||
NSInteger sections = [self.gregorian components:NSCalendarUnitMonth fromDate:[self.gregorian fs_firstDayOfMonth:self.minimumDate] toDate:self.maximumDate options:0].month + 1;
|
||||
return sections;
|
||||
}
|
||||
switch (_scope) {
|
||||
case FSCalendarScopeMonth: {
|
||||
NSInteger sections = [self.gregorian components:NSCalendarUnitMonth fromDate:[self.gregorian fs_firstDayOfMonth:self.minimumDate] toDate:self.maximumDate options:0].month + 1;
|
||||
return sections;
|
||||
}
|
||||
case FSCalendarScopeWeek: {
|
||||
NSInteger sections = [self.gregorian components:NSCalendarUnitWeekOfYear fromDate:[self.gregorian fs_firstDayOfWeek:self.minimumDate] toDate:self.maximumDate options:0].weekOfYear + 1;
|
||||
return sections;
|
||||
}
|
||||
}
|
||||
return self.calculator.numberOfSections;
|
||||
}
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
|
||||
|
|
@ -556,7 +539,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
FSCalendarCell *cell = (FSCalendarCell *)[collectionView cellForItemAtIndexPath:indexPath];
|
||||
cell.dateIsSelected = YES;
|
||||
[cell performSelecting];
|
||||
NSDate *selectedDate = [self dateForIndexPath:indexPath];
|
||||
NSDate *selectedDate = [self.calculator dateForIndexPath:indexPath];
|
||||
if (!_supressEvent) {
|
||||
[self.proxy didSelectDate:selectedDate];
|
||||
}
|
||||
|
|
@ -573,7 +556,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
}
|
||||
return NO;
|
||||
}
|
||||
NSDate *targetDate = [self dateForIndexPath:indexPath];
|
||||
NSDate *targetDate = [self.calculator dateForIndexPath:indexPath];
|
||||
if ([self isDateSelected:targetDate]) {
|
||||
// Click on a selected date in multiple-selection mode
|
||||
if (self.allowsMultipleSelection) {
|
||||
|
|
@ -597,7 +580,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (!self.allowsMultipleSelection && self.selectedDate) {
|
||||
NSIndexPath *selectedIndexPath = [self indexPathForDate:self.selectedDate];
|
||||
NSIndexPath *selectedIndexPath = [self.calculator indexPathForDate:self.selectedDate];
|
||||
if (![indexPath isEqual:selectedIndexPath]) {
|
||||
[self collectionView:collectionView didDeselectItemAtIndexPath:selectedIndexPath];
|
||||
return;
|
||||
|
|
@ -608,7 +591,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
cell.dateIsSelected = NO;
|
||||
[cell setNeedsLayout];
|
||||
}
|
||||
NSDate *selectedDate = cell.date ?: [self dateForIndexPath:indexPath];
|
||||
NSDate *selectedDate = cell.date ?: [self.calculator dateForIndexPath:indexPath];
|
||||
[_selectedDates removeObject:selectedDate];
|
||||
[self deselectCounterpartDate:selectedDate];
|
||||
[self.proxy didDeselectDate:selectedDate];
|
||||
|
|
@ -617,13 +600,13 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (!self.allowsMultipleSelection) {
|
||||
NSIndexPath *selectedIndexPath = [self indexPathForDate:self.selectedDate];
|
||||
NSIndexPath *selectedIndexPath = [self.calculator indexPathForDate:self.selectedDate];
|
||||
if (![indexPath isEqual:selectedIndexPath]) {
|
||||
return [self collectionView:collectionView shouldDeselectItemAtIndexPath:selectedIndexPath];
|
||||
}
|
||||
}
|
||||
FSCalendarCell *cell = (FSCalendarCell *)[collectionView cellForItemAtIndexPath:indexPath];
|
||||
return [self.proxy shouldDeselectDate:(cell.date?:[self dateForIndexPath:indexPath])];
|
||||
return [self.proxy shouldDeselectDate:(cell.date?:[self.calculator dateForIndexPath:indexPath])];
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
|
||||
|
|
@ -816,7 +799,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
}
|
||||
if (self.hasValidateVisibleLayout) {
|
||||
[_collectionView.visibleCells makeObjectsPerformSelector:@selector(setDateIsToday:) withObject:@NO];
|
||||
[[_collectionView cellForItemAtIndexPath:[self indexPathForDate:today]] setValue:@YES forKey:@"dateIsToday"];
|
||||
[[_collectionView cellForItemAtIndexPath:[self.calculator indexPathForDate:today]] setValue:@YES forKey:@"dateIsToday"];
|
||||
[_collectionView.visibleCells makeObjectsPerformSelector:@selector(setNeedsLayout)];
|
||||
}
|
||||
}
|
||||
|
|
@ -842,7 +825,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
if (!self.superview) {
|
||||
return CGRectZero;
|
||||
}
|
||||
CGRect frame = [_collectionViewLayout layoutAttributesForItemAtIndexPath:[self indexPathForDate:date]].frame;
|
||||
CGRect frame = [_collectionViewLayout layoutAttributesForItemAtIndexPath:[self.calculator indexPathForDate:date]].frame;
|
||||
frame = [self.superview convertRect:frame fromView:_collectionView];
|
||||
return frame;
|
||||
}
|
||||
|
|
@ -1132,7 +1115,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
return;
|
||||
}
|
||||
[_selectedDates removeObject:date];
|
||||
NSIndexPath *indexPath = [self indexPathForDate:date];
|
||||
NSIndexPath *indexPath = [self.calculator indexPathForDate:date];
|
||||
if ([_collectionView.indexPathsForSelectedItems containsObject:indexPath]) {
|
||||
[_collectionView deselectItemAtIndexPath:indexPath animated:YES];
|
||||
FSCalendarCell *cell = (FSCalendarCell *)[_collectionView cellForItemAtIndexPath:indexPath];
|
||||
|
|
@ -1152,7 +1135,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
FSCalendarAssertDateInBounds(date,self.gregorian,self.minimumDate,self.maximumDate);
|
||||
|
||||
NSDate *targetDate = [self.gregorian dateBySettingHour:0 minute:0 second:0 ofDate:date options:0];
|
||||
NSIndexPath *targetIndexPath = [self indexPathForDate:targetDate];
|
||||
NSIndexPath *targetIndexPath = [self.calculator indexPathForDate:targetDate];
|
||||
|
||||
BOOL shouldSelect = !_supressEvent;
|
||||
// 跨月份点击
|
||||
|
|
@ -1284,7 +1267,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
{
|
||||
if (!date) return;
|
||||
if (![self isDateInRange:date]) {
|
||||
date = [self safeDateForDate:date];
|
||||
date = [self.calculator safeDateForDate:date];
|
||||
if (!date) return;
|
||||
}
|
||||
|
||||
|
|
@ -1318,87 +1301,6 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
}
|
||||
}
|
||||
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath scope:(FSCalendarScope)scope
|
||||
{
|
||||
if (!indexPath) return nil;
|
||||
switch (scope) {
|
||||
case FSCalendarScopeMonth: {
|
||||
NSDate *currentPage = [self.gregorian dateByAddingUnit:NSCalendarUnitMonth value:indexPath.section toDate:[self.gregorian fs_firstDayOfMonth:_minimumDate] options:0];
|
||||
NSInteger numberOfHeadPlaceholders = [self numberOfHeadPlaceholdersForMonth:currentPage];
|
||||
NSDate *firstDateOfPage = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:-numberOfHeadPlaceholders toDate:currentPage options:0];
|
||||
switch (_collectionViewLayout.scrollDirection) {
|
||||
case UICollectionViewScrollDirectionHorizontal: {
|
||||
NSUInteger rows = indexPath.item % 6;
|
||||
NSUInteger columns = indexPath.item / 6;
|
||||
NSUInteger daysOffset = 7*rows + columns;
|
||||
NSDate *date = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:daysOffset toDate:firstDateOfPage options:0];
|
||||
return date;
|
||||
}
|
||||
case UICollectionViewScrollDirectionVertical: {
|
||||
NSUInteger daysOffset = indexPath.item;
|
||||
NSDate *date = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:daysOffset toDate:firstDateOfPage options:0];
|
||||
return date;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSCalendarScopeWeek: {
|
||||
NSDate *currentPage = [self.gregorian dateByAddingUnit:NSCalendarUnitWeekOfYear value:indexPath.section toDate:[self.gregorian fs_firstDayOfWeek:_minimumDate] options:0];
|
||||
NSDate *date = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:indexPath.item toDate:currentPage options:0];
|
||||
return date;
|
||||
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (self.animator.transition == FSCalendarTransitionWeekToMonth && self.animator.state == FSCalendarTransitionStateInProgress) {
|
||||
return [self dateForIndexPath:indexPath scope:FSCalendarScopeMonth];
|
||||
}
|
||||
return [self dateForIndexPath:indexPath scope:_scope];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date scope:(FSCalendarScope)scope
|
||||
{
|
||||
if (!date) return nil;
|
||||
NSInteger item = 0;
|
||||
NSInteger section = 0;
|
||||
switch (scope) {
|
||||
case FSCalendarScopeMonth: {
|
||||
section = [self.gregorian components:NSCalendarUnitMonth fromDate:[self.gregorian fs_firstDayOfMonth:self.minimumDate] toDate:date options:0].month;
|
||||
NSDate *firstDayOfMonth = [self.gregorian fs_firstDayOfMonth:date];
|
||||
NSInteger numberOfHeadPlaceholders = [self numberOfHeadPlaceholdersForMonth:firstDayOfMonth];
|
||||
NSDate *firstDateOfPage = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:-numberOfHeadPlaceholders toDate:firstDayOfMonth options:0];
|
||||
switch (_collectionViewLayout.scrollDirection) {
|
||||
case UICollectionViewScrollDirectionHorizontal: {
|
||||
NSInteger vItem = [self.gregorian components:NSCalendarUnitDay fromDate:firstDateOfPage toDate:date options:0].day;
|
||||
NSInteger rows = vItem/7;
|
||||
NSInteger columns = vItem%7;
|
||||
item = columns*6 + rows;
|
||||
break;
|
||||
}
|
||||
case UICollectionViewScrollDirectionVertical: {
|
||||
item = [self.gregorian components:NSCalendarUnitDay fromDate:firstDateOfPage toDate:date options:0].day;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSCalendarScopeWeek: {
|
||||
section = [self.gregorian components:NSCalendarUnitWeekOfYear fromDate:[self.gregorian fs_firstDayOfWeek:self.minimumDate] toDate:date options:0].weekOfYear;
|
||||
item = (([self.gregorian component:NSCalendarUnitWeekday fromDate:date] - _firstWeekday) + 7) % 7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [NSIndexPath indexPathForItem:item inSection:section];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date
|
||||
{
|
||||
return [self indexPathForDate:date scope:_scope];
|
||||
}
|
||||
|
||||
- (BOOL)isDateInRange:(NSDate *)date
|
||||
{
|
||||
|
|
@ -1436,7 +1338,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
|
||||
- (BOOL)isDateSelected:(NSDate *)date
|
||||
{
|
||||
return [_selectedDates containsObject:date] || [_collectionView.indexPathsForSelectedItems containsObject:[self indexPathForDate:date]];
|
||||
return [_selectedDates containsObject:date] || [_collectionView.indexPathsForSelectedItems containsObject:[self.calculator indexPathForDate:date]];
|
||||
}
|
||||
|
||||
- (BOOL)isDateInDifferentPage:(NSDate *)date
|
||||
|
|
@ -1620,7 +1522,7 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
- (void)reloadDataForCell:(FSCalendarCell *)cell atIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
cell.calendar = self;
|
||||
cell.date = [self dateForIndexPath:indexPath];
|
||||
cell.date = [self.calculator dateForIndexPath:indexPath];
|
||||
cell.image = [self.proxy imageForDate:cell.date];
|
||||
cell.numberOfEvents = [self.proxy numberOfEventsForDate:cell.date];
|
||||
cell.title = [self.proxy titleForDate:cell.date];
|
||||
|
|
@ -1778,13 +1680,6 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
return orientation;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfHeadPlaceholdersForMonth:(NSDate *)month
|
||||
{
|
||||
NSInteger currentWeekday = [self.gregorian component:NSCalendarUnitWeekday fromDate:month];
|
||||
NSInteger number = ((currentWeekday- _firstWeekday) + 7) % 7 ?: (7 * (!self.floatingMode&&(self.placeholderType == FSCalendarPlaceholderTypeFillSixRows)));
|
||||
return number;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInMonth:(NSDate *)month
|
||||
{
|
||||
if (!month) return 0;
|
||||
|
|
@ -1805,19 +1700,11 @@ typedef NS_ENUM(NSUInteger, FSCalendarOrientation) {
|
|||
_minimumDate = self.proxy.minimumDateForCalendar;
|
||||
_maximumDate = self.proxy.maximumDateForCalendar;
|
||||
NSAssert([self.gregorian compareDate:self.minimumDate toDate:self.maximumDate toUnitGranularity:NSCalendarUnitDay] != NSOrderedDescending, @"The minimum date of calendar should be earlier than the maximum.");
|
||||
[self.calculator reloadSections];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDate *)safeDateForDate:(NSDate *)date
|
||||
{
|
||||
if ([self.gregorian compareDate:date toDate:self.minimumDate toUnitGranularity:NSCalendarUnitDay] == NSOrderedAscending) {
|
||||
date = self.minimumDate;
|
||||
} else if ([self.gregorian compareDate:date toDate:self.maximumDate toUnitGranularity:NSCalendarUnitDay] == NSOrderedDescending) {
|
||||
date = self.maximumDate;
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -313,8 +313,8 @@
|
|||
- (void)performBoundingRectTransitionFromMonth:(NSDate *)fromMonth toMonth:(NSDate *)toMonth duration:(CGFloat)duration
|
||||
{
|
||||
if (self.calendarScope != FSCalendarScopeMonth) return;
|
||||
NSInteger lastRowCount = [self.calendar numberOfRowsInMonth:fromMonth];
|
||||
NSInteger currentRowCount = [self.calendar numberOfRowsInMonth:toMonth];
|
||||
NSInteger lastRowCount = [self.calendar.calculator numberOfRowsInMonth:fromMonth];
|
||||
NSInteger currentRowCount = [self.calendar.calculator numberOfRowsInMonth:toMonth];
|
||||
if (lastRowCount != currentRowCount) {
|
||||
CGFloat animationDuration = duration;
|
||||
CGRect bounds = (CGRect){CGPointZero,[self.calendar sizeThatFits:self.calendar.frame.size scope:FSCalendarScopeMonth]};
|
||||
|
|
@ -399,7 +399,7 @@
|
|||
|
||||
#define kCalculateRowNumber \
|
||||
do { \
|
||||
UICollectionViewLayoutAttributes *itemAttributes = [self.collectionViewLayout layoutAttributesForItemAtIndexPath:[self.calendar indexPathForDate:focusedDate scope:FSCalendarScopeMonth]]; \
|
||||
UICollectionViewLayoutAttributes *itemAttributes = [self.collectionViewLayout layoutAttributesForItemAtIndexPath:[self.calendar.calculator indexPathForDate:focusedDate scope:FSCalendarScopeMonth]]; \
|
||||
CGPoint focuedCenter = itemAttributes.center; \
|
||||
if (CGRectContainsPoint(self.collectionView.bounds, focuedCenter)) { \
|
||||
switch (self.collectionViewLayout.scrollDirection) { \
|
||||
|
|
@ -434,7 +434,7 @@
|
|||
NSDate *minimumPage = [self.calendar.gregorian fs_firstDayOfMonth:self.calendar.minimumDate];
|
||||
NSInteger visibleSection = [self.calendar.gregorian components:NSCalendarUnitMonth fromDate:minimumPage toDate:currentPage options:0].month;
|
||||
NSIndexPath *firstIndexPath = [NSIndexPath indexPathForItem:0 inSection:visibleSection];
|
||||
NSDate *firstDate = [self.calendar dateForIndexPath:firstIndexPath scope:FSCalendarScopeMonth];
|
||||
NSDate *firstDate = [self.calendar.calculator dateForIndexPath:firstIndexPath scope:FSCalendarScopeMonth];
|
||||
currentPage = [self.calendar.gregorian dateByAddingUnit:NSCalendarUnitDay value:focusedRowNumber*7 toDate:firstDate options:0];
|
||||
|
||||
attributes.focusedRowNumber = focusedRowNumber;
|
||||
|
|
@ -455,7 +455,7 @@
|
|||
|
||||
NSDate *focusedDate = self.calendar.selectedDate ?: self.calendar.today;
|
||||
if (focusedDate) {
|
||||
UICollectionViewLayoutAttributes *itemAttributes = [self.collectionViewLayout layoutAttributesForItemAtIndexPath:[self.calendar indexPathForDate:focusedDate scope:FSCalendarScopeWeek]];
|
||||
UICollectionViewLayoutAttributes *itemAttributes = [self.collectionViewLayout layoutAttributesForItemAtIndexPath:[self.calendar.calculator indexPathForDate:focusedDate scope:FSCalendarScopeWeek]];
|
||||
CGPoint focuedCenter = itemAttributes.center;
|
||||
if (!CGRectContainsPoint(self.calendar.collectionView.bounds, focuedCenter)) {
|
||||
focusedDate = nil;
|
||||
|
|
@ -468,7 +468,7 @@
|
|||
NSDate *firstDayOfMonth = [self.calendar.gregorian fs_firstDayOfMonth:focusedDate];
|
||||
attributes.focusedDate = focusedDate;
|
||||
firstDayOfMonth = firstDayOfMonth ?: [self.calendar.gregorian fs_firstDayOfMonth:currentPage];
|
||||
NSInteger numberOfPlaceholdersForPrev = [self.calendar numberOfHeadPlaceholdersForMonth:firstDayOfMonth];
|
||||
NSInteger numberOfPlaceholdersForPrev = [self.calendar.calculator numberOfHeadPlaceholdersForMonth:firstDayOfMonth];
|
||||
NSDate *firstDateOfPage = [self.calendar.gregorian dateByAddingUnit:NSCalendarUnitDay value:-numberOfPlaceholdersForPrev toDate:firstDayOfMonth options:0];
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
|
|
@ -534,7 +534,7 @@
|
|||
self.calendar.preferredHeaderHeight+
|
||||
self.calendar.preferredWeekdayHeight+
|
||||
self.calendar.preferredPadding*2+
|
||||
([self.calendar numberOfRowsInMonth:page]*self.calendar.preferredRowHeight)+
|
||||
([self.calendar.calculator numberOfRowsInMonth:page]*self.calendar.preferredRowHeight)+
|
||||
self.calendar.scopeHandle.fs_height);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -657,11 +657,13 @@
|
|||
- (void)invalidateTitleFont
|
||||
{
|
||||
[_calendar.collectionView.visibleCells makeObjectsPerformSelector:_cmd];
|
||||
_calendar.calculator.titleHeight = -1;
|
||||
}
|
||||
|
||||
- (void)invalidateSubtitleFont
|
||||
{
|
||||
[_calendar.collectionView.visibleCells makeObjectsPerformSelector:_cmd];
|
||||
_calendar.calculator.subtitleHeight = -1;
|
||||
}
|
||||
|
||||
- (void)invalidateTitleTextColor
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// FSCalendarCalculator.h
|
||||
// FSCalendar
|
||||
//
|
||||
// Created by dingwenchao on 30/10/2016.
|
||||
// Copyright © 2016 wenchaoios. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FSCalendar;
|
||||
|
||||
@interface FSCalendarCalculator : NSObject
|
||||
|
||||
@property (weak , nonatomic) FSCalendar *calendar;
|
||||
|
||||
@property (assign, nonatomic) CGFloat monthHeight;
|
||||
@property (assign, nonatomic) CGFloat titleHeight;
|
||||
@property (assign, nonatomic) CGFloat subtitleHeight;
|
||||
|
||||
@property (readonly, nonatomic) NSInteger numberOfSections;
|
||||
|
||||
- (instancetype)initWithCalendar:(FSCalendar *)calendar;
|
||||
|
||||
- (NSDate *)safeDateForDate:(NSDate *)date;
|
||||
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath;
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath scope:(FSCalendarScope)scope;
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date;
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date scope:(FSCalendarScope)scope;
|
||||
|
||||
- (NSInteger)numberOfHeadPlaceholdersForMonth:(NSDate *)month;
|
||||
- (NSInteger)numberOfRowsInMonth:(NSDate *)month;
|
||||
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
|
||||
|
||||
- (void)reloadSections;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
//
|
||||
// FSCalendarCalculator.m
|
||||
// FSCalendar
|
||||
//
|
||||
// Created by dingwenchao on 30/10/2016.
|
||||
// Copyright © 2016 wenchaoios. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FSCalendar.h"
|
||||
#import "FSCalendarCalculator.h"
|
||||
#import "FSCalendarDynamicHeader.h"
|
||||
#import "FSCalendarExtensions.h"
|
||||
|
||||
@interface FSCalendarCalculator () <NSCacheDelegate>
|
||||
|
||||
@property (assign, nonatomic) NSInteger numberOfMonths;
|
||||
@property (strong, nonatomic) NSCache<NSNumber *, NSDate *> *months;
|
||||
@property (strong, nonatomic) NSCache<NSNumber *, NSDate *> *monthHeads;
|
||||
|
||||
@property (assign, nonatomic) NSInteger numberOfWeeks;
|
||||
@property (strong, nonatomic) NSCache<NSNumber *, NSDate *> *weeks;
|
||||
|
||||
@property (strong, nonatomic) NSCache<NSDate *, NSNumber *> *rowNumbers;
|
||||
|
||||
@property (readonly, nonatomic) NSCalendar *gregorian;
|
||||
@property (readonly, nonatomic) NSDate *minimumDate;
|
||||
@property (readonly, nonatomic) NSDate *maximumDate;
|
||||
|
||||
- (NSDate *)weekForSection:(NSInteger)section;
|
||||
- (NSDate *)monthForSection:(NSInteger)section;
|
||||
- (NSDate *)monthHeadForSection:(NSInteger)section;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FSCalendarCalculator
|
||||
|
||||
- (instancetype)initWithCalendar:(FSCalendar *)calendar
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.calendar = calendar;
|
||||
self.monthHeight = -1;
|
||||
self.titleHeight = -1;
|
||||
self.subtitleHeight = -1;
|
||||
|
||||
self.months = [[NSCache alloc] init];
|
||||
self.months.countLimit = 40;
|
||||
self.months.delegate = self;
|
||||
self.monthHeads = [[NSCache alloc] init];
|
||||
self.monthHeads.countLimit = 40;
|
||||
self.monthHeads.delegate = self;
|
||||
|
||||
self.weeks = [[NSCache alloc] init];
|
||||
self.weeks.countLimit = 30;
|
||||
self.weeks.delegate = self;
|
||||
|
||||
self.rowNumbers = [[NSCache alloc] init];
|
||||
self.rowNumbers.countLimit = 40;
|
||||
self.rowNumbers.delegate = self;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - <NSCacheDelegate>
|
||||
|
||||
- (void)cache:(NSCache *)cache willEvictObject:(id)obj { }
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (CGFloat)titleHeight
|
||||
{
|
||||
if (_titleHeight == -1) {
|
||||
_titleHeight = [@"1" sizeWithAttributes:@{NSFontAttributeName:self.calendar.appearance.titleFont}].height;
|
||||
}
|
||||
return _titleHeight;
|
||||
}
|
||||
|
||||
- (CGFloat)subtitleHeight
|
||||
{
|
||||
if (_subtitleHeight == -1) {
|
||||
_subtitleHeight = [@"1" sizeWithAttributes:@{NSFontAttributeName:self.calendar.appearance.subtitleFont}].height;
|
||||
}
|
||||
return _subtitleHeight;
|
||||
}
|
||||
|
||||
- (NSDate *)safeDateForDate:(NSDate *)date
|
||||
{
|
||||
if ([self.gregorian compareDate:date toDate:self.minimumDate toUnitGranularity:NSCalendarUnitDay] == NSOrderedAscending) {
|
||||
date = self.minimumDate;
|
||||
} else if ([self.gregorian compareDate:date toDate:self.maximumDate toUnitGranularity:NSCalendarUnitDay] == NSOrderedDescending) {
|
||||
date = self.maximumDate;
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath scope:(FSCalendarScope)scope
|
||||
{
|
||||
if (!indexPath) return nil;
|
||||
switch (scope) {
|
||||
case FSCalendarScopeMonth: {
|
||||
NSDate *head = [self monthHeadForSection:indexPath.section];
|
||||
switch (self.calendar.collectionViewLayout.scrollDirection) {
|
||||
case UICollectionViewScrollDirectionHorizontal: {
|
||||
NSUInteger rows = indexPath.item % 6;
|
||||
NSUInteger columns = indexPath.item / 6;
|
||||
NSUInteger daysOffset = 7*rows + columns;
|
||||
NSDate *date = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:daysOffset toDate:head options:0];
|
||||
return date;
|
||||
}
|
||||
case UICollectionViewScrollDirectionVertical: {
|
||||
NSUInteger daysOffset = indexPath.item;
|
||||
NSDate *date = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:daysOffset toDate:head options:0];
|
||||
return date;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSCalendarScopeWeek: {
|
||||
NSDate *currentPage = [self weekForSection:indexPath.section];
|
||||
NSDate *date = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:indexPath.item toDate:currentPage options:0];
|
||||
return date;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (self.calendar.animator.transition == FSCalendarTransitionWeekToMonth && self.calendar.animator.state == FSCalendarTransitionStateInProgress) {
|
||||
return [self dateForIndexPath:indexPath scope:FSCalendarScopeMonth];
|
||||
}
|
||||
return [self dateForIndexPath:indexPath scope:self.calendar.scope];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date scope:(FSCalendarScope)scope
|
||||
{
|
||||
if (!date) return nil;
|
||||
NSInteger item = 0;
|
||||
NSInteger section = 0;
|
||||
switch (scope) {
|
||||
case FSCalendarScopeMonth: {
|
||||
section = [self.gregorian components:NSCalendarUnitMonth fromDate:[self.gregorian fs_firstDayOfMonth:self.minimumDate] toDate:date options:0].month;
|
||||
NSDate *head = [self monthHeadForSection:section];
|
||||
switch (self.calendar.collectionViewLayout.scrollDirection) {
|
||||
case UICollectionViewScrollDirectionHorizontal: {
|
||||
NSInteger vItem = [self.gregorian components:NSCalendarUnitDay fromDate:head toDate:date options:0].day;
|
||||
NSInteger rows = vItem/7;
|
||||
NSInteger columns = vItem%7;
|
||||
item = columns*6 + rows;
|
||||
break;
|
||||
}
|
||||
case UICollectionViewScrollDirectionVertical: {
|
||||
item = [self.gregorian components:NSCalendarUnitDay fromDate:head toDate:date options:0].day;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSCalendarScopeWeek: {
|
||||
section = [self.gregorian components:NSCalendarUnitWeekOfYear fromDate:[self.gregorian fs_firstDayOfWeek:self.minimumDate] toDate:date options:0].weekOfYear;
|
||||
item = (([self.gregorian component:NSCalendarUnitWeekday fromDate:date] - self.gregorian.firstWeekday) + 7) % 7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [NSIndexPath indexPathForItem:item inSection:section];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date
|
||||
{
|
||||
return [self indexPathForDate:date scope:self.calendar.scope];
|
||||
}
|
||||
|
||||
- (void)reloadSections
|
||||
{
|
||||
self.numberOfMonths = [self.gregorian components:NSCalendarUnitMonth fromDate:[self.gregorian fs_firstDayOfMonth:self.minimumDate] toDate:self.maximumDate options:0].month+1;
|
||||
self.numberOfWeeks = [self.gregorian components:NSCalendarUnitWeekOfYear fromDate:[self.gregorian fs_firstDayOfWeek:self.minimumDate] toDate:self.maximumDate options:0].weekOfYear+1;
|
||||
|
||||
[self.months removeAllObjects];
|
||||
[self.monthHeads removeAllObjects];
|
||||
[self.weeks removeAllObjects];
|
||||
|
||||
[self.rowNumbers removeAllObjects];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSections
|
||||
{
|
||||
if (self.calendar.animator.transition == FSCalendarTransitionWeekToMonth) {
|
||||
return self.numberOfMonths;
|
||||
} else {
|
||||
switch (self.calendar.scope) {
|
||||
case FSCalendarScopeMonth: {
|
||||
return self.numberOfMonths;
|
||||
}
|
||||
case FSCalendarScopeWeek: {
|
||||
return self.numberOfWeeks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfHeadPlaceholdersForMonth:(NSDate *)month
|
||||
{
|
||||
NSInteger currentWeekday = [self.gregorian component:NSCalendarUnitWeekday fromDate:month];
|
||||
NSInteger number = ((currentWeekday- self.gregorian.firstWeekday) + 7) % 7 ?: (7 * (!self.calendar.floatingMode&&(self.calendar.placeholderType == FSCalendarPlaceholderTypeFillSixRows)));
|
||||
return number;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInMonth:(NSDate *)month
|
||||
{
|
||||
if (!month) return 0;
|
||||
if (self.calendar.placeholderType == FSCalendarPlaceholderTypeFillSixRows) return 6;
|
||||
|
||||
NSNumber *rowNumber = self.rowNumbers[month];
|
||||
if (!rowNumber) {
|
||||
NSDate *firstDayOfMonth = [self.gregorian fs_firstDayOfMonth:month];
|
||||
NSInteger weekdayOfFirstDay = [self.gregorian component:NSCalendarUnitWeekday fromDate:firstDayOfMonth];
|
||||
NSInteger numberOfDaysInMonth = [self.gregorian fs_numberOfDaysInMonth:month];
|
||||
NSInteger numberOfPlaceholdersForPrev = ((weekdayOfFirstDay - self.gregorian.firstWeekday) + 7) % 7;
|
||||
NSInteger headDayCount = numberOfDaysInMonth + numberOfPlaceholdersForPrev;
|
||||
NSInteger numberOfRows = (headDayCount/7) + (headDayCount%7>0);
|
||||
self.rowNumbers[month] = @(numberOfRows);
|
||||
}
|
||||
return rowNumber.integerValue;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
if (self.calendar.scope == FSCalendarScopeWeek) return 1;
|
||||
NSDate *month = [self monthForSection:section];
|
||||
return [self numberOfRowsInMonth:month];
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (NSDate *)monthForSection:(NSInteger)section
|
||||
{
|
||||
NSNumber *key = @(section);
|
||||
NSDate *month = self.months[key];
|
||||
if (!month) {
|
||||
month = [self.gregorian dateByAddingUnit:NSCalendarUnitMonth value:section toDate:[self.gregorian fs_firstDayOfMonth:self.minimumDate] options:0];
|
||||
NSInteger numberOfHeadPlaceholders = [self numberOfHeadPlaceholdersForMonth:month];
|
||||
NSDate *monthHead = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:-numberOfHeadPlaceholders toDate:month options:0];
|
||||
self.months[key] = month;
|
||||
self.monthHeads[key] = monthHead;
|
||||
}
|
||||
return month;
|
||||
}
|
||||
|
||||
- (NSDate *)monthHeadForSection:(NSInteger)section
|
||||
{
|
||||
NSNumber *key = @(section);
|
||||
NSDate *monthHead = self.monthHeads[key];
|
||||
if (!monthHead) {
|
||||
NSDate *month = [self.gregorian dateByAddingUnit:NSCalendarUnitMonth value:section toDate:[self.gregorian fs_firstDayOfMonth:self.minimumDate] options:0];
|
||||
NSInteger numberOfHeadPlaceholders = [self numberOfHeadPlaceholdersForMonth:month];
|
||||
monthHead = [self.gregorian dateByAddingUnit:NSCalendarUnitDay value:-numberOfHeadPlaceholders toDate:month options:0];
|
||||
self.months[key] = month;
|
||||
self.monthHeads[key] = monthHead;
|
||||
}
|
||||
return monthHead;
|
||||
}
|
||||
|
||||
- (NSDate *)weekForSection:(NSInteger)section
|
||||
{
|
||||
NSNumber *key = @(section);
|
||||
NSDate *week = self.weeks[key];
|
||||
if (!week) {
|
||||
week = [self.gregorian dateByAddingUnit:NSCalendarUnitWeekOfYear value:section toDate:[self.gregorian fs_firstDayOfWeek:self.minimumDate] options:0];
|
||||
self.weeks[key] = week;
|
||||
}
|
||||
return week;
|
||||
}
|
||||
|
||||
- (NSCalendar *)gregorian { return self.calendar.gregorian; }
|
||||
- (NSDate *)minimumDate { return self.calendar.minimumDate; }
|
||||
- (NSDate *)maximumDate { return self.calendar.maximumDate; }
|
||||
|
||||
@end
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
|
||||
NSIndexPath *indexPath = [self.calendar.collectionView indexPathForCell:self];
|
||||
|
||||
NSInteger lineCount = [self.calendar numberOfRowsInMonth:self.month];
|
||||
NSInteger lineCount = [self.calendar.calculator numberOfRowsInMonth:self.month];
|
||||
if (lineCount == 6) {
|
||||
self.contentView.hidden = NO;
|
||||
} else {
|
||||
|
|
@ -187,8 +187,8 @@
|
|||
if (_needsAdjustingViewFrame || CGSizeEqualToSize(_titleLabel.frame.size, CGSizeZero)) {
|
||||
_needsAdjustingViewFrame = NO;
|
||||
if (_subtitle) {
|
||||
CGFloat titleHeight = [@"1" sizeWithAttributes:@{NSFontAttributeName:_titleLabel.font}].height;
|
||||
CGFloat subtitleHeight = [@"1" sizeWithAttributes:@{NSFontAttributeName:_subtitleLabel.font}].height;
|
||||
CGFloat titleHeight = self.calendar.calculator.titleHeight;
|
||||
CGFloat subtitleHeight = self.calendar.calculator.subtitleHeight;
|
||||
|
||||
CGFloat height = titleHeight + subtitleHeight;
|
||||
_titleLabel.frame = CGRectMake(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#import "FSCalendarCollectionView.h"
|
||||
#import "FSCalendarExtensions.h"
|
||||
#import "FSCalendarConstants.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#define kFSCalendarSeparatorInterRows @"FSCalendarSeparatorInterRows"
|
||||
#define kFSCalendarSeparatorInterColumns @"FSCalendarSeparatorInterColumns"
|
||||
|
|
@ -110,15 +109,16 @@
|
|||
return NO;
|
||||
}
|
||||
|
||||
NSDate *currentPage = [self.calendar.gregorian dateByAddingUnit:NSCalendarUnitMonth value:evaluatedObject.indexPath.section toDate:[self.calendar.gregorian fs_firstDayOfMonth:self.calendar.minimumDate] options:0];
|
||||
NSInteger numberOfRows = [self.calendar numberOfRowsInMonth:currentPage];
|
||||
NSInteger numberOfRows = [self.calendar.calculator numberOfRowsInSection:evaluatedObject.indexPath.section];
|
||||
|
||||
switch (self.scrollDirection) {
|
||||
case UICollectionViewScrollDirectionHorizontal: {
|
||||
return evaluatedObject.indexPath.item < numberOfRows-1;
|
||||
}
|
||||
case UICollectionViewScrollDirectionVertical: {
|
||||
return evaluatedObject.indexPath.item%7==0 && evaluatedObject.indexPath.item/7<numberOfRows-1;
|
||||
BOOL isValid = evaluatedObject.indexPath.item == 0;
|
||||
isValid |= (evaluatedObject.indexPath.item%7==0 && evaluatedObject.indexPath.item/7<numberOfRows-1);
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
#import "FSCalendarCollectionView.h"
|
||||
#import "FSCalendarCollectionViewLayout.h"
|
||||
#import "FSCalendarScopeHandle.h"
|
||||
#import "FSCalendarCalculator.h"
|
||||
#import "FSCalendarAnimator.h"
|
||||
#import "FSCalendarDelegateProxy.h"
|
||||
|
||||
@interface FSCalendar (Dynamic)
|
||||
|
||||
|
|
@ -28,6 +30,8 @@
|
|||
@property (readonly, nonatomic) FSCalendarScopeHandle *scopeHandle;
|
||||
@property (readonly, nonatomic) FSCalendarCollectionViewLayout *collectionViewLayout;
|
||||
@property (readonly, nonatomic) FSCalendarAnimator *animator;
|
||||
@property (readonly, nonatomic) FSCalendarCalculator *calculator;
|
||||
@property (readonly, nonatomic) FSCalendarDelegateProxy *proxy;
|
||||
@property (readonly, nonatomic) NSArray<UILabel *> *weekdays;
|
||||
@property (readonly, nonatomic) BOOL floatingMode;
|
||||
@property (readonly, nonatomic) NSArray *visibleStickyHeaders;
|
||||
|
|
@ -57,13 +61,6 @@
|
|||
|
||||
- (BOOL)isPageInRange:(NSDate *)page;
|
||||
- (BOOL)isDateInRange:(NSDate *)date;
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath;
|
||||
- (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath scope:(FSCalendarScope)scope;
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date;
|
||||
- (NSIndexPath *)indexPathForDate:(NSDate *)date scope:(FSCalendarScope)scope;
|
||||
|
||||
- (NSInteger)numberOfHeadPlaceholdersForMonth:(NSDate *)month;
|
||||
- (NSInteger)numberOfRowsInMonth:(NSDate *)month;
|
||||
|
||||
- (CGSize)sizeThatFits:(CGSize)size scope:(FSCalendarScope)scope;
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@end
|
||||
|
||||
@interface NSCache (FSCalendarExtensions)
|
||||
|
||||
- (void)setObject:(nullable id)obj forKeyedSubscript:(id<NSCopying>)key;
|
||||
- (id)objectForKeyedSubscript:(id<NSCopying>)key;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSObject (FSCalendarExtensions)
|
||||
|
||||
|
|
|
|||
|
|
@ -222,6 +222,26 @@
|
|||
|
||||
@end
|
||||
|
||||
@implementation NSCache (FSCalendarExtensions)
|
||||
|
||||
- (void)setObject:(nullable id)obj forKeyedSubscript:(id<NSCopying>)key
|
||||
{
|
||||
if (!key) return;
|
||||
|
||||
if (obj) {
|
||||
[self setObject:obj forKey:key];
|
||||
} else {
|
||||
[self removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (id)objectForKeyedSubscript:(id<NSCopying>)key
|
||||
{
|
||||
return [self objectForKey:key];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSObject (FSCalendarExtensions)
|
||||
|
||||
- (void)fs_setVariable:(id)variable forKey:(NSString *)key
|
||||
|
|
|
|||
Loading…
Reference in New Issue