2014-01-08 6 views
-4

Я звоню в syncWithCalendar, и после того, как события успешно добавлены, я получаю предупреждение о низкой памяти, и приложение завершается предупреждением «Полученная низкая память». События, сгенерированные и сохраненные в календаре, составляют более 50. Я пытался использовать инструменты, но я не могу найти код, в котором происходит утечка памяти, а также через живые байты, которые отображаются в инструментах. Я не могу отслеживать код, вызывающий протечь. Может кто-нибудь, пожалуйста, помогите мне решить эту проблему.Предупреждение о принимаемой памяти в ARC

- (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 
} 
+2

Проблема, скорее всего, в ваших вызовах 'util'. Вы читаете целую пластину, затем добавляете дополнительные данные в переменные (предположительно избыточные). Не сбрасывайте код здесь. Подумайте, где может быть проблема, и отправляйте выборочный код. – Mundi

+0

Инструменты должны по крайней мере показывать вам «горячие точки», где выделяется огромное количество памяти. Можете ли вы опубликовать представление «Инструменты»? – CouchDeveloper

+0

@Mundi Но я все время читаю plist. И что вы подразумеваете под избытком. Приложение работает нормально во всех других случаях, кроме случаев, когда я использую эти две функции, поэтому я решил, что проблема может заключаться только в этих двух функциях. –

ответ

0

Необходимо очистить кеш при получении предупреждения о памяти, используя этот метод, который вам поможет.

-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application { 

    [[NSURLCache sharedURLCache] removeAllCachedResponses]; 
} 
+0

нет ... это не помогло !!! –

0

Это грубое предположение, но, похоже, асинхронные вызовы могут привести к неприятностям.

Чтобы проверить это, используйте dispatch_sync вместо dispatch_async и изучите расход памяти. Если это приводит к улучшению, то появляется решение, которое включает в себя повторный фактор вашего текущего асинхронного «параллельного» подхода и превращение его в подходящий асинхронный «последовательный» подход или полный синхронный подход.

Это также может потребовать, чтобы «сериализации» всех вызовов этого асинхронного метода:

[eventStore requestAccessToEntityType:EKEntityTypeEvent 
          completion:^(BOOL granted, NSError *error) { 
    ... 
}] 
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] после того, как все события будут сохранены. Это остановило крушение в моем случае. Надеюсь, что этот пост будет помочь другим получить решение. Благодаря !!!!