后台任务中将UIImage添加到CALayer中时未显示

5
在我的视图控制器中,我有以下代码:

@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)方法中,我试图在worldmapview中展示图片。下面的代码在没有任何后台任务的情况下能够正常工作。这张图片将会立即显示。
// 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") 是同步的,不会立即返回吗? - SwiftArchitect
你说得对。我更新了代码。我写了“它是空的”,然后就遇到了这种情况。你有什么提示如何解决吗?我想在后台准备图层,当图层添加后刷新视图。怎么做呢? - mcfly soft
你不应该在后台线程中修改UI。 - kelin
请看代码。我并没有做这个。同样的方式,我可以展示CALayers而不需要任何图片也没有问题。 - mcfly soft
有人对此有解决方案吗? - mcfly soft
1个回答

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()
    })
})

谢谢你的帮助,但是它没有起作用。我更新了我的代码。在那里我们可以看到,我的新添加的圆形立即出现,但图片形状却没有。问题是为什么? - mcfly soft
getImage背后是什么?您尝试过使用Assets目录中存在的图像吗? - SwiftArchitect
我刚刚更新了getImage()函数的代码。我没有尝试使用资源目录。在我的情况下,这也是不可能的,因为我不知道有哪些图片。它们位于设备上的特定文件夹中。 - mcfly soft
那个点赞示例的人成功测试了解决方案吗? - mcfly soft
问题:你试过我的代码并且在新的解决方案中它能够正常工作吗?因为对我来说它没有。 - mcfly soft
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接