我有一段时间正在构建我自己的日历,因为标准mac cal在布局方面很糟糕。
我所做的是创建一个包含所有日期的NSCollectionView,然后在我的代码中,我将每个日期添加到数组控制器。
到目前为止一切正常并且正在显示!
在这里查看我的ss:http://cl.ly/0Z3a2i12242b2d1m3Z1n
我已经向NSArrayController添加了一个观察者,以便在用户点击日期时知道,这允许我向父类发送消息,告诉它更新cal下的表列表。
我的观察者看起来像这样:
//观察我们的数组 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)对象更改:(NSDictionary *)更改上下文:(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,iam谈论灰显日期)然后观察者被调用两次,因此我的阵列被送回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做塞内斯?我可以临时禁用集合视图上的点击事件吗?
UPDATE2 好的,我尝试添加这个
self.selectedDate = obj.dateobj;
self.currentMonth = [self moveMonth:(NSInteger)-1];
[self.collectionView setSelectable:NO];
[self buildArrayController];
[self.collectionView setSelectable:YES];
删除collecitonview的选择但它不起作用,所以它必须是shomehow被调用两次的观察者..:t
答案 0 :(得分:0)
看起来您的观察者将被调用两次:
在第二个回调中,obj.isOld将为false,所以幸运的是你没有进入这个无限循环。尝试将呼叫转移到
[self.arrayController addObserver:self
forKeyPath:@"selectionIndexes"
options:NSKeyValueObservingOptionNew
context:nil];
到buildArrayController的最后。