为啥我的 UIView 动画到错误的位置?

Posted

技术标签:

【中文标题】为啥我的 UIView 动画到错误的位置?【英文标题】:Why does my UIView animate to the wrong position?为什么我的 UIView 动画到错误的位置? 【发布时间】:2013-10-20 04:15:40 【问题描述】:

我在 UIView hardWayView 中有一个 UILabel hardWayLabel。我需要这个视图(以及标签)来动画到屏幕最左侧的一个新位置。然而,当标签移动到正确的位置时,可以看到视图继续远离屏幕左侧。我将以下代码用于动画(我在我的应用程序中成功使用了很多次):

        CGRect frame = hardWayView.frame;
        frame.origin.x = painPoint.x;
        frame.origin.y = painPoint.y;
        hardWayView.frame = frame;
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:.25];

我已经使用 NSLog 来确保 painPoint.x 和 painPoint.y 是它们应该是的 9,这可以通过 UILabel 最终位于正确位置的事实得到证实。我想真正的问题是为什么 UIView 会继续移动越过屏幕边界(并且只有在这种情况下,当 UIView 从屏幕中心向左移动时才会这样做)?

我确实启用了自动布局,但我不认为这是罪魁祸首。当我在带有 ios 7 的 iPhone 模拟器上运行应用程序时会出现此问题,并且我无法让模拟器在 iOS 6 上运行,因此无法将问题隔离到 iOS 7(虽然可能吗?我开始在旧版本的 Xcode 并且该应用程序不使用情节提要)。

这是该问题的屏幕录像。如您所见,将两个视图从左向右移动正常工作。尽管将视图移回左侧时,其中一个视图(黑色背景)似乎从左上角离开屏幕,而标签(橙色文本)则转到正确的位置)。 Explanatory video

更新:这里有更多代码。它与我的应用程序中完美运行的其他部分几乎相同,这有点像大脑冲击波。

NSString *stringOfRands = tDict[@"originalRand"];
if ([stringOfRands rangeOfString:@"+"].location != NSNotFound)

     NSArray *arrayOfRands = [stringOfRands componentsSeparatedByString:@" + "];

     for (int z=1; z<[arrayOfRands count]; z++)
     
          NSString *updateValue = arrayOfRands[z];
          NSInteger newHiddenPosition = [self findBlank:leftSpaces];

          NSDictionary *updateStuff = @@"updateValue": updateValue, @"workingMasterDict":tDict, @"newPos":@(newHiddenPosition), @"newCGPto":@"left", @"@parent":colorV;

          [self revealHidden:updateStuff];

       

我相信问题确实发生在调用动画的 revealHidden 方法期间。

[leftSpaces replaceObjectAtIndex:[hardWayPos intValue] withObject:[NSString stringWithFormat:@"full"]];
CGPoint painPoint = [[leftPoints objectAtIndex:[hardWayPos intValue]] CGPointValue];    
[UIView animateWithDuration:0.25 animations:^
        CGRect frame = hardWayView.frame;
        frame.origin.x = painPoint.x;
        frame.origin.y = painPoint.y;
        hardWayView.frame = frame;
     completion:^(BOOL finished) 
        //
    ];

hardWayView.hidden=0;
hardWayView.backgroundColor = [UIColor blueColor];
hardWayLabel.textColor = [UIColor orangeColor];

我尝试制作 frame.origin.x.y 实际数字(相对于变量),然后出现相同的模式:UILabel 动画到正确的位置,而 UIView 动画从屏幕的左上角关闭

【问题讨论】:

关闭自动布局并测试它。这可能是罪魁祸首。 @Joel 唉,没有。关闭自动布局时也会发生同样的动作。 首先修改帧然后开始动画。 @zch,您介意分享您的项目,以便我在最后看看吗? @LuisCien 感谢您抽出宝贵时间。我刚刚在原始问题中添加了更多代码,但我也刚刚将 viewcontroller.h 和 .m 添加到 Github 存储库 github.com/zchr/modx (我真的很抱歉缺乏清洁度,我在上面添加了 ERROR HERE cmets有问题的代码sn-ps。值得注意的一点是重复量。首先这意味着我需要制作更多方法,但其次我认为有趣的是,相同的动画代码在应用程序的其他区域也能正常工作.) 【参考方案1】:

哇哦!经过muuuch调试,我终于找到了问题! :) 让我告诉你......你有一些有趣的代码。无论如何,您会惊讶地发现这个问题有多愚蠢;你准备好了吗?

问题来了:

在第 540 行附近,您有一个额外的“@”符号,这就是为什么当您尝试检索它无法找到它的值时:

//ERROR HERE
NSArray *arrayOfRands = [stringOfRands componentsSeparatedByString:@" + "];

for (int z=1; z<[arrayOfRands count]; z++)

    NSString *updateValue = arrayOfRands[z];
    NSInteger newHiddenPosition = [self findBlank:leftSpaces];

    // This is the line with the error!!
    // You have @"@parent" but it should be @"parent"      
    NSDictionary *updateStuff = @@"updateValue": updateValue, @"workingMasterDict":tDict, @"newPos":@(newHiddenPosition), @"newCGPto":@"left", @"@parent":colorV;

    [self revealHidden:updateStuff];


调试您的代码非常有趣!

干杯:)

【讨论】:

你太棒了。确实这就是问题所在,感谢您抽出宝贵时间来追踪如此愚蠢的错字。我讨厌为要求某人检查我的代码而道歉的前提,但是您调试的那个文件的丑陋构成了一个例外。我告诉自己我只是想编写应用程序,然后清理它/稍后了解 Objective-C ......所以不用说这段代码在未来有很多清理工作。干杯! 真棒 Luis.. 喜欢你对帮助 zch 的奉献精神。 :) @dRAGONAIR 谢谢。这就是为什么我们都在这里......互相帮助 @zch,很高兴能够帮助您解决问题。有时有一双额外的眼睛来帮助解决问题是很有用的。此外,您还有一种构建代码的好方法。它确实需要清洁,但你在正确的轨道上。在另一件事上,我之前不想提及任何事情,但是现在赏金期结束了,我想说我投入了时间和精力来解决您的错误;您在赏金期内接受了答案,但没有授予它。我觉得我应得的。如果您不打算奖励它们,请不要提供赏金。这不好。祝你有美好的一天。 @zch,完全不用担心。在此期间结束时,我没有看到任何奖励赏金,这就是我留下该评论的原因。但现在我能够看到它。我不确定之前发生了什么。我只是假设这是一个 *** 错误。无论如何,感谢您接受答案并授予赏金。我希望我能在未来帮助你解决你的另一个问题。干杯!【参考方案2】:

从外观上看,您在动画开始之前设置了hardWayView.frame = frame;,因此 UIView 将更改位置然后进行动画处理。切换地点

hardWayView.frame = frame;
[UIView beginAnimations:nil context:nil];

应该修复它。

无论如何,我强烈建议您使用动画块。上面的代码应该是这样的:

[UIView animateWithDuration:0.4 animations:^
CGRect frame = hardWayView.frame;
frame.origin.x = painPoint.x;
frame.origin.y = painPoint.y;
hardWayView.frame = frame;
 completion:^(BOOL finished) 
    //
];

【讨论】:

感谢您的建议——我将确保用阻塞方法替换所有出现的动画代码。然而,这种变化似乎没有产生效果。无论frame.origin.x.y 设置为什么,问题仍然存在,UIView 仍在屏幕外移动。【参考方案3】:

在完成块中包含代码不是更好吗? (或在 animateWithDuration 块之前)。

[UIView animateWithDuration:0.25 animations:^
                CGRect frame = hardWayView.frame;
                frame.origin.x = painPoint.x;
                frame.origin.y = painPoint.y;
                hardWayView.frame = frame;
             completion:^(BOOL finished) 

            hardWayView.hidden=0;
            hardWayView.backgroundColor = [UIColor blueColor];
            hardWayLabel.textColor = [UIColor orangeColor];

            NSDictionary *hardWay = @@"view": hardWayView, @"label": hardWayLabel, @"intValue":[NSString stringWithFormat: @"%@", hardWayLabel.text], @"hiddenBool":@0, @"position":@([hardWayPos intValue]), @"originalRand": [NSString stringWithFormat: @"%@", hardWayLabel.text];
            [masterDict replaceObjectAtIndex:[masterDict indexOfObject:miniMaser] withObject:hardWay];

            ];

此外,如果是我,我也会为每个 rect 使用不同的名称来帮助调试。例如不要总是称你的矩形为“框架”。称之为 centerFrame、leftFrame、rightFrame。

当您在动画结束时注销 hardWayView 的帧时,它会报告您所期望的吗?

当您在动画开始时注销 hardWayView 的帧时,它会报告您所期望的吗?

我的猜测是 hardWayView 的框架不是你想象的那样。

如果您直接设置框架而不进行动画处理,它会按预期工作吗?

【讨论】:

以上是关于为啥我的 UIView 动画到错误的位置?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的动画圈子的位置会闪烁?

当我将 UIView 动画放在不同类的 containerView 中时,为啥我的 UIView 动画不起作用?

在快速静态错误中为自定义 UIView 设置动画

为啥我的 CAShapeLayer 无法使用 UIView(带 gif)正确设置动画?

具有原点的动画 UIView 无法正常工作

iOS 10 中的动画错误