didEnterRegion和didExitRegion动画冲突

时间:2015-01-27 18:52:15

标签: ios objective-c location geofencing clregion

我正在构建一个使用GeoFencing的应用。我的didEnterRegion和didExitRegion方法被调用,因为它们应该按照正确的顺序调用,但无法相应地更新UI。

什么有效:

  • 用户输入区域
  • didEnterRegion被调用
  • UI在该方法中正确更新

什么行不通:

  • 用户输入区域
  • 用户直接从一个地区转到另一个地区
  • didExitRegion被称为
  • 用户界面更新
  • didEnterRegion被称为
  • NSLogs表示所有内容都以正确的顺序执行
  • 用户界面未更新。在didExitRegion中完成的UI更新仍然存在。

我的方法:

更新标签的自定义功能(从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 = @"";
    }];
}
}

但标签保持不变,即使它记录了正确的执行顺序,一切看起来都很好。有任何想法吗?我真的卡住了..

谢谢!

3 个答案:

答案 0 :(得分:0)

详细解释,

让我们考虑一个用户退出region1并直接进入region2的场景。

第1步:

因此,触发事件退出,执行以下行,

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

在此If检查时,标签文本是&#34;在区域内&#34; (适用于1区)。由于该方法是从exit方法调用的,因此参数string将具有值&#34;外部区域&#34;。两个值都不相同,因此控件进入该区域。

第2步: 此时,您启动了持续时间为0.15的动画,但是在动画完成之前,标签的值不会更改,因为代码位于完成块中。

   // Complete
    label.text = string;

第3步: 确实进入了区域2事件被解雇了。标签文本尚未更新,因此它会激发以下行

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

然而,由于标签文字是&#34;在区域内&#34;并且字符串值也是&#34;在区域&#34;内,控件移出if条件。

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

验证:

  1. 传入自定义字符串值,同时调用更改标签文本,使文本特定,即#34;区域1&#34;,&#34;退出区域1&#34;,&#34;在区域2&#34;这样,价值会有所不同,并且会更新。

  2. 在动画之前设置标签的值。

  3. 将值分配给原子字符串属性并检查属性值。

  4. 例如:

    @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
        }];
    }];
    }
    }
    

    或其他方式满足您的要求。

答案 1 :(得分: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
                }];
            }];

答案 2 :(得分:0)

我建议您将UI更新代码放在调度块中,以确保UI-Update将在主线程上执行。

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

我猜主线是你最大的问题。对我来说,代码在这一点看起来有点奇怪:

  • 您正在混合不同的数据类型(float,CGFloat,int)

参考CocoaTouch64BitGuide这可能是一个问题,但我认为它无法解决您的布局问题。更重要的是一般的神奇数字。

  • 您的自动布局代码可能有问题

我认为没有必要通过操纵LeadingConstraint来移动ovalImageView。只需将 contentMode 设置为center / left / right,autolayout将执行重置。如果您真的需要更改约束,请在 [yourView updateConstraints] 方法中执行此操作。如果您希望标签宽度要求它: [label intrinsicContentsize] 并在需要时使用 setPreferredMaxLayoutWidth 。如果您的自动布局代码正确无法在屏幕外显示任何视图。

  • 你的动画可能有点跳跃

首先使用removeAllAnimations。基本上是正确但如果你期望高频率的更新,我建议只是在上一个动画运行时更改标签/图像内容。否则,您的图像会跳回,并开始播放新动画。