为什么我的UIView动画到了错误的位置?

时间:2013-10-20 04:15:41

标签: ios objective-c uiview ios-simulator

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

        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应该是什么样的,这可以通过UILabel到达正确的位置得到证实。我想真正的问题是为什么UIView会继续超越屏幕边界(在这种情况下只有当UIView从屏幕中心向左移动时才会这样做)?

我确实启用了Autolayout,但我不认为这是罪魁祸首。当我在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动画从屏幕的左上角关闭

3 个答案:

答案 0 :(得分:10)

Whooaa!经过多次调试后我终于找到了问题!! :)让我告诉你......那里有一些有趣的代码。无论如何,你会惊讶地发现问题是多么愚蠢;你准备好了吗?

问题在于:

在第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];

}

调试代码非常有趣!

干杯:)

答案 1 :(得分:6)

从它的外观来看,你在动画开始之前设置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) {
    //
}];

答案 2 :(得分:1)

在完成块中包含代码不是更好吗? (或者在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];

            }];

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

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

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

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

如果你直接设置框架而没有设置动画,它是否可以正常工作?