我最近下载了使用objective-c在xCode中创建日历的代码。代码在很大程度上起作用,它突出显示用户选择的日期,但它应该注销用户选择的开始日期和结束日期。我的视图控制器和uiview(日历视图)之间使用了委托,但是当我的委托在viewDidLoad中设置时,我注意到它始终设置为null。我是应用程序制作的新手,所以非常感谢任何帮助。
viewcontroller.m:
#import "CalendarViewController.h"
#import "DSLCalendarView.h"
@interface CalendarViewController ()<DSLCalendarViewDelegate>
@property (nonatomic, weak) IBOutlet DSLCalendarView *calendarView;
@property (weak, nonatomic) IBOutlet UIButton *selectDatesButton;
@end
@implementation CalendarViewController
- (void)viewDidLoad;
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.calendarView.delegate = self;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#pragma mark - DSLCalendarViewDelegate methods
- (void)calendarView:(DSLCalendarView *)calendarView didSelectRange:(DSLCalendarRange *)range;
{
if (range != nil) {
NSLog( @"Selected %ld/%ld - %ld/%ld", (long)range.startDay.day, (long)range.startDay.month, (long)range.endDay.day, (long)range.endDay.month);
}
else {
NSLog( @"No selection" );
}
}
calendarView.m(不是所有代码,只是使用委托的方法)
#import "DSLCalendarDayCalloutView.h"
#import "DSLCalendarDayView.h"
#import "DSLCalendarMonthSelectorView.h"
#import "DSLCalendarMonthView.h"
#import "DSLCalendarView.h"
#import "DSLCalendarDayView.h"
@interface DSLCalendarView ()
@property (nonatomic, strong) DSLCalendarDayCalloutView *dayCalloutView;
@property (nonatomic, copy) NSDateComponents *draggingFixedDay;
@property (nonatomic, copy) NSDateComponents *draggingStartDay;
@property (nonatomic, assign) BOOL draggedOffStartDay;
@property (nonatomic, strong) NSMutableDictionary *monthViews;
@property (nonatomic, strong) UIView *monthContainerView;
@property (nonatomic, strong) UIView *monthContainerViewContentView;
@property (nonatomic, strong) DSLCalendarMonthSelectorView *monthSelectorView;
@end
@implementation DSLCalendarView {
CGFloat _dayViewHeight;
NSDateComponents *_visibleMonth;
}
- (void)positionViewsForMonth:(NSDateComponents*)month fromMonth:(NSDateComponents*)fromMonth animated:(BOOL)animated;
{
fromMonth = [fromMonth copy];
month = [month copy];
CGFloat nextVerticalPosition = 0;
CGFloat startingVerticalPostion = 0;
CGFloat restingVerticalPosition = 0;
CGFloat restingHeight = 0;
NSComparisonResult monthComparisonResult = [month.date compare:fromMonth.date];
NSTimeInterval animationDuration = (monthComparisonResult == NSOrderedSame || !animated) ? 0.0 : 0.5;
NSMutableArray *activeMonthViews = [[NSMutableArray alloc] init];
// Create and position the month views for the target month and those around it
for (NSInteger monthOffset = -2; monthOffset <= 2; monthOffset += 1)
{
NSDateComponents *offsetMonth = [month copy];
offsetMonth.month = offsetMonth.month + monthOffset;
offsetMonth = [offsetMonth.calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday | NSCalendarUnitCalendar fromDate:offsetMonth.date];
// Check if this month should overlap the previous month
if (![self monthStartsOnFirstDayOfWeek:offsetMonth]) {
nextVerticalPosition -= _dayViewHeight;
}
// Create and position the month view
DSLCalendarMonthView *monthView = [self cachedOrCreatedMonthViewForMonth:offsetMonth];
[activeMonthViews addObject:monthView];
[monthView.superview bringSubviewToFront:monthView];
CGRect frame = monthView.frame;
frame.origin.y = nextVerticalPosition;
nextVerticalPosition += frame.size.height;
monthView.frame = frame;
// Check if this view is where we should animate to or from
if (monthOffset == 0) {
// This is the target month so we can use it to determine where to scroll to
restingVerticalPosition = monthView.frame.origin.y;
restingHeight += monthView.bounds.size.height;
}
else if (monthOffset == 1 && monthComparisonResult == NSOrderedAscending) {
// This is the month we're scrolling back from
startingVerticalPostion = monthView.frame.origin.y;
if ([self monthStartsOnFirstDayOfWeek:offsetMonth]) {
startingVerticalPostion -= _dayViewHeight;
}
}
else if (monthOffset == -1 && monthComparisonResult == NSOrderedDescending) {
// This is the month we're scrolling forward from
startingVerticalPostion = monthView.frame.origin.y;
if ([self monthStartsOnFirstDayOfWeek:offsetMonth]) {
startingVerticalPostion -= _dayViewHeight;
}
}
// Check if the active or following month start on the first day of the week
if (monthOffset == 0 && [self monthStartsOnFirstDayOfWeek:offsetMonth]) {
// If the active month starts on a monday, add a day view height to the resting height and move the resting position up so the user can drag into that previous month
restingVerticalPosition -= _dayViewHeight;
restingHeight += _dayViewHeight;
}
else if (monthOffset == 1 && [self monthStartsOnFirstDayOfWeek:offsetMonth]) {
// If the month after the target month starts on a monday, add a day view height to the resting height so the user can drag into that month
restingHeight += _dayViewHeight;
}
}
// Size the month container to fit all the month views
CGRect frame = self.monthContainerViewContentView.frame;
frame.size.height = CGRectGetMaxY([[activeMonthViews lastObject] frame]);
self.monthContainerViewContentView.frame = frame;
// Remove any old month views we don't need anymore
NSArray *monthViewKeyes = self.monthViews.allKeys;
for (NSString *key in monthViewKeyes) {
UIView *monthView = [self.monthViews objectForKey:key];
if (![activeMonthViews containsObject:monthView]) {
[monthView removeFromSuperview];
[self.monthViews removeObjectForKey:key];
}
}
// Position the content view to show where we're animating from
if (monthComparisonResult != NSOrderedSame) {
CGRect frame = self.monthContainerViewContentView.frame;
frame.origin.y = -startingVerticalPostion;
self.monthContainerViewContentView.frame = frame;
}
self.userInteractionEnabled = NO;
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
for (NSInteger index = 0; index < activeMonthViews.count; index++) {
DSLCalendarMonthView *monthView = [activeMonthViews objectAtIndex:index];
for (DSLCalendarDayView *dayView in monthView.dayViews) {
// Use a transition so it fades between states nicely
[UIView transitionWithView:dayView duration:animationDuration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
dayView.inCurrentMonth = (index == 2);
} completion:NULL];
}
}
// Animate the content view to show the target month
CGRect frame = self.monthContainerViewContentView.frame;
frame.origin.y = -restingVerticalPosition;
self.monthContainerViewContentView.frame = frame;
// Resize the container view to show the height of the target month
frame = self.monthContainerView.frame;
frame.size.height = restingHeight;
self.monthContainerView.frame = frame;
// Resize the our frame to show the height of the target month
frame = self.frame;
frame.size.height = CGRectGetMaxY(self.monthContainerView.frame);
self.frame = frame;
// Tell the delegate method that we're about to animate to a new month
if (monthComparisonResult != NSOrderedSame && [self.delegate respondsToSelector:@selector(calendarView:willChangeToVisibleMonth:duration:)]) {
[self.delegate calendarView:self willChangeToVisibleMonth:[month copy] duration:animationDuration];
}
} completion:^(BOOL finished) {
self.userInteractionEnabled = YES;
if (finished) {
// Tell the delegate method that we've animated to a new month
if (monthComparisonResult != NSOrderedSame && [self.delegate respondsToSelector:@selector(calendarView:didChangeToVisibleMonth:)]) {
[self.delegate calendarView:self didChangeToVisibleMonth:[month copy]];
}
}
}];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
DSLCalendarDayView *touchedView = [self dayViewForTouches:touches];
if (touchedView == nil) {
self.draggingStartDay = nil;
return;
}
self.draggingStartDay = touchedView.day;
self.draggingFixedDay = touchedView.day;
self.draggedOffStartDay = NO;
DSLCalendarRange *newRange = self.selectedRange;
if (self.selectedRange == nil) {
newRange = [[DSLCalendarRange alloc] initWithStartDay:touchedView.day endDay:touchedView.day];
}
else if (![self.selectedRange.startDay isEqual:touchedView.day] && ![self.selectedRange.endDay isEqual:touchedView.day]) {
newRange = [[DSLCalendarRange alloc] initWithStartDay:touchedView.day endDay:touchedView.day];
}
else if ([self.selectedRange.startDay isEqual:touchedView.day]) {
self.draggingFixedDay = self.selectedRange.endDay;
}
else {
self.draggingFixedDay = self.selectedRange.startDay;
}
if ([self.delegate respondsToSelector:@selector(calendarView:didDragToDay:selectingRange:)]) {
newRange = [self.delegate calendarView:self didDragToDay:touchedView.day selectingRange:newRange];
}
self.selectedRange = newRange;
[self positionCalloutViewForDayView:touchedView];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
{
if (self.draggingStartDay == nil) {
return;
}
DSLCalendarDayView *touchedView = [self dayViewForTouches:touches];
if (touchedView == nil) {
self.draggingStartDay = nil;
return;
}
DSLCalendarRange *newRange;
if ([touchedView.day.date compare:self.draggingFixedDay.date] == NSOrderedAscending) {
newRange = [[DSLCalendarRange alloc] initWithStartDay:touchedView.day endDay:self.draggingFixedDay];
}
else {
newRange = [[DSLCalendarRange alloc] initWithStartDay:self.draggingFixedDay endDay:touchedView.day];
}
if ([self.delegate respondsToSelector:@selector(calendarView:didDragToDay:selectingRange:)]) {
newRange = [self.delegate calendarView:self didDragToDay:touchedView.day selectingRange:newRange];
}
self.selectedRange = newRange;
if (!self.draggedOffStartDay) {
if (![self.draggingStartDay isEqual:touchedView.day]) {
self.draggedOffStartDay = YES;
}
}
[self positionCalloutViewForDayView:touchedView];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
{
if (self.draggingStartDay == nil)
{
return;
}
DSLCalendarDayView *touchedView = [self dayViewForTouches:touches];
if (touchedView == nil) {
self.draggingStartDay = nil;
return;
}
if (!self.draggedOffStartDay && [self.draggingStartDay isEqual:touchedView.day]) {
self.selectedRange = [[DSLCalendarRange alloc] initWithStartDay:touchedView.day endDay:touchedView.day];
}
self.draggingStartDay = nil;
// Check if the user has dragged to a day in an adjacent month
if (touchedView.day.year != _visibleMonth.year || touchedView.day.month != _visibleMonth.month)
{
// Ask the delegate if it's OK to animate to the adjacent month
BOOL animateToAdjacentMonth = YES;
if ([self.delegate respondsToSelector:@selector(calendarView:shouldAnimateDragToMonth:)])
{
animateToAdjacentMonth = [self.delegate calendarView:self shouldAnimateDragToMonth:[touchedView.dayAsDate dslCalendarView_monthWithCalendar:_visibleMonth.calendar]];
}
if (animateToAdjacentMonth)
{
if ([touchedView.dayAsDate compare:_visibleMonth.date] == NSOrderedAscending)
{
[self didTapMonthBack:nil];
}
else
{
[self didTapMonthForward:nil];
}
}
}
if ([self.delegate respondsToSelector:@selector(calendarView:didSelectRange:)])
{
[self.delegate calendarView:self didSelectRange:self.selectedRange];
}
}
calendarView.h
#import "DSLCalendarRange.h"
#import "NSDate+DSLCalendarView.h"
@protocol DSLCalendarViewDelegate;
@interface DSLCalendarView : UIView
@property (nonatomic, weak) id<DSLCalendarViewDelegate>delegate;
@property (nonatomic, copy) NSDateComponents *visibleMonth;
@property (nonatomic, strong) DSLCalendarRange *selectedRange;
@property (nonatomic, assign) BOOL showDayCalloutView;
@property (nonatomic, assign) BOOL daysSelected;
+ (Class)monthSelectorViewClass;
+ (Class)monthViewClass;
+ (Class)dayViewClass;
- (void)setVisibleMonth:(NSDateComponents *)visibleMonth animated:(BOOL)animated;
- (void)commonInit;
@end
@protocol DSLCalendarViewDelegate <NSObject>
@optional
- (void)calendarView:(DSLCalendarView*)calendarView didSelectRange:(DSLCalendarRange*)range;
- (void)calendarView:(DSLCalendarView *)calendarView willChangeToVisibleMonth:(NSDateComponents*)month duration:(NSTimeInterval)duration;
- (void)calendarView:(DSLCalendarView *)calendarView didChangeToVisibleMonth:(NSDateComponents*)month;
- (DSLCalendarRange*)calendarView:(DSLCalendarView*)calendarView didDragToDay:(NSDateComponents*)day selectingRange:(DSLCalendarRange*)range;
- (BOOL)calendarView:(DSLCalendarView *)calendarView shouldAnimateDragToMonth:(NSDateComponents*)month;