0

I have 2 UIGraphicsImageRenderer tasks with different renderers and when i run this, only one task is returned as it is synchronous, how do I wait until both have created images before returning them?

func createShareImage(callback: @escaping (_ image: UIImage, _ bgImage: UIImage) -> Void) {

    let canvas = UIView()
    ...

    let format = UIGraphicsImageRendererFormat()
    format.scale = UIScreen.main.scale

    let renderer = UIGraphicsImageRenderer(size: canvas.bounds.size, format: format)
    let stickerImage = renderer.image { _ in
        canvas.drawHierarchy(in: canvas.bounds, afterScreenUpdates: true)
    }

    let bgImageView = UIView()
    ...

    let bgRenderer = UIGraphicsImageRenderer(size: bgImageView.bounds.size, format: format)
    let bgImage = bgRenderer.image { _ in
        bgImageView.drawHierarchy(in: bgImageView.bounds, afterScreenUpdates: true)
    }

    callback(stickerImage, bgImage)
    
}
Halpo
  • 2,982
  • 3
  • 25
  • 54
  • "as it is synchronous" You meant `asynchronous`, right? You can use a `DispatchQueue`, with `enter()` (before calling `image{})`, `leave()` (inside closure) and `notify()` (to call `callBack()`). – Larme Jan 25 '22 at 14:09
  • @Larme there is no closure here to call leave() in, so I'm not sure what to do – Halpo Jan 25 '22 at 14:12
  • `image { _ in }`, isn't that a closure? Isn't that the async call? – Larme Jan 25 '22 at 14:13
  • no that's where you put your drawing actions inside, the resulting image is applied to the stickerImage variable when it is complete – Halpo Jan 25 '22 at 14:14
  • That's a closure, no? Is it really async? When do you know that one has finished? Isn't it in one has finished drawing? – Larme Jan 25 '22 at 14:16

1 Answers1

0

Testing your code

func createShareImage(callback: @escaping (_ image: UIImage, _ bgImage: UIImage) -> Void) {

    let canvas = UIView(frame: CGRect.init(x: 0, y: 0, width: 200, height: 200))
    canvas.backgroundColor = .red
    let format = UIGraphicsImageRendererFormat()
    format.scale = UIScreen.main.scale
    print("1:",Thread.isMainThread)
    let renderer = UIGraphicsImageRenderer(size: canvas.bounds.size, format: format)
    let stickerImage = renderer.image { _ in
        canvas.drawHierarchy(in: canvas.bounds, afterScreenUpdates: true)
        print("2:",Thread.isMainThread)
    }

    let bgImageView = UIView(frame: CGRect.init(x: 0, y: 0, width: 2000, height: 2000))
    bgImageView.backgroundColor = .green
    let bgRenderer = UIGraphicsImageRenderer(size: bgImageView.bounds.size, format: format)
    let bgImage = bgRenderer.image { _ in
        bgImageView.drawHierarchy(in: bgImageView.bounds, afterScreenUpdates: true)
        print("3:",Thread.isMainThread)
    }

    print("4:",Thread.isMainThread)
    callback(stickerImage, bgImage)
}

Gets

1: true
2: true
3: true
4: true

Which means there is no async part , all the code is synchronous and serial and no waiting need to happen

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87