【问题标题】:UIView animation not working in iOS 7UIView 动画在 iOS 7 中不起作用
【发布时间】:2014-07-31 02:55:58
【问题描述】:

我正在处理一个示例项目,其中我有一个垂直的scrollview 和一个水平的scrollview。垂直的scrollview 有许多子视图。在scrollviewDidScroll 我正在执行一些操作。除此之外,我现在想在垂直滚动视图内的子视图在屏幕上可见时为该子视图设置动画。为此,我正在做一个正确的计算。动画如下:

子视图包含多个自定义视图。我正在尝试以某些特定的时间顺序对这些视图中的每一个进行动画处理(减少然后再次增加视图的 alpha 值)(以便动画看起来是按顺序排列的)。为此,我正在向视图发布通知,并且动画序列和逻辑根据我的需要是完美的。

但是我遇到的问题是我下断点时代码正在执行,但动画没有出现。如果我在停止滚动后发布通知,那么动画会非常好。但我希望即使在我滚动并且视图在屏幕上时也能发生动画。

我正在添加我的代码 sn-p 如下:

SubView:(在我的scrollview里面)

- (void)animateSequenceTemplate {
if (!hasSequenceTemplateAnimated) {
    [self performSelector:@selector(animateSequenceSlides) withObject:nil afterDelay:0];
    hasSequenceTemplateAnimated = YES;
}
else {
    return;
}
}

- (void)animateSequenceSlides {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:imageAsset forKey:@"assetMO"];
[[NSNotificationCenter defaultCenter]postNotificationName:AnimateSequenceSlide object:nil userInfo:userInfo];
}

上述子视图内的子视图:

- (void)animateSlideView:(NSNotification *)notification {

NSDictionary *userInfo = notification.userInfo;
if ([userInfo objectForKey:@"assetMO"] == assetMO) {
    [[NSNotificationCenter defaultCenter]removeObserver:self name:AnimateSequenceSlide object:nil];

    CGFloat duration = 0.035;
    float delay = (self.slideCount * duration);
    CGFloat timeDelay = 0;


    [self performSelector:@selector(animationPhase1) withObject:nil afterDelay:delay];
    timeDelay = delay + duration;
    [self performSelector:@selector(animationPhase2) withObject:nil afterDelay:timeDelay];

    if (self.slideCount == (self.maxSlideCount - 1)) {
        timeDelay += duration * 18; //No animation till 18 frames
    }
    else {
        timeDelay += duration;
    }
    [self performSelector:@selector(animationPhase3) withObject:nil afterDelay:timeDelay];
    timeDelay += duration;
    [self performSelector:@selector(animationPhase4) withObject:nil afterDelay:timeDelay];
}
}

- (void)animationPhase1 {
[UIView animateWithDuration:0.035 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^ {
    [self setAlpha:0.85];
}completion:^(BOOL finished) {
}];
}

- (void)animateSequenceTemplate内部出现两种情况:

  1. 我打电话给[self animateSequenceSlides];。在这种情况下,动画不会显示。
  2. [self performSelector:@selector(animateSequenceSlides) withObject:nil afterDelay:0.0f];。在这种情况下,动画会在 scrollview 休息之后出现。

我不得不使用执行选择器来使用UIView 动画,因为如果我删除它并使用嵌套的 UIView 动画块/或直接调用这些方法,那么动画不会再次出现。现在至少它会在我休息滚动后显示。

我想就解决方案提出建议,或者对我可能犯的错误进行任何猜测。

【问题讨论】:

  • 你能发布你的代码吗?很难猜测到底出了什么问题。
  • 已编辑我的问题。请看一看。希望它对我们俩都有帮助。
  • 谢谢安东!但这对我不起作用。

标签: ios objective-c ipad ios7 xcode5


【解决方案1】:

最后,我得到了我的问题的解决方案,它按预期工作得很好。

所做的更改:

  1. 从“animateSequenceTemplate”调用“animateSequenceSlides” 直接方法
  2. 在上面提到的“animateSlideView”方法中,我没有使用执行选择器,而是创建了具有所需延迟的 NSTimer 对象, 重复设置为 NO,并在当前运行循环中添加计时器
  3. 调用所有四个 animationPhase 方法的方法相同
  4. 代码可以正常工作

     - (void)animateSequenceTemplate {
     if (!hasSequenceTemplateAnimated && self.isSequenceSlideCreated) {
    hasSequenceTemplateAnimated = YES;
    [self animateSequenceSlides];
    }
    }
    
    
    - (void)animateSlideView:(NSNotification *)notification {
    
    NSDictionary *userInfo = notification.userInfo;
    if ([userInfo objectForKey:@"assetMO"] == assetMO) {
    [[NSNotificationCenter defaultCenter]removeObserver:self name:AnimateSequenceSlide object:nil];
    
    CGFloat duration = 0.035;
    float delay = (self.slideCount * duration);
    CGFloat timeDelay = 0;
    
    NSTimer *animate1 = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(animationPhase1) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop]addTimer:animate1 forMode:NSRunLoopCommonModes];
    
    timeDelay = delay + duration;
    
    NSTimer *animate2 = [NSTimer scheduledTimerWithTimeInterval:timeDelay target:self selector:@selector(animationPhase2) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop]addTimer:animate2 forMode:NSRunLoopCommonModes];
    
    if (self.slideCount == (self.maxSlideCount - 1)) {
        timeDelay += duration * 18; //No animation till 18 frames
    }
    else {
        timeDelay += duration;
    }
    
    NSTimer *animate3 = [NSTimer scheduledTimerWithTimeInterval:timeDelay target:self selector:@selector(animationPhase3) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop]addTimer:animate3 forMode:NSRunLoopCommonModes];
    
    timeDelay += duration;
    
    NSTimer *animate4 = [NSTimer scheduledTimerWithTimeInterval:timeDelay target:self selector:@selector(animationPhase4) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop]addTimer:animate4 forMode:NSRunLoopCommonModes];
    }
    }
    

我对代码结构的优点不满意。如果您想到任何其他聪明的做法,请分享。

【讨论】:

    【解决方案2】:

    您可能不在主队列上执行它。

    dispatch_async(dispatch_get_main_queue, block()) 可能会有所帮助。 处理动画时,主队列是执行代码的唯一地方,这使得动画发生。

    编辑:

    [self performSelector:@selector(animationPhase1) withObject:nil afterDelay:delay];
    

    我不确定它发生在哪里,但我不认为在主线程上。 试试这个:

    [self performSelectorOnMainThread:@selector(animationPhase1) 
                           withObject:nil 
                        waitUntilDone:YES];
    

    我不确定延迟,这就是为什么我更喜欢 GCD 函数和块。

    【讨论】:

    • 我按照建议尝试了。同样的情况仍然发生。会出现两种情况: 1. 我叫作[self animateSequenceSlides];。在这种情况下,动画不会显示。 2. [self performSelector:@selector(animateSequenceSlides) withObject:nil afterDelay:0.0f];。在这种情况下,动画会在滚动视图停止后显示。有什么线索吗?
    • 每次调用 UIView 选择器时,将其放入 dispatch_async(dispatch_get_main_queue, ^{ [UIView selector] });,除非您 100% 确定您在主线程上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    相关资源
    最近更新 更多