2015-01-27 3 views
1

Я создаю приложение, которое использует GeoFencing. Мои методы didEnterRegion и didExitRegion вызываются так, как они должны, по-видимому, в правильном порядке, но не обновляют пользовательский интерфейс соответственно.сделалEnterRegion и didExitRegion анимация противоречивая

Что работает:

  • Пользователь вводит регион
  • didEnterRegion вызывается
  • UI правильно обновляется в рамках этого метода

Что не работает:

  • пользователя введите область
  • Пользователь идет прямо из одного региона в другой
  • didExitRegion называется
  • обновления пользовательского интерфейса
  • didEnterRegion называется
  • NSLogs показывают, что все выполняется в правильном порядке
  • UI не обновляется. Обновления пользовательского интерфейса, которые были сделаны в didExitRegion, остаются.

Мои методы:

Пользовательские функции для обновления метки (вызывается из didEnterRegion и didExitRegion):

-(void)updateCurrentLocationLabelAndImage:(NSString *)locationText subLocationText:(NSString *)subLocationText; 
{ 
// Clear existing animations before we begin 
[self.locationLabel.layer removeAllAnimations]; 
[self.subLocationLabel.layer removeAllAnimations]; 
[self.ovalImageView.layer removeAllAnimations]; 
if (![locationText isEqual:@""]) 
{ 
    // Only animate if the text changes 
    if (![self.locationLabel.text isEqualToString:locationText]) 
    { 
     // Update the ovalImageView 
     CGSize maxLabelSize = CGSizeMake(([UIScreen mainScreen].bounds.size.width - (([UIScreen mainScreen].bounds.size.width * 0.0267) * 2)), 64); // maximum label size 
     float expectedLabelWidth = [locationText boundingRectWithSize:maxLabelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName:self.locationLabel.font } context:nil].size.width; // get expected width 

     CGFloat xValueForImage = ((([UIScreen mainScreen].bounds.size.width - expectedLabelWidth)/2) - 25); // Calcuate the x-coordinate for the ovalImageView 
     if (xValueForImage < 15) 
     { 
      xValueForImage = 15; // we don't want it to display off-screen 
     } 
     self.ovalImageViewLeadingConstraint.constant = xValueForImage; 
     [self.view setNeedsUpdateConstraints]; 
     [self changeLabelText:self.subLocationLabel string:subLocationText]; 
// Update the subLocationLabel 
     [UIView animateWithDuration:.15 animations:^{ 
      // Animate 
      self.locationLabel.alpha = 0; 
      self.ovalImageView.alpha = 1; 
     [self.view layoutIfNeeded]; // update the UI 
     }completion:^(BOOL finished) { 
      // Set the text 
      self.locationLabel.text = locationText; 
      self.locationLabel.adjustsFontSizeToFitWidth = YES; 
      [UIView animateWithDuration:.15 animations:^{ 
       // Animate 
       self.locationLabel.alpha = 1; 
      }completion:^(BOOL finished) { 
       // Complete 
      }]; 
     }]; 
    } 
} else if ([locationText isEqual:@""]) 
{ 
    // Move it to the center 
    self.ovalImageViewLeadingConstraint.constant = (([UIScreen mainScreen].bounds.size.width/2) - 9); // Default center calculation for this image 
    [self.view setNeedsUpdateConstraints]; 
    [self changeLabelText:self.subLocationLabel string:subLocationText]; // Update the subLocationLabel 
    [UIView animateWithDuration:.15 animations:^{ 
     self.locationLabel.alpha = 0; 
     self.ovalImageView.alpha = 1; 
     [self.view layoutIfNeeded]; 
    }completion:^(BOOL finished) { 
     // Complete 
     self.locationLabel.text = @""; 
    }]; 
} 
} 

Но метка остается неизменным, даже если он регистрирует правильный порядок исполнения и все выглядит отлично. Есть идеи? Я действительно застрял ..

Спасибо!

+0

Откуда берутся журнал «Введенный регион работы ...»? –

+0

Ваше событие ввода региона 2 отменяет значение сразу после выхода из области 1. Попробуйте просмотреть значения на две разные метки и проверьте .. –

+0

@NaveenPrasadR Тестовая метка, которую я добавил, теперь задана правильно – Erik

ответ

0

Чтобы подробно объяснить,

позволяет рассматривать сценарий пользователя выхода REGION1 и прямой ввод REGION2.

Шаг 1:

Таким образом, выход событие вызывается, следующие строки выполняются,

NSLog(@"changing text from: %@, to: %@", label.text, string); 
    // Only animate if the text changes 
    if (![label.text isEqualToString:string]) 

При этом проверьте, если текстовая метка является «внутри региона» (что для региона 1). Поскольку метод вызывается из метода выхода, параметр string будет иметь значение «Внешняя область». Оба значения не одинаковы, и, следовательно, элемент управления входит в эту область.

Шаг 2: На этом этапе вы начали анимацию продолжительностью 0,15, однако значение метки не изменяется до тех пор, пока анимация не будет завершена, так как код находится в блоке завершения.

// Complete 
    label.text = string; 

Шаг 3: ПВН попадают в область 2 событие.Текст метки еще не в курсе, так что возбуждает строку ниже

NSLog(@"changing text from: %@, to: %@", label.text, string); 

Однако поскольку текст метка «в области» и строковое значение также «внутри области», то управление переходит из КРП состояние.

if (![label.text isEqualToString:string]) 

Для проверки:

  1. Pass в настраиваемой строковое значение при вызове текста ярлыка изменения делая конкретный текст а именно, «в области 1», «выхода из региона 1», «внутри региона. 2 "и т. Д. Таким образом, значение будет отличаться и будет обновляться.

  2. Установите значение метки непосредственно перед анимацией.

  3. Назначьте значение для свойства атомной строки и проверьте свойство Value.

для например:

@property (atomic, strong) NSString * currentLabelText; 



-(void)changeLabelText:(UILabel *)label string:(NSString *)string 
{ 
    NSLog(@"changing text from: %@, to: %@", label.text, string); 
    // Only animate if the text changes 

    if (![self. currentLabelText isEqualToString:string]) 
    { 
     self. currentLabelText = string; //Ultimately this would be our value 
     [UIView animateWithDuration:.15 animations:^{ 

     // Animate 
     label.alpha = 0; 
    }completion:^(BOOL finished) { 
     // Complete 
    label.text = self. currentLabelText; 
    [UIView animateWithDuration:.15 animations:^{ 
     // Animate 
     label.alpha = 1; 
    }completion:^(BOOL finished) { 
     // Complete 
    }]; 
}]; 
} 
} 

Или другой способ, как это костюмы ваше требование.

+0

Хмм, я не совсем понимаю, как реализовать в своем коде. Ярлык может содержать другую строку, чем «Inside region something» и т. Д. Мне нужно как-то определить, работает ли анимация в данный момент для данной метки, и если да, переопределите ее – Erik

0

Вы можете попробовать это ...

  static NSString *currentText; 
      currentText = locationText; 

      [UIView animateWithDuration:.15 animations: ^{ 
       // Animate 
       self.locationLabel.alpha = 0; 
       self.ovalImageView.alpha = 1; 
       [self.view layoutIfNeeded]; // update the UI 
      } completion: ^(BOOL finished) { 
       // Set the text 

       if (![currentText isEqualToString:locationText]) { 
        return; 
       } 

       self.locationLabel.text = locationText; 
       self.locationLabel.adjustsFontSizeToFitWidth = YES; 
       [UIView animateWithDuration:.15 animations: ^{ 
        // Animate 
        self.locationLabel.alpha = 1; 
       } completion: ^(BOOL finished) { 
        // Complete 
       }]; 
      }]; 
0

Я бы рекомендовал вам поставить ваш UI код обновления в диспетчерский блок, чтобы убедиться, что UI-Update будет выполняться в основном потоке.

dispatch_async(dispatch_get_main_queue(), ^{ 
    //... UI Update Code 
}); 

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

  • вы смешиваете различные типы данных (с плавающей точкой, CGFloat, Int)

см CocoaTouch64BitGuide это может быть проблемой, но я думаю, что это Безразлично Решить проблему с макетом. Более критическими являются магические числа в целом.

  • код autolayout может быть проблема

Я считаю, что не надо двигаться ovalImageView манипулируя LeadingConstraint. Просто установите contentMode в центр/влево/вправо, и автозапуск выполнит сброс. Если вам действительно нужно изменить ограничение, сделайте это в [yourView updateConstraints]. Если вы хотите, чтобы ширина этикеток просила об этом: [label intrinsicContentsize] и используйте setPreferredMaxLayoutWidth, если вам это нужно. Если ваш код автоопределения верен, не будет отображаться «вне экрана».

  • ваши анимации может быть немного нервный

Вы используете removeAllAnimations на первый.В принципе, но если вы ожидаете высоких частотных обновлений, я бы рекомендовал просто изменить содержимое ярлыков/изображений во время предыдущей анимации. В противном случае изображение скачет назад, и начнется новая анимация.

+0

Я попробую это, но почему лучше убедиться он выполняется по основному потоку? – Erik

+0

@Erik Любые изменения в UI ** должны выполняться на основном потоке. – Lefteris

+0

Я считаю, что вы не поняли проблему. Анимация работает на 100% безупречно, когда я вхожу в область, выхожу за пределы региона, а затем в регион - но если я прыгаю прямо из одного региона в другой, не обращаясь сначала в пустую область, тогда он вызывает метод, который выполняет анимацию дважды , и поэтому текст, отображаемый в UILabel, является неправильным. Но все элементы управления постоянно находятся в правильном месте – Erik

Смежные вопросы