在开始注意之前,这与后台处理无关.没有"计算"涉及到背景.
只有UIKit.
view.addItemsA()
view.addItemsB()
view.addItemsC()
Run Code Online (Sandbox Code Playgroud)
让我们说6s的iPhone
这将发生:
但是,让我说我希望这种情况发生:
(注意"一秒钟"只是一个简单的例子.为了更全面的例子,请参阅本文末尾.)
你是如何在iOS中做到的?
您可以尝试以下方法.它似乎不起作用.
view.addItemsA()
view.setNeedsDisplay()
view.layoutIfNeeded()
view.addItemsB()
Run Code Online (Sandbox Code Playgroud)
你可以试试这个:
view.addItemsA()
view.setNeedsDisplay()
view.layoutIfNeeded()_b()
delay(0.1) { self._b() }
}
func _b() {
view.addItemsB()
view.setNeedsDisplay()
view.layoutIfNeeded()
delay(0.1) { self._c() }...
Run Code Online (Sandbox Code Playgroud)
请注意,如果该值太小 - 这种方法很简单,显然也没有做任何事情.UIKit将继续努力.(它还会做什么?).如果价值太大,那就没有意义了.
请注意,目前(iOS10),如果我没有弄错的话:如果你尝试使用零延迟的技巧,它最好不正常工作.(正如你可能期望的那样.)
view.addItemsA()
view.setNeedsDisplay()
view.layoutIfNeeded()
RunLoop.current.run(mode: .defaultRunLoopMode, before: Date())
view.addItemsB()
view.setNeedsDisplay()
view.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)
合理. 但是我们最近的实际测试显示,在许多情况下这似乎不起作用.
(也就是说,Apple的UIKit现在足够精致,可以将UIKit的工作涂抹在那个"技巧"之外.)
思考:在UIKit中,或许有一种方法可以获得一个回调,基本上,它已经绘制了你所堆积的所有视图了吗?还有其他解决方案吗?
一个解决方案似乎是......将子视图放在控制器中,因此您可以获得"didAppear"回调,并跟踪这些回调. 这似乎是婴儿,但也许这是唯一的模式?无论如何它真的会起作用吗?(仅仅是一个问题:我没有看到任何保证,确保确保所有子视图都已被绘制.)
日常用例示例:
•假设可能有七个部分.
•假设每个人通常需要0.01到0.20来构建UIKit(取决于您显示的信息).
•如果你只是"让一切都搞砸了"它通常会好或可以接受(总时间,比如0.05到0.15)......但......
•当"新屏幕出现"时,用户经常会有一个单调乏味的停顿.(.1到.5或更糟 …
首先,我的问题是:你如何管理你的iOS Run-Loop?
接下来我的理由是:我一直在研究各种原型(v.早期开发),并发现了许多令人困惑的问题.
那么有没有人围绕这些问题找到了灵丹妙药?有没有人在这个平台上有一个杀手运行循环架构?目前看起来我必须选择较少的邪恶.
在我的应用程序中,我有一些小的子视图.当用户点击子视图时,我会在点击的子视图(相同大小)的顶部放置一个单独的视图,然后将此单独视图设置为全屏大小.
放大视图是自定义绘制的,这对这种方法造成了很大的问题.如果我在主视图的viewDidLoad方法中创建放大视图并将其框架设置为全屏大小,drawRect则立即调用视图的方法,并且视图正确呈现为全尺寸.如果我然后在动画中使用此视图,一切都按预期工作.
但是,我需要这个放大视图根据所拍摄的子视图而有所不同,所以我需要每次重新创建/重新绘制它.问题是当我这样做以响应触摸事件时,视图的drawRect方法在动画开始之前不会被调用,此时视图的帧很小而不是全屏,因此一切都被绘制错误.
在我的触摸事件代码中,我明确地将视图的帧设置为全屏并setNeedsDisplay在开始动画之前调用,但这没有任何效果 - drawRect直到动画开始才调用.
有没有办法强制重绘,以便绘制视图,而其框架是我想要的大小?
你如何通过AVAssetReader读取样本?我找到了使用AVAssetReader进行复制或混合的示例,但这些循环始终由AVAssetWriter循环控制.是否可以只创建一个AVAssetReader并通读它,获取每个样本?
谢谢.
这是一个真正的谜.
想象一下,您正在进行在屏幕外绘制复杂图像的传统过程(CGLayer),并且您在绘制时间歇性地将图像更新到屏幕上.
如您所知,执行此操作的方法是:在后台运行大型绘图过程,并根据需要调用setNeedsDisplays的前景,从而更新图像.这是微不足道的,可以通过两行代码实现.
但是,当你这样做时,会出现一个神秘的问题:每个绘图周期所花费的时间,每次都会增加,变得无法使用.此外,时间可能不规律地变化.
这是一个已知的iOS错误,还是?谁看过这个吗?
这是一个非常简单,非常容易理解的应用程序,可以解决问题:
http://www.fileswap.com/dl/p8lU3gAi/stepwiseDrawingV2.zip.html
输出示例如下.
有谁知道为什么会这样?操作系统的行为非常奇怪.
后来 ...... FELZ已经找到了令人震惊的解决方案.Felz副本的CGLayer一次每一轮.这完全阻止了这种奇怪的行为.
然而,对于究竟发生了什么仍然没有真正清楚的理解:因此从字面上看,当奇怪的问题出现时,时间在哪里?
这是一个很长的输出示例......
请注意,您有时会得到一个"双重奇异"的结果,如下所示:它表现出"正常"奇怪的行为:每次都会增加时间.然而,偶尔会有几轮时间"非常快",然后返回.怪啊?此外,如果您在模拟器上运行,请快速单击Mac上不相关的应用程序,以获得"更奇怪"的结果.
尽管费尔兹给出了一个完美的工作答案,但实际的机制仍然是一个谜.
:26:56.697 stepwiseDrawing[5334:1a03] time difference was 0
:26:56.707 stepwiseDrawing[5334:1a03] time difference was 10
:26:56.717 stepwiseDrawing[5334:1a03] time difference was 10
:26:56.744 stepwiseDrawing[5334:1a03] time difference was 27
:26:56.771 stepwiseDrawing[5334:1a03] time difference was 27
:26:56.807 stepwiseDrawing[5334:1a03] time difference was 37
:26:56.829 stepwiseDrawing[5334:1a03] time difference was 22
:26:56.864 stepwiseDrawing[5334:1a03] time difference was 35
:26:56.891 stepwiseDrawing[5334:1a03] time difference was 28
:26:56.936 stepwiseDrawing[5334:1a03] time difference was 45 …Run Code Online (Sandbox Code Playgroud) 在我的代码中,我希望"动画"绘制一条线的延迟,所以在向视图添加新行之后,我调用setNeedsDisplay - 它工作正常一次.
在drawRect方法中,我绘制线并调用线的方法来增加line-lengthl.现在我想再次调用setNeedsDisplay来重绘该行 - 所以它得到了一个"成长"的动画.
但它只调用setNeedsDisplay一次并且再也不会调用,除非我添加另一行.我也尝试在这个类中调用一个方法,它调用setNeedsDisplay,以确保你不能在drawRect中调用它.
- (void)drawRect:(CGRect)rect {
for(GameLine *line in _lines) {
if(line.done) {
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(c, 5.0f);
CGContextSetStrokeColor(c, lineColor);
CGContextBeginPath(c);
CGContextMoveToPoint(c, line.startPos.x, line.startPos.y);
CGContextAddLineToPoint(c, line.endPos.x, line.endPos.y);
CGContextStrokePath(c);
}else {
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(c, 5.0f);
CGContextSetStrokeColor(c, delayColor);
CGContextBeginPath(c);
CGContextMoveToPoint(c, line.delayStartPos.x, line.delayStartPos.y);
CGContextAddLineToPoint(c, line.delayEndPos.x, line.delayEndPos.y);
CGContextStrokePath(c);
[line incrementDelayLine];
[self setNeedsDisplay];
}
}
}
Run Code Online (Sandbox Code Playgroud)
_lines是一个带有GameLine对象(非原子,保留)属性的NSMutableArray.
谁能解释为什么重新绘制到屏幕外的CGLayer会导致渲染随时间推移而变慢?让我向您展示我为说明问题而创建的测试。
@implementation DrawView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
//setup frame rate monitoring
fps = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
fps.textColor = [UIColor whiteColor];
fps.font = [UIFont boldSystemFontOfSize:15];
fps.text = @"0 fps";
[self addSubview:fps];
frames = 0;
lastRecord = [NSDate timeIntervalSinceReferenceDate];
//create a cglayer and draw the background graphic to it
CGContextRef context = UIGraphicsGetCurrentContext();
cacheLayer = CGLayerCreateWithContext(context, self.bounds.size, NULL);
CGImageRef background = [[UIImage imageNamed:@"background.jpg"] CGImage];
CGContextRef cacheContext = CGLayerGetContext(cacheLayer);
CGContextDrawImage(cacheContext, CGRectMake(0, 0, 768, 1024), …Run Code Online (Sandbox Code Playgroud) ios ×5
iphone ×5
objective-c ×3
drawrect ×2
runloop ×2
avfoundation ×1
cocoa ×1
cocoa-touch ×1
method-call ×1
opengl-es ×1
optimization ×1
performance ×1