定时器与 UIView 动画结合的雪花降落的效果

 1 #import "HUAppDelegate.h"

 2 

 3 @implementation HUAppDelegate

 4 

 5 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

 6 {

 7     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

 8     self.window.backgroundColor = [UIColor whiteColor];

 9     [self.window makeKeyAndVisible];

10     

11     UIImageView *bg = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

12     bg.image = [UIImage imageNamed:@"xueshan.jpg"];

13     [self.window addSubview:bg];

14     

15     _snowArray = [[NSMutableArray alloc] init];

16     UIImageView *snow = nil;

17     for (int i  = 0; i < 50; i ++)

18     {

19         snow = [[UIImageView alloc] initWithFrame:CGRectMake(arc4random() % 320, -20, 20, 20)];

20         snow.image = [UIImage imageNamed:@"flake.png"];

21         snow.tag = 0;

22         [self.window addSubview:snow];

23         [_snowArray addObject:snow];

24     }

25     

26     [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(findSnow) userInfo:nil repeats:YES];

27     

28     

29     return YES;

30 }

31 

32 //找雪花

33 - (void)findSnow

34 {

35     UIImageView *aSnow = nil;

36     for (int i = 0; i < _snowArray.count; i ++)

37     {

38         aSnow = [_snowArray objectAtIndex:i];

39         if (aSnow.tag == 0)

40         {

41             aSnow.tag = 1;

42 //            [self snowDown:aSnow];  //如果将这句代码放在这里,后面的 else 以及后面的代码都可以不要,因为放在这里不会出现不被允许动画的雪花又被调用执行一次动画

43             break;

44         }

45         else

46         {

47             aSnow = nil;   //找雪花的时候没有一朵雪花是符合条件的,但这时候 aSnow 仍然有一个值,如果不让它指向空的时候,最后一朵雪花(第50朵)又被使用了一次,此时这多雪花下落的动画还没有结束,再次使用会造成意想不到的结果(有一朵雪花会往上飞)。这个 bug 折磨了我一天,最后还是老师帮助解决的,思维进入了一个误区,还真的是害人不浅。

48         }

49     }

50 

51     [self snowDown:aSnow];  //调用雪花动画的方法,即时让被找到的这朵雪花进行动画

52 }

53 

54 //让一朵雪花动画

55 - (void)snowDown:(UIImageView *)aSnow

56 {

57     [UIView beginAnimations:nil context:aSnow];

58     [UIView setAnimationDuration:7];

59     aSnow.frame = CGRectMake(arc4random() % 320 , 480, 20, 20);

60     [UIView setAnimationDelegate:self];

61     [UIView setAnimationDidStopSelector:@selector(restart:finished:context:)];

62     [UIView commitAnimations];

63 }

64 

65 - (void)restart:(NSString *)animationID finished:(NSNumber *)finished context:(void *)aSnow

66 {

67     UIImageView * snow = (UIImageView *)aSnow;

68     snow.frame = CGRectMake(arc4random() % 320, -20, 20, 20);

69     snow.tag = 0;

70 }//让已经下落到底部的动画重新定位到顶部,达到重用的效果,并且重置 tag 值,此时这多雪花就可以被重新找到,再次进行下落的动画

71 

72 /*

73  注意上面的定时器的时间间隔(0.14)以及雪花下落动画所需要的时间(7),以及数组的长度(50)

74  0.14 * 50 = 7

75  这个时间去的有点巧妙,这是一个临界值,本来我是本着不浪费的原则让每一朵雪花都能够没找到然后进

76  动画,然后出现了上面的 bug, 如果将时间间隔调小一点(雪花动画会出现断层,最后一朵雪花的动画

77  果也会受到影响,此时将数组长度减至10,会发现只有 9 多雪花进行了动画,原理同上),如果将时间

78  调大是可以解决问题的,因为此时在找到最后一朵雪花之前,已经有雪花重新在进行一轮动画了。

79  */

80 

81 @end

这种使用定时器与 UIView 动画结合制作的动画效果既不僵硬,然后又能够对雪花对象重用,节省了内存,是比较好的方式。

到这里,动画的学习已经结束了一个阶段,在使用过程中需要结合实际情况选择。

你可能感兴趣的:(UIView)