multithreading - ios运行自定义动画的首选方式

  显示原文与译文双语对照的内容
145 0

我需要在iOS应用程序中运行复杂的自定义动画。为此,我编写了需要反复调用的函数,并使用当前时间戳来计算屏幕上UIView元素的位置。颜色。阴影和 等等 。

我可以以使用一系列不同的方法来调用这个函数:

我尝试从单独的线程调用动画功能,但在触发一个设备时,我没有看到任何屏幕更新。但我甚至不知道这是不是最好的方法。

如果不阻塞图形颜色或者视图位置,那么在不阻止GUI的情况下,继续调用函数( 对于动画,例如)的首选方法是:更改屏幕颜色或者位置。

如果可以能,我想使用一种尽可以能向后兼容的方法,所以最好不要使用在 iOS 8.1 ( 夸大) 中引入的任何功能。: )

对不起,我没有发布代码示例。我正在使用 RoboVM,并且不希望"吓跑"开发人员对任何答案进行。此外,这更像是一般的概念问题,而不是特定的错误修正。

时间:原作者:0个回答

91 1

我已经从 CADisplayLink 找到了最好的性能。

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTick)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
- (void)displayLinkTick {
//Update your animation.
}

在销毁这里视图时,不要忘记拆除,否则你的displayLinkTick 将被调用,直到你的应用程序退出:

[displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

如果使用( 或者转换为) CALayer,则子类将从动画键的needsDisplayForKey: 返回 YES然后,在 CALayer 子类'display 方法,应用 self.presentationLayer 对动画所做的更改。

@property (assign) CGFloat myAnimatingProperty;
@implementation MyAnimatingLayer : CALayer
+ (BOOL)needsDisplayForKey:(NSString *)key {
 if ([key isEqualToString:@"myAnimatingProperty"]) {
 return YES;
 }
 return [super needsDisplayForKey:key];
}
- (void)display {
 if ([self.animationKeys containsObject:@"myAnimatingProperty"]) {
 CGFloat currentValue = self.presentationLayer.myAnimatingProperty;
//Update.
 }
}
@end

第二种方式可以让你轻松地连接到内置的缓动函数中。

原作者:
102 2

如果其他人正在寻找RoboVM解决方案,你可以:

import org.robovm.apple.coreanimation.CADisplayLink;
import org.robovm.apple.foundation.NSObject;
import org.robovm.apple.foundation.NSRunLoop;
import org.robovm.apple.foundation.NSString;
import org.robovm.objc.Selector;
import org.robovm.objc.annotation.BindSelector;
import org.robovm.rt.bro.annotation.Callback;
//Requires iOS 3.1
public abstract class DisplayRefreshTimer extends NSObject implements Runnable {
 private static final Selector REFRESH = Selector.register("displayRefresh:");
 private static final NSString RUNMODE = new NSString("kCFRunLoopDefaultMode");
 public DisplayRefreshTimer() {
 CADisplayLink displayLink = CADisplayLink.create(this, REFRESH);
 displayLink.addStrongRef(this);//Don't garbage collect"this"
 displayLink.addToRunLoop(NSRunLoop.getCurrent(), RUNMODE);//Start calling
 }
 @Callback @BindSelector("displayRefresh:")
 private static void displayRefresh(DisplayRefreshTimer __self__) {
 if (__self__!=null) __self__.run();
 }
}

只有子类,重写 run() 并实例化:

new DisplayRefreshTimer() {
 @Override
 public void run() {
//Do your magic here...
 }
};

完成。

注意:常量字符串可能改变,应该从应该由 NSRunLoop 提供的NSDefaultRunLoopMode 常量读取。出于某些原因,RoboVM删除了对这里常量( 这里有些细节。)的访问。我认为,苹果可以能会决定将来改变这个常量,在这种情况下应用程序将会破坏。

原作者:
...