【问题标题】:UIImageView animation delay when doing startAnimating执行 startAnimating 时 UIImageView 动画延迟
【发布时间】:2023-04-05 15:33:01
【问题描述】:

我有一个 21 帧的菜单背景动画。我在视图的 viewDidLoad 方法中使用以下代码将它们加载到内存中。

NSMutableArray *menuanimationImages = [[NSMutableArray alloc] init];

for( int aniCount = 0; aniCount < 21; aniCount++ )
{

    NSString *fileLocation = [[NSBundle mainBundle] pathForResource: [NSString stringWithFormat: @"bg%i", aniCount + 1] ofType: @"png"];
    NSData *imageData = [NSData dataWithContentsOfFile: fileLocation];

    [menuanimationImages addObject: [UIImage imageWithData:imageData]];

}

settingsBackground.animationImages = menuanimationImages;

不幸的是,正在做 [settingsBackground startAnimating];在 viewDidLoad 方法中不起作用。有没有办法预加载动画,这样在第一次运行时就没有 1-3 秒的延迟?

【问题讨论】:

    标签: iphone objective-c ios ipad uiimageview


    【解决方案1】:

    UIImageView 的animationImages 属性需要UIImage 对象数组,而不是NSData 对象数组。

    您可能还想设置持续时间和重复计数,即使它们具有默认值。

    例子:

    if (!self.idleView.animationImages) {
        self.idleView.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:@"idle1.png"],
                          [UIImage imageNamed:@"idle2.png"],
                          [UIImage imageNamed:@"idle3.png"],
                          [UIImage imageNamed:@"idle4.png"],
                          [UIImage imageNamed:@"idle5.png"],
                          [UIImage imageNamed:@"idle6.png"],
                          [UIImage imageNamed:@"idle7.png"],
                          [UIImage imageNamed:@"idle8.png"],
                          [UIImage imageNamed:@"idle9.png"],
                          [UIImage imageNamed:@"idle10.png"],
                          [UIImage imageNamed:@"idle11.png"],
                          [UIImage imageNamed:@"idle12.png"],
                          [UIImage imageNamed:@"idle13.png"],
                          [UIImage imageNamed:@"idle14.png"],
                          [UIImage imageNamed:@"idle15.png"],
                          [UIImage imageNamed:@"idle16.png"],
                          [UIImage imageNamed:@"idle17.png"],
                          [UIImage imageNamed:@"idle18.png"],
                          [UIImage imageNamed:@"idle19.png"],
                          [UIImage imageNamed:@"idle20.png"]                
                          , nil];
        }
        self.idleView.animationRepeatCount = 0;
        self.idleView.animationDuration = 2.0;
        [self.view addSubview:self.idleView];
        [self.view sendSubviewToBack:self.idleView];
        [self.idleView startAnimating];
    

    【讨论】:

      【解决方案2】:

      试试下面的代码,通常你应该没有延迟。这段代码也更简单:

       NSMutableArray *menuanimationImages = [[NSMutableArray alloc] initWithCapacity:21];
       NSString *imageName;
      
       for( int aniCount = 1; aniCount < 21; aniCount++ )
       {
           imageName = [NSString stringWithFormat:@"bg%d.png", aniCount];
           [menuanimationImages addObject:[UIImage imageNamed:imageName]];
       }
      
       settingsBackground.animationImages = menuanimationImages;
       // all frames will execute in 2 seconds
       settingsBackground.animationDuration = 2.0;
       // repeat the annimation forever
       settingsBackground.animationRepeatCount = 0;
       // start animating
       [settingsBackground startAnimating];
      

      【讨论】:

        【解决方案3】:

        我通常不建议使用 imageNamed 并依赖内置缓存机制。如果您搜索,您会发现很多关于此的讨论,但它也不一定会预渲染您的图像。

        我使用以下代码预加载和预渲染图像,因此在第一次制作动画时不会出现延迟。

        NSMutableArray *menuanimationImages = [[NSMutableArray alloc] init];
        
        for (int aniCount = 1; aniCount < 21; aniCount++) {
            NSString *fileLocation = [[NSBundle mainBundle] pathForResource: [NSString stringWithFormat: @"bg%i", aniCount + 1] ofType: @"png"];
            // here is the code to pre-render the image
            UIImage *frameImage = [UIImage imageWithContentsOfFile: fileLocation];
            UIGraphicsBeginImageContext(frameImage.size);
            CGRect rect = CGRectMake(0, 0, frameImage.size.width, frameImage.size.height);
            [frameImage drawInRect:rect];
            UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
        
            [menuanimationImages addObject:renderedImage];
        }
        
        settingsBackground.animationImages = menuanimationImages;
        

        【讨论】:

        • @DanielGillespie 它对你有用吗?我也面临同样的问题。
        • 图片预渲染需要settingsBackground.animationImages = menuanimationImages;吗?
        • 不,你猜不,它们已经被渲染了——它只是为了直接回答关于使用 UIImageView 的动画特性的问题。
        • 谢谢,它对我有用!但是我的图像在预渲染后看起来很模糊。为了避免模糊,我使用 UIGraphicsBeginImageContextWithOptions(frameImage.size, NO, 0.0);而不是 UIGraphicsBeginImageContext(frameImage.size);
        【解决方案4】:

        每个答案的问题在于建议的“修复”是将所有图像数据预加载到内存中。如果您的图像太大或图像太多,这可能并且将会导致崩溃,请参阅我对uiimage-animation-causing-app-to-crash-memory-leaks 的回答以获取更多详细信息。真正的解决方法是您需要解压缩图像,但不要将它们全部保存在内存中。或者,您可以使用已经在一个步骤中对所有帧进行解压缩的电影格式,这样从帧到帧的更改不是一项昂贵的操作。

        【讨论】:

          猜你喜欢
          • 2012-02-08
          • 1970-01-01
          • 2015-02-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多