Retrigger CABasicAnimation с NSThread в iOS - PullRequest
2 голосов
/ 01 мая 2011

Я взламываю этот пример основной анимации: https://github.com/joericioppo/Shape_05

Я хочу перезапустить анимацию в ответ на NSThread. NSLogs отображаются, как и ожидалось, но сама анимация не запускается до тех пор, пока не будут завершены все спящие режимы, даже если его метод был проверенно проверен. Как я могу запустить эту анимацию каждую секунду?

Кстати, это всего лишь пример патча, над которым я работаю, чтобы понять концепцию. Я знаю, что анимация может быть настроена на повторение, но я не хочу этого делать по разным причинам. Вот код, любая помощь будет приветствоваться, спасибо.

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@interface Shape_05ViewController : UIViewController {

    CALayer                     *rootLayer;

    CAShapeLayer            *shapeLayer;

    CGMutablePathRef        pentagonPath;
    CGMutablePathRef        starPath;

    int animationCount;
    CABasicAnimation *animation;

}

-(void)startAnimation;
-(void) viewDidLoad;
-(void) startSequence;
-(void) enactSequence;

@end

#import "Shape_05ViewController.h"

@implementation Shape_05ViewController


- (void)loadView 
{

    UIView *appView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    appView.backgroundColor = [UIColor blackColor];
    self.view = appView;
    [appView release];
    rootLayer   = [CALayer layer];
    rootLayer.frame = self.view.bounds;
    [self.view.layer addSublayer:rootLayer];


    //Pentagon Path

    pentagonPath = CGPathCreateMutable();
    CGPoint center = self.view.center;
    CGPathMoveToPoint(pentagonPath, nil, center.x, center.y - 75.0);

    for(int i = 1; i < 5; ++i) {
        CGFloat x = - 75.0 * sinf(i * 2.0 * M_PI / 5.0);
        CGFloat y =  - 75.0 * cosf(i * 2.0 * M_PI / 5.0);
        CGPathAddLineToPoint(pentagonPath, nil,center.x + x, center.y + y);
    }
    CGPathCloseSubpath(pentagonPath); //This seems to be fixed in 4.0

    //Star Path

    starPath = CGPathCreateMutable();
    center = self.view.center;
    CGPathMoveToPoint(starPath, NULL, center.x, center.y + 75.0);
    for(int i = 1; i < 5; ++i) {
        CGFloat x =  75.0 * sinf(i * 4.0 * M_PI / 5.0);
        CGFloat y =  75.0 * cosf(i * 4.0 * M_PI / 5.0);
        CGPathAddLineToPoint(starPath, NULL, center.x + x, center.y + y);
    };
    CGPathCloseSubpath(starPath);


    //Create Shape

    shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = pentagonPath;
    UIColor *fillColor = [UIColor colorWithWhite:0.9 alpha:1.0];
    shapeLayer.fillColor = fillColor.CGColor; 
    shapeLayer.fillRule = kCAFillRuleNonZero;
    [rootLayer addSublayer:shapeLayer];

}


-(void) viewDidLoad {

    NSLog(@"viewDidLoad");
    animationCount = 0;
    [NSThread detachNewThreadSelector:@selector(startSequence) toTarget:self withObject:nil];

}

-(void) startSequence {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [self enactSequence];
    //[NSThread sleepForTimeInterval:100];

    [pool release];

}
-(void) enactSequence {
    NSLog(@"enactSequence");
    for(int i = 0; i < 4; i++) {
        [NSThread sleepForTimeInterval:1];
        [self performSelector:@selector(startAnimation) withObject:nil];
        [rootLayer setNeedsDisplay];
        NSLog(@"%i", i);
    };

}


-(void)startAnimation
{   
    NSLog(@"startAnimation");

    animation = [CABasicAnimation animationWithKeyPath:@"path"];
    animation.duration = 0.25;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.repeatCount = 0;
    animation.autoreverses = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = YES;

    if( (animationCount % 2) == 0) {
        animation.fromValue = (id)pentagonPath;
        animation.toValue = (id)starPath;
    } else {
        animation.fromValue = (id)starPath;
        animation.toValue = (id)pentagonPath;
    };


    [shapeLayer addAnimation:animation forKey:@"animatePath"];

    animationCount++;

}


- (void)didReceiveMemoryWarning 
{
    [super didReceiveMemoryWarning];
}


- (void)dealloc
{
    CGPathRelease(starPath);
    CGPathRelease(pentagonPath);
    [super dealloc];
}


@end

1 Ответ

0 голосов
/ 01 мая 2011

ОК после очередного трала Google: http://forums.macrumors.com/showthread.php?t=749518&highlight=cabasicanimation

Я узнал об этой штуке под названием NSTimer! Еще один поиск по этому сайту показал полезную информацию: Как мне использовать NSTimer?

А по поводу запуска NSTimer в собственной ветке: Хранить NSThread, содержащий NSTimer, неограниченно долго? (IPhone)

Так что теперь я могу предложить этот обновленный пример кода, который, я надеюсь, может пригодиться кому-нибудь однажды Кстати, я еще не пробовал, но, по-видимому, для остановки таймера можно использовать следующее:

[myTimer invalidate];
myTimer = nil;

Спасибо всем здесь, на этом сайте, не только самый красиво оформленный уголок Интернета, но и спасатель!

    #import <UIKit/UIKit.h>
    #import <QuartzCore/QuartzCore.h>

    @interface Shape_05ViewController : UIViewController {

        CALayer                     *rootLayer;

        CAShapeLayer            *shapeLayer;

        CGMutablePathRef        pentagonPath;
        CGMutablePathRef        starPath;

        int animationCount;
        CABasicAnimation *animation;
        NSTimer *repeatingTimer;

    }

@property (assign, readwrite) NSTimer *repeatingTimer;

    -(void) startAnimation: (NSTimer*)theTimer;
    -(void) viewDidLoad;
    -(void) startSequence;

    @end

    #import "Shape_05ViewController.h"

    @implementation Shape_05ViewController

    @synthesize repeatingTimer;


    - (void)loadView 
    {

        UIView *appView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        appView.backgroundColor = [UIColor blackColor];
        self.view = appView;
        [appView release];
        rootLayer   = [CALayer layer];
        rootLayer.frame = self.view.bounds;
        [self.view.layer addSublayer:rootLayer];


        //Pentagon Path

        pentagonPath = CGPathCreateMutable();
        CGPoint center = self.view.center;
        CGPathMoveToPoint(pentagonPath, nil, center.x, center.y - 75.0);

        for(int i = 1; i < 5; ++i) {
            CGFloat x = - 75.0 * sinf(i * 2.0 * M_PI / 5.0);
            CGFloat y =  - 75.0 * cosf(i * 2.0 * M_PI / 5.0);
            CGPathAddLineToPoint(pentagonPath, nil,center.x + x, center.y + y);
        }
        CGPathCloseSubpath(pentagonPath); //This seems to be fixed in 4.0

        //Star Path

        starPath = CGPathCreateMutable();
        center = self.view.center;
        CGPathMoveToPoint(starPath, NULL, center.x, center.y + 75.0);
        for(int i = 1; i < 5; ++i) {
            CGFloat x =  75.0 * sinf(i * 4.0 * M_PI / 5.0);
            CGFloat y =  75.0 * cosf(i * 4.0 * M_PI / 5.0);
            CGPathAddLineToPoint(starPath, NULL, center.x + x, center.y + y);
        };
        CGPathCloseSubpath(starPath);


        //Create Shape

        shapeLayer = [CAShapeLayer layer];
        shapeLayer.path = pentagonPath;
        UIColor *fillColor = [UIColor colorWithWhite:0.9 alpha:1.0];
        shapeLayer.fillColor = fillColor.CGColor; 
        shapeLayer.fillRule = kCAFillRuleNonZero;
        [rootLayer addSublayer:shapeLayer];

    }


    -(void) viewDidLoad {

        NSLog(@"viewDidLoad");
        animationCount = 0;

        [NSThread detachNewThreadSelector:@selector(startSequence) toTarget:self withObject:nil];

    }

    -(void) startSequence {
        NSLog(@"startSequence");
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                          target:self
                                                        selector:@selector(startAnimation:)
                                                        userInfo:nil 
                                                         repeats:YES];
        [[NSRunLoop currentRunLoop] run];
        self.repeatingTimer = timer;
        [pool release];

    }

-(void)startAnimation: (NSTimer*)theTimer {

        NSLog(@"startAnimation");

        animation = [CABasicAnimation animationWithKeyPath:@"path"];
        animation.duration = 0.25;
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        animation.repeatCount = 0;
        animation.autoreverses = NO;
        animation.fillMode = kCAFillModeForwards;
        animation.removedOnCompletion = NO;

        if( (animationCount % 2) == 0) {
            animation.fromValue = (id)pentagonPath;
            animation.toValue = (id)starPath;
        } else {
            animation.fromValue = (id)starPath;
            animation.toValue = (id)pentagonPath;
        };
        [shapeLayer addAnimation:animation forKey:@"animatePath"];
        animationCount++;

    }


    - (void)didReceiveMemoryWarning 
    {
        [super didReceiveMemoryWarning];
    }


    - (void)dealloc
    {
        CGPathRelease(starPath);
        CGPathRelease(pentagonPath);
        [super dealloc];
    }

    @end
...