I'm trying to add an event into calendar with recurrence rule RRULE:FREQ=YEARLY;BYMONTH=6,7;BYDAY=1TH
So according to this rule the event should be added yearly, each 1st thursday of june and july until expire date, which I've set in my project.
In my project, events are created but not according to the recurrence rule. With the following code the events added only on each 1st thursday of june. Why the events are not added on 1st thursday of each july also?
Here is .m file code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self createEvent];
}
- (void)createEvent
{
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title = #"testRecurrenceRule";
event.location = #"Dhaka";
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
event.startDate = [self dateFromString:#"2013-06-18T21:00:00+06:00"];
event.endDate = [self dateFromString:#"2013-06-18T22:00:00+06:00"];
id recurrenceRule = [self recurrenceRuleForEvent];
if(recurrenceRule != nil)
[event addRecurrenceRule:recurrenceRule];
if ([eventStore respondsToSelector:#selector(requestAccessToEntityType:completion:)])
{
// iOS 6 and later
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (granted)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self saveTheEvent:event eventStore:eventStore];
//[eventStore saveEvent:event span:EKSpanThisEvent error:error];
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
//do nothing
});
}
}];
}
else
{
[self saveTheEvent:event eventStore:eventStore];
}
textView.text = [NSString stringWithFormat:#"Event has been added with recurrence rule %#",recurrenceRule];
}
- (void)saveTheEvent:(EKEvent *)aEvent eventStore:(EKEventStore *)aStore
{
[aStore saveEvent:aEvent span:EKSpanThisEvent error:NULL];
}
- (EKRecurrenceRule *)recurrenceRuleForEvent
{
//just creating a recurrence rule for RRULE:FREQ=YEARLY;BYMONTH=6,7;BYDAY=1TH
// setting the values directly for testing purpose.
//FREQ=YEARLY
EKRecurrenceFrequency recurrenceFrequency = EKRecurrenceFrequencyYearly;
NSInteger recurrenceInterval = 1;
EKRecurrenceEnd *endRecurrence = nil;
NSMutableArray *monthsOfTheYearArray = [NSMutableArray array];
NSMutableArray *daysOfTheWeekArray = [NSMutableArray array];
NSMutableArray *daysOfTheMonthArray = [NSMutableArray array];
NSMutableArray *weeksOfTheYearArray = [NSMutableArray array];
NSMutableArray *daysOfTheYearArray = [NSMutableArray array];
NSMutableArray *setPositionsArray = [NSMutableArray array];
//BYMONTH=6,7
[monthsOfTheYearArray addObject:[NSNumber numberWithInt:6]];
[monthsOfTheYearArray addObject:[NSNumber numberWithInt:7]];
//BYDAY=1TH
[daysOfTheWeekArray addObject:[EKRecurrenceDayOfWeek dayOfWeek:5 weekNumber:1]];
endRecurrence = [EKRecurrenceEnd recurrenceEndWithEndDate:[self dateFromString:#"2018-12-15T22:30+06:00"]];
EKRecurrenceRule *recurrence = [[EKRecurrenceRule alloc] initRecurrenceWithFrequency:recurrenceFrequency
interval:recurrenceInterval
daysOfTheWeek:daysOfTheWeekArray
daysOfTheMonth:daysOfTheMonthArray
monthsOfTheYear:monthsOfTheYearArray
weeksOfTheYear:weeksOfTheYearArray
daysOfTheYear:daysOfTheYearArray
setPositions:setPositionsArray
end:endRecurrence];
return recurrence;
}
- (NSDate *)dateFromString:(NSString *)string
{
//check if the date string in null
if ([string length] == 0)
return nil;
NSString *dateString = nil;
NSString *modifiedString = nil;
BOOL secSpotMissing = false;
NSRange range = [string rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:#"T"]];
if (range.location != NSNotFound)
{
dateString = [string substringFromIndex:range.location];
range = [dateString rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:#"+-Z"]];
if (range.location != NSNotFound)
{
//seperate the time portion of date string and checking second field is missing or not. like is it HH:mm or HH:mm:ss?
if ([[[dateString substringToIndex:range.location] componentsSeparatedByString:#":"] count] < 3)
secSpotMissing = true;
//seperate the time zone portion and checking is there any extra ':' on it. It should like -0600 not -06:00. If it has that extra ':', just replacing it here.
dateString = [dateString substringFromIndex:range.location];
if([dateString hasSuffix:#"Z"])
modifiedString = [dateString stringByReplacingOccurrencesOfString:#"Z" withString:#"+0000"];
else
modifiedString = [dateString stringByReplacingOccurrencesOfString:#":" withString:#""];
string = [string stringByReplacingOccurrencesOfString:dateString withString:modifiedString];
}
}
else
return nil;
// converting the date string according to it's format.
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
if (secSpotMissing)
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mmZZZ"];
else
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ssZZZ"];
return [dateFormatter dateFromString:string];
}
Can somebody please help me regarding this?
This seems a repeat of another question. Basically, according to "BYDAY" rule, the 1st for YEARLY frequency means the first week in the year - instead of 1st week each month.
#Shuvo, I did not read rfc. But here is Apple document EKRecurrenceDayOfWeek.
The EKRecurrenceDayOfWeek class represents a day of the week for use with an EKRecurrenceRule object. A day of the week can optionally have a week number, indicating a specific day in the recurrence rule’s frequency. For example, a day of the week with a day value of Tuesday and a week number of 2 would represent the second Tuesday of every month in a monthly recurrence rule, and the second Tuesday of every year in a yearly recurrence rule.
When you say "1st Thursday", that is correct - except in the context of yearly, it is 1st thursday of the year.
The bug was confirmed by Apple, at least until iOS 7.1.3 (which is the latest available version at this moment).
Related
I have three subscription plans in in-app-purchase 1 month,6 months,1 year so i want to check the users current subscription plan and date of expire so what i am doing right now is from receipt getting latest_receipt_info in that I am using the last object.
from the last object, I am taking product_id and using it as a current subscription plan and expires_date used to check active or not.
Below is the block of code I am using.
So is this the correct approach?
if([dict[#"status"] integerValue] == 0) {
if([dict.allKeys containsObject:#"latest_receipt_info"]) {
NSArray *iapReceipts = dict[#"latest_receipt_info"];
if(iapReceipts) {
if(iapReceipts.count > 0) {
NSDictionary *latestReceipt = [iapReceipts lastObject];
if(latestReceipt) {
_currentIAPID = latestReceipt[#"product_id"];
NSDate *expireDate = latestReceipt[#"expires_date"];
if(expireDate) {
NSInteger days = DaysBetween(NSDate.date, expireDate);
if(days >= 0) {
NSLog(#"days %ld",(long)days);
status = SubscriptionStatusActive;
} else {
NSLog(#"Subs :NEGATIVE DAYS");
status = SubscriptionStatusExpired;
}
}
}
}
}
}
}
Any suggestions would be more helpful.
No, it's not a correct approach. You shouldn't get last object because that array is not sorted. It contains all your transactions including all renewals. This example code doesn't take into account cancellation_date:
- (void)parseResponse:(NSDictionary*)dict{
if ([dict[#"status"] integerValue] != 0) {return;}
NSArray *iapReceipts = dict[#"latest_receipt_info"];
NSDateFormatter *formatter = [NSDateFormatter new];
formatter.dateFormat = #"yyyy-MM-dd HH:mm:ss VV";
for (NSDictionary *iapReceipt in iapReceipts){
NSString *productID = iapReceipt[#"product_id"];
NSDate *date = [formatter dateFromString:iapReceipt[#"expires_date"]?:#""];
if (date && [date timeIntervalSinceDate:[NSDate date]] > 0){
[[NSUserDefaults standardUserDefaults] setObject:date forKey:productID];
}
}
}
- (BOOL)isSubscriptionActive:(NSString*)productID {
NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:productID];
if (date && [date timeIntervalSinceDate:[NSDate date]] > 0){
return YES;
} else {
return NO;
}
}
I am using a Calendar view in my project. I am using a MBCalendarKit. That time single date in single event show. But I want single date on multiple events show. But how it possible please help.
- (void) viewWillAppear: (BOOL)animated{
NSArray *title = [_caldevice valueForKey:#"pill"];
// NSLog(#"event name fetch %#",title);
NSArray *date =[_caldevice valueForKey:#"datetaken"];
// NSLog(#"event fetch %#",date);
NSArray*dose= [_caldevice valueForKey:#"dose"];
NSString *title1;
NSString*title2;
NSDate *date1;
NSData *imgdata;
CKCalendarEvent *releaseUpdatedCalendarKit;
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"dd-MM-yyyy";
for (int i = 0; i < [date count]; i++){
title1 = NSLocalizedString(title[i], #"");
title2 = NSLocalizedString(dose[i], #"");
NSString *combined = [NSString stringWithFormat:#"%# - %#", title1, title2];
date1 = [dateFormatter dateFromString:date[i]];
releaseUpdatedCalendarKit = [CKCalendarEvent eventWithTitle:combined andDate:date1 andInfo:Nil];
// NSLog(#"Event: %# , %#",combined,date1);
// releaseUpdatedCalendarKit = [CKCalendarEvent eventWithTitle:combined andDate:date1 andInfo:Nil andColor:[UIColor blueColor]];
self.data[date1] = #[releaseUpdatedCalendarKit];
}
}
You're looping over a bunch of events and for each event, you're *replacing the previously assigned array with a new one, containing a single element.
Replace this:
self.data[date1] = #[releaseUpdatedCalendarKit];
with something more like this:
// 1. First, get the previous events for that day.
NSMutableArray <CKCalendarEvent *> *events = self.data[date1].mutableCopy;
// 2. If events exist, append the event, otherwise create an empty array with the new event.
if (events) {
[events addObject: newEvent];
}
else {
events = #[newEvent];
}
// 3. Set the events for the date key.
self.data[date1] = events;
This way you're doing an "add or create" operation, instead of overwriting each time.
Disclosure: I wrote and maintain MBCalendarKit.
I have a foursquare hours array (Foursquare API) that stores segments of hours when a specific venue is open. It looks something like this:
[{
"days":[1,2,3,4,7],
"includesToday":true,
"open":[
{"end":"+0200","start":"1000"}],
"segments":[]},
{
"days":[5,6]
,"open":[
{"end":"+0300","start":"1000"}],
"segments":[]}
]
How do I find out if the venue is opened or closed at current time?
I handle it like this: 4sq hours API gist
-(NSDictionary*)isVenueOpenDictionaryForHours:(NSArray*)hours{
// defaults and inits
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDictionary *lastSegmentYesterday = [[NSDictionary alloc] init];
NSDate *dateNow = [NSDate date];
NSString *venueOpenText = [[NSString alloc] init];
NSString *venueOpen = #"no";
// get components for today
NSDateComponents *compsNow = [gregorian components:NSWeekdayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:dateNow];
// get weekday for today and yesterday so we can lookup 4sq API
NSInteger weekday = [compsNow weekday];
NSInteger weekdayYesterday = (weekday>1)?weekday-1:7;
// look for todays' segment
NSMutableArray *venueOpenSegments = [[NSMutableArray alloc] init]; // stores all the segments when the venue is open
for (NSDictionary *segment in hours){
// get today's segment (if it exists)
if ([segment[#"days"] containsObject:[NSNumber numberWithInteger:weekday]]){
for (NSDictionary *dictOpen in segment[#"open"])
[venueOpenSegments insertObject:#{#"end": [dictOpen[#"end"] mutableCopy], #"start":[dictOpen[#"start"] mutableCopy]}.mutableCopy atIndex:venueOpenSegments.count];
}
// check the day before if the venue is open past midnight
if (([segment[#"days"] containsObject:[NSNumber numberWithInteger:weekdayYesterday]] && [segment[#"open"] count])){
// get the last segment (that should be the one passing midnight)
NSDictionary *tempSegment = [segment[#"open"] lastObject];
// if it has more than 4 characters it's after midnight ("+02:00"), also, ignore if it closes at midnight
if ([tempSegment[#"end"] length] > 4 && ![tempSegment[#"end"]isEqualToString:#"+0000"]){
// create a new segment that starts at midnight and lasts till the time it closes (early AMs usually)
lastSegmentYesterday = #{#"start":#"0000", #"end":[tempSegment[#"end"] substringFromIndex:1]};
}
}
}
// add last night segment that passes midnight as the first segment of today
if (lastSegmentYesterday.count){
[venueOpenSegments insertObject:lastSegmentYesterday atIndex:0];
}
// go through all the segments and find out if the venue is closed or open
if (venueOpenSegments.count){
NSDateComponents *comps = [[NSDateComponents alloc] init];
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc]init];
timeFormatter.dateFormat = #"HH:mm"; // set time output format
int segmentNumber = 0;
for (NSMutableDictionary *segment in venueOpenSegments){
segmentNumber++;
// confing start date
[comps setDay:compsNow.day];
[comps setMonth:compsNow.month];
[comps setYear:compsNow.year];
[comps setHour:[[segment[#"start"] substringToIndex:2] intValue]];
[comps setMinute:[[segment[#"start"] substringFromIndex:2] intValue]];
NSDate *dateStart = [[[NSCalendar currentCalendar] dateFromComponents:comps] copy];
// config end date
// check if the segment goes to next day
BOOL closesTomorrow = NO;
if ( [segment[#"end"] length]==5 ){
segment[#"end"] = [segment[#"end"] substringFromIndex:1];
closesTomorrow = YES;
}
[comps setHour:[[segment[#"end"] substringToIndex:2] intValue]];
[comps setMinute:[[segment[#"end"] substringFromIndex:2] intValue]];
NSDate *dateEnd = [[[NSCalendar currentCalendar] dateFromComponents:comps] copy];
// add a day if it closes tomorrow
if (closesTomorrow){
NSDateComponents *nextDayComponent = [[NSDateComponents alloc] init];
nextDayComponent.day = 1;
dateEnd = [gregorian dateByAddingComponents:nextDayComponent toDate:dateEnd options:0];
}
// start checking if it's open or closed
// now < segment start
if ([dateNow compare:dateStart] == NSOrderedAscending){
venueOpenText = [NSString stringWithFormat:#"opens at %#",[timeFormatter stringFromDate: dateStart]];
venueOpen = #"later";
break;
}
// segment end < now
else if ([dateEnd compare:dateNow] == NSOrderedAscending){
if (segmentNumber == venueOpenSegments.count){
venueOpenText = [NSString stringWithFormat:#"closed since %#",[timeFormatter stringFromDate: dateEnd]];
break;
}
continue;
}
// segment start < now < segment end
else if ([dateStart compare:dateNow] == NSOrderedAscending && [dateNow compare:dateEnd] == NSOrderedAscending){
venueOpenText = [NSString stringWithFormat:#"open till %#",[timeFormatter stringFromDate: dateEnd]];
venueOpen = #"yes";
break;
}
// rare but possible... last minute of the venue being open (I treat it as closed)
else {
venueOpenText = #"closing right now";
}
}
}
else venueOpen = #"closed today"; // no segments for today, so it's closed for the dayæ
// return results
return #{#"open":venueOpen, #"string":venueOpenText};
}
and I update my UILabel like this:
NSDictionary *venueOpen = [self isVenueOpenDictionaryForHours:_arrayVenues[indexPath.row][#"hours"]];
label.text = venueOpen[#"string"];
if ([venueOpen[#"open"] isEqualToString:#"no"]){
label.textColor = [UIColor colorWithHexString:#"b91d47" alpha:1]; // red
} else if ([venueOpen[#"open"] isEqualToString:#"yes"]) {
label.textColor = [UIColor colorWithHexString:#"1e7145" alpha:1]; // green
} else if ([venueOpen[#"open"] isEqualToString:#"later"]) {
label.textColor = [UIColor colorWithHexString:#"e3a21a" alpha:1]; // yellow
}
BTW, I use pod 'HexColors' for colorWithHexString methods
I have been testing this code to add a calendar to IOS Cal App, and also add some events to that specific calendar in the app.
I have an Ipad with IOS7, iCloud disabled.
First problem is when I create calendar I can't see newly created calendar in iPad's iCal App,Isn't that app supposed to show all calendars even if they are not added to iCloud?
second problem is my code keep adding same events every time I call that code.
Lets say I call the add function and it adds 3 events successfully firs time, next time when call that function with same events it supposed to skip adding but it adds that 3 events to calendar again now I have duplicate events, and so on...
-(void) initCalendar:(NSDictionary *)dataDict
{
self.eventStore = [[EKEventStore alloc] init];
if([self.eventStore respondsToSelector:#selector(requestAccessToEntityType:completion:)]) {
// iOS 6 and later
[self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (granted){
//---- codes here when user allow your app to access theirs' calendar.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.isCalendarAccepted=YES;
NSLog(#"self.isCalendarAccepted=YES;");
if ([defaults objectForKey:#"Calendar"] == nil) // Create Calendar if Needed
{
EKSource *theSource = nil;
for (EKSource *source in self.eventStore.sources) {
if (source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:#"iCloud"]) {
theSource = source;
NSLog(#"iCloud Store Source");
break;
} else {
for (EKSource *source in self.eventStore.sources) {
if (source.sourceType == EKSourceTypeLocal) {
theSource = source;
NSLog(#"ios Local Store Source");
break;
}
}
}
}
//EKCalendar *calendar = [EKCalendar calendarWithEventStore:self.eventStore];
EKCalendar *calendar =[EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:self.eventStore];
calendar.title = #"My App Name";
if (theSource) {
calendar.source = theSource;
} else {
NSLog(#"Error: Local source not available");
return;
}
NSError *errorCalendar = nil;
BOOL result = [self.eventStore saveCalendar:calendar commit:YES error:&errorCalendar];
if (result) {
NSLog(#"Saved calendar to event store.");
[[NSUserDefaults standardUserDefaults] setObject:calendar.calendarIdentifier forKey:#"Calendar"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
NSLog(#"Error saving calendar: %#.", errorCalendar);
}
}
//start adding event to calendar
[self addSelectedOwnEventsToCalendar:dataDict];
}
}];
}
}
-(void)addSelectedOwnEventsToCalendar:(NSDictionary *)dataDict
{
// Create a new event... save and commit
NSError *error = nil;
EKEvent *myEvent = [EKEvent eventWithEventStore:self.eventStore];
myEvent.allDay = NO;
myEvent.availability = EKEventAvailabilityFree;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *startDate = [[NSDate alloc] init];
NSString *startDateFormatted=[NSString stringWithFormat:#"%# %#",[dataDict objectForKey:#"start_date"],[dataDict objectForKey:#"starts"]];
startDate = [dateFormatter dateFromString:startDateFormatted];
NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *endDate = [[NSDate alloc] init];
NSString *endDateFormatted=[NSString stringWithFormat:#"%# %#",[dataDict objectForKey:#"end_date"],[dataDict objectForKey:#"ends"]];
endDate = [dateFormatter1 dateFromString:endDateFormatted];
//compare dates
NSComparisonResult result = [startDate compare:endDate];
if (result == NSOrderedAscending) {
} else if (result == NSOrderedDescending) {
} else {
//the same
endDate=[startDate dateByAddingTimeInterval:60];
}
myEvent.startDate=startDate;
myEvent.endDate = endDate;
myEvent.title = [dataDict objectForKey:#"event_id"];
myEvent.calendar = [self.eventStore calendarWithIdentifier:[[NSUserDefaults standardUserDefaults] objectForKey:#"Calendar"]];
myEvent.location=[dataDict objectForKey:#"location"];
NSArray *cals = [self.eventStore calendarsForEntityType: EKEntityTypeEvent];
NSPredicate *predicateForEventsOnHolidayDate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:cals]; // nil will search through all calendars
NSArray *eventsOnHolidayDate = [self.eventStore eventsMatchingPredicate:predicateForEventsOnHolidayDate];
//NSLog(#"eventsOnHolidayDate %#",eventsOnHolidayDate);
BOOL eventExists = NO;
for (EKEvent *eventToCheck in eventsOnHolidayDate) {
NSLog(#"eventToCheck.title %#",eventToCheck.title);
NSLog(#"event_id %#",[dataDict objectForKey:#"event_id"]);
if ([eventToCheck.title isEqualToString:[dataDict objectForKey:#"event_id"]]) {
eventExists = YES;
NSLog(#"Event Already Exists");
}
}
//save eventts
if (eventExists == NO) {
[self.eventStore saveEvent:myEvent span:EKSpanThisEvent commit:YES error:&error];
if (!error) {
// NSLog(#"the event saved and committed correctly with identifier %#", myEvent.eventIdentifier);
} else {
NSLog(#"there was an error saving and committing the event");
NSLog(#"Error %#",error);
error = nil;
}
}
}
When I first run the code NSlog says (#"ios Local Store Source");
What am I missing?
Note: Code is working on simulator(Ipad ios 7) most of the time, I assuming something wrong with [NSUserDefaults] ?
First, see the discussion points about duplicates in the calendarItemExternalIdentifier documentation and determine if any of them apply.
Then, take a look at the following suggestions:
The calendar identifier can change. Ensure that the saved version for key Calendar in NSUserDefaults is the same as the one being accessed in addSelectedOwnEventsToCalendar:.
When retrieving the calendar identifier from the NSUserDefaults make sure that it’s valid.
Try using the saveEvent:span:error: method without the commit parameter. I’ve had problems using the save event method that takes a commit argument in the past.
Lastly, I believe that iOS calendar access authorization can only be tested on an iOS device, which is probably why it’s working in the simulator.
I am using Tapku library for calendar implementation. I could see that there is a way to add Markers for predefined start and end date but I want to allow users to select/unselect any number of dates from current month only, and want to generate event for each action.
Moreover, I have switched off the month navigation functionality by returning nil for Left and Right arrow to display only current month but not able to remove events for few previous and next months Date tiles that gets displayed on current month. I can still select previous month's day 31st to navigate to previous month or select 1st on next month to navigate to next month. Can I restrict the date selection to only current month please?
Thanks.
The touches are handled in TKCalendarMonthView.m in the following method:
- (void) reactToTouch:(UITouch*)touch down:(BOOL)down
look at the block at row 563:
if(portion == 1)
{
selectedDay = day;
selectedPortion = portion;
[target performSelector:action withObject:[NSArray arrayWithObject:[NSNumber numberWithInt:day]]];
}
else if(down)
{
// this is the important part for you.
// ignore it by adding a return here (or remove the following three lines)
return;
[target performSelector:action withObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:day],[NSNumber numberWithInt:portion],nil]];
selectedDay = day;
selectedPortion = portion;
}
The selecting/deselecting perhaps doesn't work as you expect. It's not like setDateSelected and setDateDeselected.. instead there is a single UIImageView*, which represents the selected state. And that view is moved around to the current position. You can search for self.selectedImageView in the code to see, what is happening.
So its not that easy to introduce multiple-date-selection. The architecture isn't built for that.
In TKCalendarMonthView there is a method name
-(void) reactToTouch:(UITouch*)touch down:(BOOL)down
in that method comment this line
[target performSelector:action withObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:day],[NSNumber numberWithInt:portion],nil]];
this wont allow you to change month.
You can store all selected date in an array and pass all the values in
- (NSArray*)calendarMonthView:(TKCalendarMonthView *)monthView marksFromDate:(NSDate *)startDate toDate:(NSDate *)lastDate
The above method is used to put tiles but if u want selection image then u can replace it with tile image
You can also try this code:
You can do this by first entering the dates in to an array. code for this is.
- (void)calendarMonthView:(TKCalendarMonthView *)monthView didSelectDate:(NSDate *)d {
NSLog(#"selected Date IS - %#",inDate);
[myArray addObject:d];
for (id entry in myArray)
{
if (inDate == nil && outDate == nil)
{
inDate = d;
outDate = d;
}
if ([d compare:inDate] == NSOrderedAscending)
{
inDate = d;
}
if ([d compare:outDate] == NSOrderedDescending)
{
outDate = d;
}
d = nil;
}
}
After this you have to use a button click action by which you can make the dates selected between these two dates. Code for it is:
- (IBAction)goBtn:(id)sender
{
NSLog(#"startDate is: %#",inDate);
NSLog(#"endDate is: %#",outDate);
[calendar reload];
inDate = nil;
outDate = nil;
}
}
Then in one delegate method you just have to make an array containing all the dates between these two dates. It will be called just after the button click. Code for it is:
- (NSArray*)calendarMonthView:(TKCalendarMonthView *)monthView marksFromDate:(NSDate *)startDate toDate:(NSDate *)lastDate {
//***********
NSMutableArray *tempData = [[NSMutableArray alloc] init];
NSDate *nextDate;
for ( nextDate = inDate ; [nextDate compare:outDate] < 0 ; nextDate = [nextDate addTimeInterval:24*60*60] ) {
// use date
NSLog(#"%#",nextDate);
[tempData addObject:[NSString stringWithFormat:#"%#",nextDate]];
}
[tempData addObject:[NSString stringWithFormat:#"%#",outDate]];
//***********
NSMutableArray *marks = [NSMutableArray array];
NSCalendar *cal = [NSCalendar currentCalendar];
[cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDateComponents *comp = [cal components:(NSMonthCalendarUnit | NSMinuteCalendarUnit | NSYearCalendarUnit |
NSDayCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit)
fromDate:startDate];
NSDate *d = [cal dateFromComponents:comp];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:1];
while (YES) {
if ([d compare:lastDate] == NSOrderedDescending) {
break;
}
if ([tempData containsObject:[d description]]) {
[marks addObject:[NSNumber numberWithBool:YES]];
} else {
[marks addObject:[NSNumber numberWithBool:NO]];
}
d = [cal dateByAddingComponents:offsetComponents toDate:d options:0];
}
return [NSArray arrayWithArray:marks];
}
I hope, this helped you. Please let me know if you face any problem.