我正在调用syncWithCalendar,并且在成功添加事件后,我得到内存不足警告,并且应用程序以“Received Low Memory”警告终止。在日历中生成和保存的事件超过50个。我尝试使用仪器,但我无法找到发生内存泄漏的代码,也无法通过仪器中显示的实时字节找到我无法跟踪导致泄漏。任何人都可以帮我解决这个问题。
- (void)syncWithCalendar
{
@autoreleasepool {
[self deleteEventsIfExist];
NSMutableDictionary *dictionary = [util readPListData];
NSMutableArray *courses = [util getCourses];
__block NSMutableArray *lessons;
__block NSMutableDictionary *lesson;
NSString *studentID = [util getProgramDetails].studentId;
NSString *programName = [util getProgramDetails].programName;
double offset[] = {0, 0, -300, -900, -1800, -3600, -7200, -86400, -172800};
__block NSString *startDateString = @"", *endDateString = @"";
NSTimeInterval relativeOffsetValue = 0;
int index = [[dictionary objectForKey:@"event-alert-option"] intValue];
relativeOffsetValue = offset[index];
NSDateFormatter *formatter;
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MM/dd/yyyy HH:mm:ss"];
[formatter setDateFormat:@"MM/dd/yyyy"];
NSString *currentDateString = [NSString stringWithFormat:@"%@ 09:00:00", [formatter stringFromDate:[NSDate date]]];
[formatter setDateFormat:@"MM/dd/yyyy HH:mm:ss"];
NSDate *currentDate = [formatter dateFromString:currentDateString];
EKEventStore *eventStore = [[EKEventStore alloc] init];
if([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {
// iOS 6 and later
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (granted){
//---- codes here when user allow your app to access theirs' calendar.
dispatch_async(dispatch_get_main_queue(), ^{
// Event creation code here.
for (int i=0; i<[courses count]; i++)
{
@autoreleasepool {
lessons = [[courses objectAtIndex:i] objectForKey:@"lessons"];
for (int j=0; j<[lessons count]; j++)
{
@autoreleasepool {
lesson = [lessons objectAtIndex:j];
NSString *title = nil;
title = [NSString stringWithFormat:@"%@ %@-Complete %@ lesson",studentID,programName,[lesson objectForKey:@"lesson-name"]];
if ([[lesson objectForKey:@"actual-exam-date"] isEqualToString:@"00/00/0000"])
{
startDateString = [NSString stringWithFormat:@"%@ %@", [lesson objectForKey:@"plan-exam-date"], @"09:00:00"];
endDateString = [NSString stringWithFormat:@"%@ %@", [lesson objectForKey:@"plan-exam-date"], @"18:00:00"];
}
else
{
if ([[lesson objectForKey:@"retake-actual-date"] isEqualToString:@"00/00/0000"])
{
startDateString = [NSString stringWithFormat:@"%@ %@", [lesson objectForKey:@"retake-plan-date"], @"09:00:00"];
endDateString = [NSString stringWithFormat:@"%@ %@", [lesson objectForKey:@"retake-plan-date"], @"18:00:00"];
}
}
if (!([startDateString isEqualToString:@""] && [endDateString isEqualToString:@""]))
{
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title=title;
event.startDate = [formatter dateFromString:startDateString];
event.endDate = [formatter dateFromString:endDateString];
event.allDay = NO;
if (index != 0)
{
event.alarms = [NSArray arrayWithObjects:[EKAlarm alarmWithRelativeOffset:relativeOffsetValue], nil];
}
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
// Compare current date to event start date, if start date has been passed then preventing to sync with calendar
NSComparisonResult result = [event.startDate compare:currentDate];
if (result != NSOrderedAscending)
{
NSError *err = nil;
[eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
if (err) {
NSLog(@"event not saved .. error = %@",err);
} else {
NSLog(@"event added successfully");
}
}
}
} // autoreleasepool
} // lessons for loop
} // autoreleasepool
} // courses for loop
[self hideModal];
});
}else
{
//----- codes here when user NOT allow your app to access the calendar.
// [self performSelectorOnMainThread:@selector(hideModal) withObject:nil waitUntilDone:NO];
}
}];
} else {
// sync calendar for <iOS6
}
} // autoreleasepool
}
- (void)deleteEventsIfExist
{
@autoreleasepool {
NSMutableArray *courses = [util getCourses];
__block NSMutableArray *lessons;
__block NSMutableDictionary *lesson;
NSString *studentID = [util getProgramDetails].studentId;
NSString *programName = [util getProgramDetails].programName;
EKEventStore* store = [[EKEventStore alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
// Event creation code here.
NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow:[[NSDate distantFuture] timeIntervalSinceReferenceDate]];
NSPredicate *fetchCalendarEvents = [store predicateForEventsWithStartDate:[NSDate date] endDate:endDate calendars:store.calendars];
NSArray *allEvents = [store eventsMatchingPredicate:fetchCalendarEvents];
for (int i=0; i<[courses count]; i++)
{
@autoreleasepool {
lessons = [[courses objectAtIndex:i] objectForKey:@"lessons"];
for (int j=0; j<[lessons count]; j++)
{
@autoreleasepool {
lesson = [lessons objectAtIndex:j];
NSString *oldEventSubtitle = [NSString stringWithFormat:@"%@ %@-Complete %@ lesson",studentID,programName,[lesson objectForKey:@"lesson-name"]];
for (EKEvent *e in allEvents)
{
if ( [oldEventSubtitle isEqualToString:e.title])
{
NSError* error = nil;
[store removeEvent:e span:EKSpanThisEvent commit:YES error:&error];
NSLog(@"deleting events");
}
}
} // autoreleasepool
} // lessons
} // autoreleasepool
} // courses
});
} // autoreleasepool
}
答案 0 :(得分:0)
您需要在收到内存警告时清除缓存,使用此方法可以帮助您。
-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
答案 1 :(得分:0)
这是一个粗略的猜测,但似乎异步调用可能会导致麻烦。
为了测试这一点,只需使用dispatch_sync
而不是dispatch_async
并检查内存消耗。如果这会带来改进,那么就会出现一个解决方案,其中包括重新考虑当前的异步“并行”方法,并将其转换为适当的异步“串行”方法或完整的同步方法。
这可能还需要“序列化”此异步方法的所有调用:
[eventStore requestAccessToEntityType:EKEntityTypeEvent
completion:^(BOOL granted, NSError *error) {
...
}]
答案 2 :(得分:0)
这就是我调用syncWithCalendar
函数
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 syncWithCalendar];
});
} else {
// calendar access not granted
}
}];
}
在syncWithCalendar
函数中,除了代码行之外,一切都保持不变
正在创建崩溃/内存问题。下面是我不正确的代码行
使用较早的
// wrong
[self.eventstore saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
保存事件的正确方法:(注意:在我的情况下我不需要事件标识符)
// correct
[self.eventstore saveEvent:event span:EKSpanThisEvent commit:NO error:&err];
然后在保存所有事件后使用[self.eventstore commit:NULL]
。这阻止了我的崩溃。希望这篇文章能够
帮助其他人获得解决方案。谢谢!!!!