在 iOS 中使用 NSThread 重新触发 CABasicAnimation
我正在破解这个核心动画示例: 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
I am hacking this Core Animation example:
https://github.com/joericioppo/Shape_05
I want to retrigger the animation in response to an NSThread. The NSLogs show up as expected, but the animation itself does not trigger until all sleeps have completed, even though its method has verifiably been called. How can I retrigger this animation every second?
By the way - this is just an example patch I am working on in order to understand the concept. I know that animations can be set to repeat, but this isn't what I want to do, for various reasons. Here's the code, any help would be most welcome, thanks.
#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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
再次谷歌搜索后确定:
http://forums.macrumors.com/showthread.php?t= 749518&highlight=cabasicanimation
我发现了这个叫做 NSTimer 的东西!对该网站的另一次搜索发现了一些好信息:
如何使用 NSTimer?
关于在自己的线程中运行 NSTimer:
无限期地保留包含 NSTimer 的 NSThread 吗? (iPhone)
所以现在我可以提供这个更新的代码示例,我希望有一天它可能对某人有用。顺便说一句,我还没有尝试过,但显然可以使用以下方法来停止计时器:
感谢本网站的所有人,不仅是网络上设计最精美的角落,而且还是一个完全的救星!
OK after another Google trawl:
http://forums.macrumors.com/showthread.php?t=749518&highlight=cabasicanimation
I found out about this thing called NSTimer! Another search of this site revealed some good info:
How do I use NSTimer?
And about running NSTimer in its own thread:
Keep an NSThread containing an NSTimer around indefinitely? (iPhone)
So now I can offer this updated code example, which I hope may be useful to someone one day. By the way, I didn't try it yet, but apparently the following can be used to stop the timer:
Thanks to all here at this site, not only the most beautifully designed corner of the web but also a total lifesaver!