2015-07-10 4 views
0

Я работаю над проектом, в котором я должен попробовать выполнить данный метод в течение заданного времени (см. Его как автоматический режим), и если в автоматическом режиме нет преуспеть, переключитесь в ручной режим. Чтобы предупредить вас, я довольно новичок в Objective-C и iOS dev, поэтому ошибка может быть очевидной.Проблема с памятью Objective-C с помощью performSelector и бесконечного цикла

До сих пор, вот что я сделал:

-(void)viewDidLoad { 
    [self performSelector:@selector(autoMode) withObject:nil afterDelay:1.0]; 
    [self performSelectorInBackground:@selector(switchManualMode) withObject:nil]; 
} 


-(void)autoMode { 
    @autoreleasepool { 
     while (isAutoMode == true) { 
      if ([session isRunning]) 
       [self captureImage]; 
       // NSLog(@"test"); 
     } 
    } 
} 

-(void)switchManualMode { 
    [NSThread sleepForTimeInterval:2.0f]; 
    isAutoMode = false; 
    self.button.enabled = true; 

    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Changement de mode" 
                message:@"Du a un délai trop long, la capture automatique va être desactivée. La capture se fait maintenant de manière manuelle Touchez l'écran pour prendre une photo." 
                delegate:nil 
              cancelButtonTitle:@"OK" 
              otherButtonTitles:nil]; 

    [alert show]; 
} 

У меня есть несколько вопросов здесь:
- Первый, что память используется пик и сбои приложения.
- Второе, что switchManualMode никогда не вызывается.

Я попытался просто напечатать «тест» в журналах (вместо того, чтобы на самом деле вызвать функцию «captureImage»), и когда я это делаю, все в порядке.

Я не могу опубликовать код captureImage, но метод пытается получить изображение из AVCaptureSession, а затем обрабатывает его на нем.
В любом случае, я не понимаю, почему switchManualMode вызывается в случае, а не в другом.

+0

несколько заметок: почему '@ autoreleasepool'? вы должны указать, что '[alert show]' должен выполняться до основного потока - в настоящее время вы работаете в фоновом потоке. Захват изображений снова и снова будет приводить к исключительно высокой производительности процессора и памяти. – luk2302

+0

Я добавил @autoreleasepool, потому что это то, что я нашел при поиске решения для выпуска памяти с бесконечными циклами. И [alert show] отлично работает, когда я заменю captureImage на NSLog в комментарии. – Chris

+0

он не будет работать отлично, он не будет определен в какой момент времени будет отображаться вид предупреждения. если он работает для вас прямо сейчас: отлично. он не будет продолжаться. – luk2302

ответ

0

Одна из причин заключается в том, что вы положили @autoreleasepool точно в неправильное место. Он должен быть внутри петля. Вы запускаете бесконечный цикл в пределах тот же пул авторефератов; это требует проблем с памятью. Захват изображений с максимально возможной скоростью точно не помогает.

Другая проблема заключается в том, что performSelector будет работать в основном потоке, поэтому второй выполнитьSelector не будет вызываться, так как первый вызов никогда не возвращается.

Вы действительно должны действительно избавиться от performSelector и переключиться на GCD. Я бы не хотел, чтобы функции performSelector и sleep вызывались в любом коде, написанном сегодня.

+0

Я переместил @autoreleasepool внутри цикла, и память продолжает двигаться. Может быть, некоторые элементы внутри методов captureImage по какой-то причине остаются в памяти? Я буду смотреть в GCD, спасибо. Я знаю, что мой первый performSelector работает в основном потоке, а второй - в фоновом режиме, но как это может случиться, что когда я заменяю вызов captureImage на NSLog, вызывается switchManualMode? Должно ли это называться либо всегда или никогда (поскольку я в бесконечной петле даже с NSLog)? – Chris

0

Я предпочитаю использовать рекурсию для этого типа вещей:

-(void)buttonTappedMethod 
{ 
    [self recusionMethod]; 
} 

-(void)recursionMethod 
{ 
    if(self.isAutoMode) 
    { 
     // ------------------------------------------------ 
     // Do something 
     // 
     // change self.isAutoMode = YES 
     // on condition satisfied in this logic block 
     // ------------------------------------------------ 

     // ------------------------------------------------ 
     // call this method again 
     // ------------------------------------------------ 
     [self recursionMethod]; 
    } 
}