cocoa - objective-c building my own custom calendar (nsarraycontroller observer problems) -


i have time being building own calendar because standard mac cal sucks in terms of layout.

what have done make nscollectionview holds dates, , in code add each date array controller.

so far works fine , cal showing!

take @ ss here: http://cl.ly/0z3a2i12242b2d1m3z1n

i have added observer nsarraycontroller know whenever user clicks date, allows me send message parent class telling update table-list under cal.

my observer looks this:

// observing our array - (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];                 }             }         }     } } 

}

my big problem when user presses date before current month (look @ ss, iam talking grayed-out dates) observer gets called twice , therefor array sent 2 months, iam not sure how counterfight , have been struggling days..

my code building array controller looks this:

- (void) buildarraycontroller {      nslog(@"building array controller");      // remove observer, objects , set selection -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 current month have     nsrange daysinmonth = [self daysinmonth:self.currentmonth];      // save current month int later     int month = [nowcomps month];      // getting days add before month         nsdatecomponents *weekdaycomponents = [self.currentcal components:nsweekdaycalendarunit fromdate:self.currentmonth];     int weekdaystoadd = (([weekdaycomponents weekday] == 1) ? 8 : [weekdaycomponents weekday])-2;      // add days befroe current month, ie when 1st day of month on wednesday f.ex.     nsdate* lastmonth = [self movemonth:-1];     nsrange daysinlastmonth = [self daysinmonth:lastmonth];     nsdatecomponents *lastmonthcomps = [self.currentcal components:(nsyearcalendarunit|nsmonthcalendarunit|nsdaycalendarunit|nsweekdaycalendarunit) fromdate:lastmonth];     (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 month dates     (int = 1; < 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 current month      nsdate* nextmonthobj = [self movemonth:1];     nsdatecomponents *nextmonthcomps = [self.currentcal components:(nsyearcalendarunit|nsmonthcalendarunit|nsdaycalendarunit|nsweekdaycalendarunit) fromdate:nextmonthobj];     (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 our array controller     [self.arraycontroller addobserver:self                            forkeypath:@"selectionindexes"                                options:nskeyvalueobservingoptionnew                               context:nil];      // figure out object should 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];     }    } 

thats it! suggestions?

(btw, if have heads on making code better please tell me, first project in objective-c ever :))

update 'feel' not observer problem somehow, when press before date in cal , method rebuilds array somehows re-send/click on next view when items updated, htis make senes? temporary disable click events on collection view?

update2 okay, tried adding this

                    self.selecteddate = obj.dateobj;                     self.currentmonth = [self movemonth:(nsinteger)-1];                      [self.collectionview setselectable:no];                      [self buildarraycontroller];                      [self.collectionview setselectable:yes]; 

removing selectiable collecitonview not work, must observer shomehow gets called twice.. :t

it looks observer called twice:

  • the user selects new date, before current month. causes change in "selectionindexes" , causes observer method called.
  • in buildarraycontroller, remove observer, make changes reactivate observer. after re-adding observer, call 'setselectionindex' on array controller, causes second observation callback.

on second callback, obj.isold false, luckily don't enter infinite loop of this. try moving call to

[self.arraycontroller addobserver:self                        forkeypath:@"selectionindexes"                            options:nskeyvalueobservingoptionnew                           context:nil]; 

to end of buildarraycontroller.


Comments

Popular posts from this blog

Delphi Wmi Query on a Remote Machine -