Ios 使用setNeedsDisplay在背景中设置Calayer动画
我正在将我的库从Andriod移植到IOS,在这个过程中,我已经取得了很大的进步,并学习了一些有关Objective C的知识。我说一点,因为有很多东西要学。Android库创建一个surfaceView,并通过直接将图像绘制到surfaceView来制作动画;在目标C中,我将UIView与CALayers一起使用 在UIView中,我将动态添加加载了精灵图纸图像的CALayer,然后在UIView中移动CALayer,同时通过移动CALayer的内容Rect在CALayer中的精灵图像中漫游 这一切都可以在Android的后台线程中完美工作,并且不会干扰主机应用程序。在目标C中,我试图使用performSelectorInBackground或新的Grand Central Dispatch在后台运行它。两者似乎都在背景中工作良好,将图像加载到CALayers中,然后我遇到了一个障碍:CALayers没有显示 我知道CALayers在那里,因为当我在模拟器中暂停应用程序时,单击中间的硬件按钮,然后再次单击以显示它,CALayers在那里看起来很棒,但是是静态的 读了几天的帖子,尝试了各种方式在UIView和各个Calayer上设置需要显示和需要删除,我已经放弃了,我请求您的帮助 所以,请看一下下面的代码,让我知道我做错了什么。我也有问题设置我的CALayers框架。当我试着用[self-setFrame:CGRectMake(0,0,spWidth,spHeight)]设置它们时——两个nsInteger;我得到一个错误,说发送CGRect到不兼容类型NSInteger的参数。我知道这可能是新手犯的错误 以下是我的代码的相关部分。我会发布更多,但我希望我的错误在run方法中 在我看来Ios 使用setNeedsDisplay在背景中设置Calayer动画,ios,Ios,我正在将我的库从Andriod移植到IOS,在这个过程中,我已经取得了很大的进步,并学习了一些有关Objective C的知识。我说一点,因为有很多东西要学。Android库创建一个surfaceView,并通过直接将图像绘制到surfaceView来制作动画;在目标C中,我将UIView与CALayers一起使用 在UIView中,我将动态添加加载了精灵图纸图像的CALayer,然后在UIView中移动CALayer,同时通过移动CALayer的内容Rect在CALayer中的精灵图像中漫游
if ((self = [super initWithFrame:CGRectMake(0,0,dw,dh)])){
(initialization and defining variables)
self.bounds = CGRectMake(0, 0, dw, dh);
self.frame = CGRectMake(0,0,dw,dh);
self.backgroundColor = [UIColor whiteColor];
MainDrawLayer = [[CALayer layer]retain];
MainDrawLayer.bounds = CGRectMake(0, 0, dw, dh); //dw=320 dh=50.
MainDrawLayer.frame = CGRectMake(0,0,dw,dh);
[self.layer addSublayer:MainDrawLayer] ;
}
return self;
所有动作都在run方法中触发,下面我从ViewController调用该方法
- (void) run {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
PGM = [[[GadsMonitor alloc] init: @"http://www.javelin21.com/servlets/theloader" :_displaySizeW :_displaySizeH]autorelease];
while(!PGM.adsdone){
[NSThread sleepForTimeInterval:2.0];
NSLog(@"The value of adsdone is %@\n", (PGM.adsdone ? @"YES" : @"NO"));
}
NSLog(@"Into processComponent Number in PGM.PGVarray %d ", PGM.PGVarray.count);
GVarray = [PGM.PGVarray mutableCopy];
NSLog(@"Into RUN after copy GVArray %d ", GVarray.count);
Gad * readyGad = (Gad *) [GVarray objectAtIndex:0];
if (readyGad != nil)
[readyGad getImages];
NSLog(@"The value of the bool is %@\n", (readyGad.gdone ? @"YES" : @"NO"));
while (!readyGad.gdone) {
[NSThread sleepForTimeInterval:2.0];
[readyGad checkImages];
NSLog(@"The value of the readyGad.gdone is %@\n", (readyGad.gdone ? @"YES" : @"NO"));
}
rstop = NO;
while (!rstop) {
NSLog(@"The value of rstop in while is %@\n", (rstop ? @"YES" : @"NO"));
[self rotateGames];
stop = NO;
while (!stop) {
[self gameAction];
[self paint];
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsLayout]; //I have also tried self.layer
[self setNeedsDisplay]; //I have also tried self.layer
});
//These are various timers for CALayer action
[NSThread sleepForTimeInterval:stime];
rtime = (rtime +runGad.gslp);
ltime += runGad.gslp;
jtime += runGad.gslp;
vtime += runGad.gslp;
ftime += runGad.gslp;
ttime += runGad.gslp;
Stime += runGad.gslp;
NSLog(@"After Thread Sleep rtime + gslp %f ", rtime);
if ((runTime += runGad.gslp) >= runGad.grun) {
stop = YES;
}
}
stop = NO;
}
});
}
感谢您抽出时间。在iOS中,任何UI更新代码都必须在主线程中执行。您不能使用GCD(除非它在主队列上运行)或performSelectorInBackground来更新UI 您可以更新数据并在后台线程上执行IO,但当您加载了数据并希望显示数据时,必须切换回主线程 尝试其他方法有时有效,有时无效,或者使应用程序崩溃 主线程拥有iOS中的UI更新 此外,在主线程上执行工作时,您有一些选项,可以使用performSelectorOnMainThread将块排队 或者您可以向主线程GCD队列发送一个块,有时您可能需要在主线程上使用dispatch\u async vs dispatch\u sync,如果您使用GCD,它们在每种情况下都不起作用。performSelectorInMainthread似乎比GCDs主线程队列更可靠
ymmvymmv-感谢您的评论。我已经尝试过performSelectorOnMainThread,但它不起作用。我将尝试performSelectorOnMainThread。我正在调用performselectornmainthread:@selector(setNeedsDisplay),对象为:nil waitUntilDone:false)。这是正确的方法吗?它如何知道在我的UIVIew上设置需要显示?设置需要显示不是真正的问题,任何UI代码都必须在主线程中设置帧大小,设置图像。setNeedsDisplay在大多数情况下并不真正需要。您不能为此使用全局队列。或者后台thread.ymmv-performSelectorOnMain不起作用。我尝试删除performSelectorInBackground,屏幕变黑,没有显示白色背景视图。我已将图层类更改为NSObjects,只需在init上创建一个CALayer。我认为这会有帮助,因为我现在只做计算,在主线程中做UI。但是现在这些层没有被添加到我的UIView中。当I NSLog[self.layer.sublayers count]时;它是零。我以这种方式添加层[self.layer addSublayer:ags.t_layer];并以这种方式在我的NSObject类中创建层:t_layer=[[CALayer alloc]init]。我以这种方式添加图像,但它在-t_layer.contents=(id)ppImage.CGImage之前工作;(但是,不在主线程上)