【发布时间】:2011-02-05 10:04:57
【问题描述】:
我有一段时间正在构建自己的日历,因为标准的 mac cal 在布局方面很糟糕。
我所做的是创建一个包含所有日期的 NSCollectionView,然后在我的代码中将每个日期添加到数组控制器中。
到目前为止一切正常,并且显示卡!
在这里看看我的 ss:http://cl.ly/0Z3a2i12242b2d1m3Z1n
我在我的 NSArrayController 中添加了一个观察者,以了解用户何时单击日期,这允许我向我的父类发送一条消息,告诉它更新我在 cal 下的表列表。
我的观察者看起来像这样:
// 观察我们的数组 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([keyPath isEqualTo:@"selectionIndexes"])
{
if([[self.arrayController selectedObjects] count] > 0)
{
if ([[self.arrayController selectedObjects] count] == 1)
{
CalendarDate* obj = [[self.arrayController selectedObjects] objectAtIndex:0];
if(obj.dateobj != nil)
{
if(obj.isOld)
{
self.currentMonth = [self moveMonth:(NSInteger)-1];
self.selectedDate = obj.dateobj;
[self buildArrayController];
}
else {
self.selectedDate = obj.dateobj;
[self callParent];
}
}
}
}
}
}
我的大问题是,当用户按下当前月份之前的日期时(看看 SS,我正在谈论灰色的日期)然后观察者被调用两次,因此我的数组被送回 2 个月,我不知道如何应对这个问题,现在我已经挣扎了好几天了..
我构建数组控制器的代码如下所示:
- (void) buildArrayController {
NSLog(@"Building array controller");
// remove observer, all objects and set selection to -1
[arrayController removeObserver:self forKeyPath:@"selectionIndexes"];
[[self.arrayController content] removeAllObjects];
[self.arrayController setSelectionIndex:-1];
// getting current month
NSDateComponents *nowComps = [self.currentCal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit) fromDate:self.currentMonth];
// figure out how many days the current month have
NSRange daysInMonth = [self daysInMonth:self.currentMonth];
// save current month int for later
int month = [nowComps month];
// getting days to add before this month
NSDateComponents *weekdayComponents = [self.currentCal components:NSWeekdayCalendarUnit fromDate:self.currentMonth];
int weekdaysToAdd = (([weekdayComponents weekday] == 1) ? 8 : [weekdayComponents weekday])-2;
// add days befroe the current month, ie when 1st day of month is on a wednesday f.ex.
NSDate* lastMonth = [self moveMonth:-1];
NSRange daysInLastMonth = [self daysInMonth:lastMonth];
NSDateComponents *lastMonthComps = [self.currentCal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit) fromDate:lastMonth];
for (int i2 = 0; i2 < weekdaysToAdd; i2++)
{
[lastMonthComps setDay:daysInLastMonth.length-weekdaysToAdd+i2+1];
CalendarDate* obj = [[CalendarDate alloc] init];
obj.dateobj = [self.currentCal dateFromComponents:lastMonthComps];
obj.showDot = [coreEditor checkDate:[self.currentCal dateFromComponents:lastMonthComps]];
obj.textColor = [NSColor lightGrayColor];
obj.isOld = YES;
[self.arrayController addObject:obj];
[obj release];
}
// adding actually month dates
for (int i = 1; i < daysInMonth.length+1; i++)
{
[nowComps setDay:i];
CalendarDate* obj = [[CalendarDate alloc] init];
obj.dateobj = [self.currentCal dateFromComponents:nowComps];
obj.showDot = [coreEditor checkDate:[self.currentCal dateFromComponents:nowComps]];
[self.arrayController addObject:obj];
[obj release];
}
// add days after the current month
NSDate* nextMonthobj = [self moveMonth:1];
NSDateComponents *nextMonthComps = [self.currentCal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit) fromDate:nextMonthobj];
for (int i3 = 1; i3 < 7-weekdaysToAdd+1; i3++)
{
[nextMonthComps setDay:i3];
CalendarDate* obj = [[CalendarDate alloc] init];
obj.dateobj = [self.currentCal dateFromComponents:nextMonthComps];
obj.showDot = [coreEditor checkDate:[self.currentCal dateFromComponents:nextMonthComps]];
obj.textColor = [NSColor lightGrayColor];
obj.isOld = YES;
[self.arrayController addObject:obj];
[obj release];
}
// add observer for our array controller
[self.arrayController addObserver:self
forKeyPath:@"selectionIndexes"
options:NSKeyValueObservingOptionNew
context:nil];
// now figure out what object should be selected
NSDateComponents *selectedComp = [self.currentCal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit) fromDate:self.selectedDate];
int selectedMonth = [selectedComp month];
int selectedDay = [selectedComp day]-1;
if(selectedMonth == month)
{
[self.arrayController setSelectionIndex:selectedDay+weekdaysToAdd];
}
else {
[self.arrayController setSelectionIndex:-1];
}
}
就是这样!有什么建议吗?
(顺便说一句,如果您对改进我的代码有任何建议,请告诉我,这是我在 Objective-c 中的第一个项目 :))
更新 我“感觉”问题并不是真正的观察者,而是不知何故,当我在 cal 中按下之前的日期并且我的方法重建数组时,它会以某种方式在项目更新时重新发送/单击下一个视图,htis有道理吗?我可以暂时禁用集合视图上的点击事件吗?
更新2 好的,我尝试添加这个
self.selectedDate = obj.dateobj;
self.currentMonth = [self moveMonth:(NSInteger)-1];
[self.collectionView setSelectable:NO];
[self buildArrayController];
[self.collectionView setSelectable:YES];
删除 collecitonview 的可选择项,但它不起作用,所以必须是观察者 shomehow 被调用两次..:t
【问题讨论】:
标签: objective-c cocoa