【问题标题】:Write method that takes completion block写入完成块的方法
【发布时间】:2015-02-16 15:08:27
【问题描述】:

我刚开始尝试使用块,我对创建自己的完成块的方法很感兴趣。到目前为止,我阅读了 appCoda 的教程和 stackoverflow 的这篇文章: Custom Completion Block For My Own Method

这是我尝试实现它的一个例子:

#import "MainViewController.h"

@interface MainViewController ()
{
    UIImageView *animationView;
}
typedef void(^myCompletion)(BOOL);
@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //Set the backgroun image
    UIImageView *backgroundImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20.0f, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height - 20.f)];
    [backgroundImage setImage:[UIImage imageNamed:@"chalk_board_texture_by_blueamnesiac-d4h76qm.png"]];
    [self.view addSubview:backgroundImage];


    [self myMethod:^(BOOL finished) {
        if(finished){
            [animationView setImage:[UIImage imageNamed:@"Animation60.png"]];
        }
    }];
}

-(void) myMethod:(myCompletion) compblock{
    //do stuff
    //Get the imges name into array
    NSArray *imageNames = @[@"Animation1.png", @"Animation2.png", @"Animation3.png", @"Animation4.png",
                            @"Animation5.png", @"Animation6.png", @"Animation7.png", @"Animation8.png",
                            @"Animation9.png", @"Animation10.png", @"Animation11.png", @"Animation12.png",
                            @"Animation13.png", @"Animation14.png", @"Animation15.png", @"Animation16.png",
                            @"Animation17.png", @"Animation18.png", @"Animation19.png", @"Animation20.png",
                            @"Animation21.png", @"Animation22.png", @"Animation23.png", @"Animation24.png",
                            @"Animation25.png", @"Animation26.png", @"Animation27.png", @"Animation28.png",
                            @"Animation29.png", @"Animation30.png", @"Animation31.png", @"Animation32.png",
                            @"Animation33.png", @"Animation34.png", @"Animation35.png", @"Animation36.png",
                            @"Animation37.png", @"Animation38.png", @"Animation39.png", @"Animation40.png",
                            @"Animation41.png", @"Animation42.png", @"Animation43.png", @"Animation44.png",
                            @"Animation45.png", @"Animation46.png", @"Animation47.png", @"Animation48.png",
                            @"Animation49.png", @"Animation50.png", @"Animation51.png", @"Animation52.png",
                            @"Animation53.png", @"Animation54.png", @"Animation55.png", @"Animation56.png",
                            @"Animation57.png", @"Animation58.png", @"Animation59.png", @"Animation60.png",];

    //move image objects by name to mutable array
    NSMutableArray *images = [[NSMutableArray alloc] init];
    for (int i = 0; i < imageNames.count; i++) {
        [images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
    }

    //Create the image horlder for the animation using the window size
    int animationViewWidth = [[UIScreen mainScreen] bounds].size.width - 20.0f;
    int animationViewHeight = animationViewWidth * 1.38;
    animationView = [[UIImageView alloc]initWithFrame:CGRectMake(10.0f, 20.0f, animationViewWidth, animationViewHeight)];
    animationView.animationImages = images;
    animationView.animationDuration = 0.5;
    animationView.animationRepeatCount = 1;
    [self.view addSubview:animationView];
    [animationView startAnimating];

    //completion finished set bool to yes
    compblock(YES);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

完成处理程序中的错误是它在动画完成后没有设置背景图像。 提前致谢!

到目前为止,我找到了两个很好的答案: 来自@Rob 的那个: - 将图像视图的图像属性设置为 startAnimating 之前的第 60 个图像。

还有来自@ian-macdonald 的另一个重定向到我们同时发现的一个很棒的教程: - How to Animate Images in a UIImageView with Completion Handler

但问题仍然存在,为什么不能将块实现为侦听器,而当动画完成时,块会触发背景图像更改?

【问题讨论】:

  • 不相关,除非您可能多次重复使用该动画序列,否则我会谨慎使用 imageNamed 处理动画序列中的一堆图像。正如imageNamed 文档所说:“如果您有一个只显示一次的图像文件并希望确保它不会被添加到系统的缓存中,您应该使用imageWithContentsOfFile: 创建您的图像。这将保持系统图像缓存中的一次性图像,可能会改善应用的内存使用特性。”
  • 第一个数组保存图像的名称,第二个保存可变对象数组,图像
  • 我明白了。只是imageNamed缓存了它的图像,所以即使你的动画完成了,即使图像视图被移除了,即使整个视图控制器消失了,图像仍然会缓存在内存中。仅将 imageNamed 用于您的应用程序重复使用的图像,因此将从这种缓存行为中受益。否则使用imageWithContentsOfFile

标签: ios animation uiimageview block


【解决方案1】:

我认为您根本不需要完成的块。只需致电
[animationView setImage:[UIImage imageNamed:@"Animation60.png"]];
在触发动画之前,它会在动画完成后显示图像。不确定在动画开始之前是否会在很短的时间内显示最后一张图像(但我认为如果你立即开始动画则没有)。

【讨论】:

  • 选中的图片,图片60不留在屏幕上,动画结束后消失,和之前一样问题
  • 为什么这被否决了?这看起来很简单,除非 OP 想在动画完成后触发其他一些东西,否则这对我来说似乎是一个有效的答案。
  • @LaurStefan 将图像视图的image 属性设置为startAnimating 之前的第60 个图像。
  • 完全移除动画并调用[animationView setImage:[UIImage imageNamed:@"Animation60.png"]];而不是[self myMethod:^(BOOL finished) { if(finished){ [animationView setImage:[UIImage imageNamed:@"Animation60.png"]]; } }];时会显示什么?
  • @LaurStefan 如果您接受这个答案,我会很高兴。我只是重申金已经指出的内容。
【解决方案2】:

您在告诉动画开始后立即调用compblock。动画还没来得及完成。

您可以监听动画完成,或者您可以假设它需要您请求的确切时间。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  compblock(YES);
});

您可能会在使用此方法时遇到一些未对齐的帧,因为动画可能需要更少或更多的时间,但它可能只是几毫秒并且完全不引人注意。


您可能对 uiimageview 动画图像补全first hit on Google 感兴趣。相关代码块:

NSMutableArray *images = [[NSMutableArray alloc] init];
NSInteger animationImageCount = 38;
for (NSInteger i = 0; i < animationImageCount; i++) {
    // Images are numbered IndexedImagesInMyAnimation0, 1, 2, etc...
    [images addObject:(id)[UIImage imageNamed:[NSString stringWithFormat:@"IndexedImagesInMyAnimation%d", i]].CGImage];
}

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
animation.calculationMode = kCAAnimationDiscrete;
animation.duration = animationImageCount / 24.0; // 24 frames per second
animation.values = images;
animation.repeatCount = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.animationImageView.layer addAnimation:animation forKey:@"animation"];

【讨论】:

  • 我已经替换了 compblock(YES);根据您的建议,它似乎不起作用,这些是第一个问题,第二个问题是关于实现的,我知道不建议使用 dispatch_after dispatch_time 不仅因为帧速率而且因为它可能会导致界面冻结并可能导致崩溃。
  • dispatch_after 不会导致您的界面冻结或崩溃,除非您正在分派到主线程并在块内执行重要进程。
  • 让我先用 0.6 测试
  • 它播放动画,动画结束后没有设置新的背景图像。图像视图保持清晰
  • 这看起来是一个糟糕的解决方法。如果您想更好地控制动画何时完成,您可能不应该使用 animationImages 但例如CAKeyFrameAnimation.
猜你喜欢
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-23
  • 1970-01-01
相关资源
最近更新 更多