NSDateFormatter memory leak? - ios

I have a problem with NSDateFormatter dateFromString: method. There is an array of dictionaries with string dates and I want to convert them to NSDates. But there is a huge heap growth every time I call this method (I need to call it more than once, cause it's an "update" method). Also I call it in background thread and ARC is on. What am I doing wrong? Any help, please.
UPDATE:
Full code of the function:
- (GraphController *) initGraphWithData: (NSArray *) points forInterval: (GraphInterval) interval andFrame: (CGRect) frame gestures: (BOOL) gestures secondGraph: (NSArray *) secondPoints graphNames: (NSArray *) graphNames
{
self = [super init];
_calendar = [NSCalendar currentCalendar];
_secondPoints = secondPoints;
_graphNames = graphNames;
[self.view setFrame:frame];
_points = [[NSMutableArray alloc] init];
double minValue = HUGE_VALF, maxValue = -HUGE_VALF;
NSDate *minDate = [NSDate date], *maxDate = [NSDate dateWithTimeIntervalSince1970:0];
NSMutableDictionary *datesTable = [[NSMutableDictionary alloc] init];
int index = 0;
for(NSArray *pointArray in points){
NSDictionary *point = pointArray[0];
NSMutableDictionary *newPoint = [[NSMutableDictionary alloc] initWithDictionary:point];
// convert date
NSString *dateString = (NSString *)[point objectForKey:#"date"];
NSLog(#"dateString to convert: %#", dateString);
[_dateFormatter setDateFormat:#"MM/dd/yyyy"];
NSDate *date = [_dateFormatter dateFromString: dateString];
[newPoint setObject: date forKey:#"date"];
// convert numbers
[newPoint setObject: [NSNumber numberWithFloat:[((NSString *)[point objectForKey:#"value"]) floatValue]] forKey:#"value"];
if(secondPoints)
[newPoint setObject: [NSNumber numberWithFloat:[((NSString *)[secondPoints[index] objectForKey:#"value"]) floatValue]] forKey:#"secondValue"];
[newPoint setObject: [NSNumber numberWithInt:index] forKey:#"index"];
// min and max
if([[newPoint objectForKey:#"value"] floatValue] < minValue)
minValue = [[newPoint objectForKey:#"value"] floatValue];
if([[newPoint objectForKey:#"value"] floatValue] > maxValue)
maxValue = [[newPoint objectForKey:#"value"] floatValue];
// check second value
if(self.secondPoints){
if([[newPoint objectForKey:#"secondValue"] floatValue] < minValue)
minValue = [[newPoint objectForKey:#"secondValue"] floatValue];
if([[newPoint objectForKey:#"secondValue"] floatValue] > maxValue)
maxValue = [[newPoint objectForKey:#"secondValue"] floatValue];
}
if([[newPoint objectForKey:#"date"] timeIntervalSince1970] > [maxDate timeIntervalSince1970])
maxDate = [newPoint objectForKey:#"date"];
if([[newPoint objectForKey:#"date"] timeIntervalSince1970] < [minDate timeIntervalSince1970])
minDate = [newPoint objectForKey:#"date"];
[self.points addObject:newPoint];
[datesTable setObject:newPoint forKey: [[NSNumber numberWithDouble:[date timeIntervalSince1970]] stringValue] ];
index++;
}
// set draw parameters
_drawVars = [[NSMutableDictionary alloc] init];
NSDate *startSearchDate;
switch (interval) {
case GraphIntervalWeek:
startSearchDate = [maxDate dateByAddingTimeInterval:-7*24*3600];
break;
case GraphIntervalMonth:
startSearchDate = [maxDate dateByAddingTimeInterval: -31*24*3600];
break;
case GraphIntervalSixMonths:
startSearchDate = [maxDate dateByAddingTimeInterval:-6*31*24*3600];
break;
case GraphIntervalYear:
startSearchDate = [maxDate dateByAddingTimeInterval:-365*24*3600];
break;
case GraphIntervalAllTime:
break;
default:
break;
}
NSMutableDictionary *searchPoint;
while(searchPoint == nil && [startSearchDate timeIntervalSince1970] > [minDate timeIntervalSince1970]){
searchPoint = [datesTable objectForKey:[[NSNumber numberWithDouble:[startSearchDate timeIntervalSince1970]] stringValue]];
startSearchDate = [startSearchDate dateByAddingTimeInterval:-24*3600];
}
if(searchPoint != nil && interval != GraphIntervalAllTime)
[self.drawVars setObject:[searchPoint objectForKey:#"index"] forKey:#"startDrawIndex"];
else
[self.drawVars setObject:[NSNumber numberWithInt:0] forKey:#"startDrawIndex"];
[self.drawVars setObject:[[NSNumber numberWithFloat:minValue] copy] forKey:#"minValue"];
[self.drawVars setObject:[[NSNumber numberWithFloat:maxValue] copy] forKey:#"maxValue"];
[self.drawVars setObject:minDate forKey:#"minDate"];
[self.drawVars setObject:maxDate forKey:#"maxDate"];
[self.drawVars setObject:datesTable forKey:#"datesTable"];
// set drawImageView
_drawArea = [[UIImageView alloc] initWithFrame: frame];
[self.view addSubview:self.drawArea];
// set overlayImageView for fingerInpect
_inspectOverlay = [[UIImageView alloc] initWithFrame:frame];
[self.view addSubview:self.inspectOverlay];
// set hintUIView for fingerInspect
_hint = [[Hint alloc] initWithFrame:frame];
[self.hint initHint];
self.hint.hidden = YES;
[self.drawArea addSubview:self.hint];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panHandler:)];
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressHandler:)];
if(gestures)
[self.view addGestureRecognizer:panRecognizer];
[self.view addGestureRecognizer:longPressRecognizer];
return self;
}

I see you are using Heapshot analysis. Good. Here are some more details:
http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/
Now, hopefully, each one of your Heapshot iterations represents doing something in your app that should return it back to the base state. Opening and closing a document, for example.
If that is the case, your data is showing a 500K-600K growth per iteration. That is quite a bit.
Note that trying to analyze the last iteration is generally useless; many of those objects will exist because of whatever the current state of the app is. You really want to focus on that 2nd or 4th iteration.
As for why that specific date or date formatter is leaking, turn on reference count event tracking and then review the retain/release events for one of the leaked objects. There will be some number of extra retains.

Something you are doing right is init the NSDateFormatter before entering the loop. If you are expecting the same date format (MM/dd/yyyy) you can put in the same place you init it as well. It can be that you are allocating too many objects, so I could advise putting everything inside an #autoreleasepool {} (aka: the content of the loop inside the autorelease).
I am seeing you are allocating the *newPoint inside the for and then you are setting the date to that object. What do you do after?

Related

If statement not being called

I'm Simply trying to change the text on a UILabel on a Friday between 4 and 6pm using the below code but the if statement is not being called? I am using a subclass of UILabel via Interface Builder.
- (void)viewDidLoad {
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(targetMethod) userInfo:nil repeats:YES];
}
-(void)targetMethod {
NSLog(#"Called Timer");
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"EEE hh mm"];
NSDate *dt = [NSDate date];
NSString *dayAsString = [formatter stringFromDate:dt];
NSArray *array = [dayAsString componentsSeparatedByString: #""];
if([[array objectAtIndex:0] isEqualToString:#"Friday"] && [[array objectAtIndex:1] intValue]>=4 && [[array objectAtIndex:1] intValue]<=6 && [[array objectAtIndex:2] intValue]>=0 && [[array objectAtIndex:2] intValue] <=59)
{
self.scrollingLabel.text = #"On Air";
NSLog(#"On Air");
}
else
{
self.scrollingLabel.text = #"Off Air";
NSLog(#"Off Air");
}
}
Any help on this would be very much appreciated.
Do you want to split time with spaces string it?
NSArray *array = [dayAsString componentsSeparatedByString:#" "];
And "EEE" will return "Fri", not "Friday".
Also, if you need to manipulate date/time you can look at this library : DateTools
#import "DateTools.h"
NSDate *date = [NSDate date];
if (date.weekday == 6 && date.hour >= 16 && date.hour <= 18) {
NSLog(#"On Air");
}else{
NSLog(#"Off Air");
}
You have made 2 mistakes
[formatter setDateFormat:#"EEE hh mm"]; in this "EEE" will show only 3 characters of day like "Fri".
NSArray *array = [dayAsString componentsSeparatedByString: #""]; will return only one object in array.
Now you need to do
Either change "Friday" to "Fri" in you if condition or use "EEEE" (4E) that will return full name like "Friday".
Separate by single space in NSArray *array = [dayAsString componentsSeparatedByString: #" "];
setDateFormat:#"EEE hh mm"
With 3 E's in the date format, it returns short version of Weekday, like "Fri".
I think you need to change the comparison from "Friday" to "Fri"
Technically, your components are not being separated into individual elements at all. You forgot the space in the quotes after the 'componentsSeparatedByString' method. It should be:
NSArray *array = [dayAsString componentsSeparatedByString: #" "];
I tested it out, and the if statement should be called and return the specified output.
Also, the first element returns only the first three characters of the day, such as 'Tue' for Tuesday. Change Friday to 'Fri' and you should be good.

JavaScriptCore Objective-C Slow When accessing non existing objects

My app slowed down extremely and I ran some tests to find out why.
I ran it twice, the first time accessing an object that is in the context, and the second accessing a non-existing object in the JSContext
I tracked it down to this part:
JSContext *ctx = [[JSContext alloc] init];
[ctx evaluateScript:scpt];
// var someExisting = {"view": {"tint-color": "red"}};
NSDate * start = [NSDate date];
for (int i=0; i<=100000; i++) {
ctx[#"someExisting"][#"view"][#"tint-color"];
}
NSDate * end = [NSDate date];
double timeTaken = [end timeIntervalSinceDate:start] * 1000;
NSLog(#"%g", timeTaken);
[ctx release];
I got 195.697
JSContext *ctx = [[JSContext alloc] init];
[ctx evaluateScript:scpt];
// var someExisting = {"view": {"tint-color": "red"}};
NSDate * start = [NSDate date];
for (int i=0; i<=100000; i++) {
ctx[#"nonExisting"][#"view"][#"tint-color"];
}
NSDate * end = [NSDate date];
double timeTaken = [end timeIntervalSinceDate:start] * 1000;
NSLog(#"%g", timeTaken);
[ctx release];
I got 8377.37! CPU and Memory also spike up
Does anyone know if this is a JavaScriptCore bug or something that I'm doing incorrectly?

Handle Foursquare hours API to find out if the venue is opened or closed

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

Create Events for MBCalendarKit in iOS

I imported MBCalendar Kit into my project, and I don't know how to add an event or array of events in calendar. I found this code:
NSMutableDictionary *eventsDict = [[NSMutableDictionary alloc] init];
for (int i =0; i< eventsArray.count ;i++)
{
// Create events
eventsDict = eventsArray[i];
CKCalendarEvent* aCKCalendarEvent = [[CKCalendarEvent alloc] init];
aCKCalendarEvent.title = [eventsDict objectForKey:#"email"];
aCKCalendarEvent.date = date; //[eventsArray objectForKey:#"phone"];
aCKCalendarEvent.address = [eventsDict objectForKey:#"addrLine1"];
aCKCalendarEvent.image = [eventsDict objectForKey:#"pPic"];
aCKCalendarEvent.name = [eventsDict objectForKey:#"fname"];
aCKCalendarEvent.appDate = [eventsDict objectForKey:#"apntDt"];
aCKCalendarEvent.notes = [eventsDict objectForKey:#"notes"];
aCKCalendarEvent.phone = [eventsDict objectForKey:#"phone"];
[myeventsArray addObject: aCKCalendarEvent];
}
[_data setObject:myeventsArray forKey:date];
but I don't know where to write it, or how to use it. Can anyone help me?
Thank you.
I'm working with this Framework and I've had the same issues.
What worked for me was to use the NSDate+Components category, specifically the dayWithDay:month:year method to create the dates for the events, then create as many events as you want the way you're doing it, encapsulate all the events that are on the same day in an array and lastly setting that array as an object for the NSDictionary data with the previously created as the key to that array. Here's an example:
NSDate *eventDate1 = [NSDate dateWithDay:8 month:8 year:2014];
NSDate *eventDate2 = [NSDate dateWithDay:9 month:8 year:2014];
CKCalendarEvent *event1 = [CKCalendarEvent eventWithTitle:#"Event 1" andDate:eventDate1 andInfo:nil];
CKCalendarEvent *event2 = [CKCalendarEvent eventWithTitle:#"Event 2" andDate:eventDate2 andInfo:nil];
NSArray *today = [NSArray arrayWithObjects:event1, nil];
NSArray *tomorrow = [NSArray arrayWithObjects:event2, nil];
[[self data] setObject:today forKey:eventDate1];
[[self data] setObject:tomorrow forKey:eventDate2];
Hope this helps :D
I'm working on my own framework based on this but with an iOS7 native feel, it's not finished yet but here is the repo:
https://github.com/AndoniV/CalendarBar_iOS7_Style.git

EKEvent is not added according to given EKRecurrenceRule

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).

Resources