Ios 使用setNeedsDisplay在背景中设置Calayer动画

Ios 使用setNeedsDisplay在背景中设置Calayer动画,ios,Ios,我正在将我的库从Andriod移植到IOS,在这个过程中,我已经取得了很大的进步,并学习了一些有关Objective C的知识。我说一点,因为有很多东西要学。Android库创建一个surfaceView,并通过直接将图像绘制到surfaceView来制作动画;在目标C中,我将UIView与CALayers一起使用 在UIView中,我将动态添加加载了精灵图纸图像的CALayer,然后在UIView中移动CALayer,同时通过移动CALayer的内容Rect在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方法中

在我看来

    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主线程队列更可靠


ymmv

ymmv-感谢您的评论。我已经尝试过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之前工作;(但是,不在主线程上)