【问题标题】:UIImage not displayed when added to CALayer in a backgroundtask在后台任务中添加到 CALayer 时不显示 UIImage
【发布时间】:2016-02-29 06:03:44
【问题描述】:

在我的视图控制器中,我有:

@IBOutlet var worldmapview: Worldmapview!


var eventLayer:CALayer=CALayer();

还有一些功能:

func create_picture_layer(pathtopic:String) -> CALayer {
    let bm=getImage(pathtopic,fBitmapsizeSelected: 100)!;
    var calayer_for_picture=CALayer();
    calayer_for_picture.frame=CGRectMake(100, 100, 100, 100);
    calayer_for_picture.contents = bm.CGImage;
    return calayer_for_picture;
}

func createCircleShape(x:CGFloat,y:CGFloat, size:CGFloat) -> CAShapeLayer {

    var test2:UIBezierPath=UIBezierPath(ovalInRect: CGRectMake(x - size/2, y - size/2, size, size));

    var shapelayer:CAShapeLayer=CAShapeLayer();
    shapelayer.backgroundColor=UIColor.clearColor().CGColor;
    //shapelayer.frame=CGRectMake(0, 0, 300, 300);
    shapelayer.fillColor=UIColor.darkGrayColor().CGColor;
    shapelayer.path=test2.CGPath;
    shapelayer.opaque=true

    return shapelayer;
}

func getImage(simagename: String, fBitmapsizeSelected:CGFloat) -> UIImage?{

    var sPathToImage:String=AppProperties.sharedInstance.sPicturePath + simagename;
    let checkValidation = NSFileManager.defaultManager()

    if (!checkValidation.fileExistsAtPath(sPathToImage) || simagename.equals("")){
        // Path to unknown image
        let sunknownimagename:String = "na/na.jpa";
        sPathToImage=AppProperties.sharedInstance.sPicturePath + sunknownimagename;
    }

    let bm:UIImage=UIImage(contentsOfFile: sPathToImage)!;
    var bMapScaled:UIImage;
    if(!bm.isEqual(nil)){
        let newSize:CGSize=CGSizeMake(fBitmapsizeSelected, fBitmapsizeSelected);
        bMapScaled = bm.imageByScalingToSize(newSize,contentMode: UIViewContentMode.ScaleAspectFill)!;
        return bMapScaled;
    }else{
        return nil;
    }
}

在我的viewDidAppear(animated: Bool) method 中,我尝试在世界地图视图中显示图像

以下代码无需任何后台任务即可正常工作。图像立即显示。

// works
let thepicturelayer=create_picture_layer("mypicpath")
eventLayer.addSublayer(thepicturelayer);
worldmapview.layer.addSublayer(eventLayer);
eventLayer.setNeedsDisplay();

在后台任务中并在主要任务中刷新它对我不起作用。图片未显示。一段时间后它会出现,但并非总是如此。

// doesn't work

        let qualityOfServiceClass = QOS_CLASS_BACKGROUND
        let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)

        dispatch_async(backgroundQueue, {
            // geht auch mit Eventlayer

            let thepicturelayer=self.create_picture_layer() // This Shape doesn't appear.
            let circleshapelayer=self.createCircleShape(200, y: 200, size: 20) // This shape appears immediatelly.

            self.eventLayer.addSublayer(thepicturelayer);
            self.eventLayer.addSublayer(circleshapelayer);


            dispatch_async(dispatch_get_main_queue(),{
                    //assert(self.eventLayer.sublayers?.count > 0,"no layers in eventLayer !") // just added

                    self.worldmapview.layer.addSublayer(self.eventLayer);
                    //assert(self.worldmapview.layer.sublayers!.count > 0,"no layers in worldmapview!" ) // just added
                    let sublayers=self.eventLayer.sublayers;
                    if sublayers != nil {
                        for l in self.eventLayer.sublayers! {
                            l.setNeedsDisplay()
                        }
                    }
                    //self.updateWorldMapGUI();
                    self.worldmapview.layer.addSublayer(self.eventLayer);
                    //thepicturelayer.setNeedsDisplay();
                    //circleshapelayer.setNeedsDisplay();
                    self.eventLayer.setNeedsDisplay();

            })
        })

更新

我用相同的方式添加了一个新的 CAShapelayer 更新了代码,它会立即显示。我不明白其中的区别。图片在后台任务中创建时不显示。

更新2

我还意识到一些令我困惑的事情: 没有后台任务的以下代码如前所述工作:

    let thepicturelayer=create_picture_layer()
    eventLayer.addSublayer(thepicturelayer);
    worldmapview.layer.addSublayer(eventLayer);
    eventLayer.setNeedsDisplay();
    //thepicturelayer.setNeedsDisplay(); // When adding this, the picture is not shown.

但是激活最后一行,图片没有出现。可能与它有关?好像calayer的内容没了?

【问题讨论】:

  • 你能确认self.create_picture_layer("mypicpath")是同步的,不会立即返回吗?
  • 你是对的。我更新了代码。我写了“它是空的”,它遇到了这种情况。你有任何提示如何解决这个问题吗?添加图层后,我想在后台准备图层并刷新视图。该怎么做?
  • 你不应该在后台线程中修改 UI。
  • 请看代码。我不这样做。就像我可以在没有 UIImages 的情况下显示 CALayers 一样,没有任何问题。
  • 有人有解决方案吗?

标签: ios swift uiimage calayer


【解决方案1】:

据我了解,您正在后台创建CALayer并且将该层添加到后台的 UI 层次结构中。

认为所有 UI 修改都发生在 main 线程中是否合理?如果是这样,试试这个:

let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)

dispatch_async(backgroundQueue, {
    let thepicturelayer=self.create_picture_layer()

    dispatch_async(dispatch_get_main_queue(),{
        self.eventLayer.addSublayer(thepicturelayer);
        assert(self.eventLayer.sublayers) // just added

        self.worldmapview.layer.addSublayer(self.eventLayer);
        assert(self.worldmapview.layer.sublayers) // just added

        self.worldmapview.setNeedsDisplay()
    })
})

【讨论】:

  • 感谢您的帮助,但没有奏效。我更新了我的代码。我们可以看到,我新添加的圆形会立即出现,但图片不会。问题是为什么?
  • getImage 背后是什么?您是否尝试过使用资产目录中的图片?
  • 我刚刚用getImage()的代码更新了这个问题。我没有尝试使用资产目录。这在我的情况下也是不可能的,因为我不知道那里有哪些图片。它们位于设备上的特定文件夹中。
  • 点赞样本的人是否成功测试了解决方案?
  • 我刚刚意识到一些令人困惑的事情,我在 UPDATE2 下的问题中进行了描述。大概和它有关?
猜你喜欢
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多