1

I am working on an app that uses a CATiledLayer backed View in a UIScrollView to let the user work on an arbitrarily large canvas. The canvas basically contains a large chart of blocks that the user can color, select, move, etc. I override draw(_ rect: CGRect) to draw on the view.

All of that is working fine - the CATiledLayer works really well to keep memory consumption down while the user is working on their chart. Scrolling and Zooming work great.

What I need to do now is allow the user to export a copy of their chart to the camera roll, but I'm running into memory issues and the app is crashing. I've tried a variety of methods to capture the view to an image. The view isn't completely visible as it's in a UIScrollView

Here is how I am currently generating the image:

// MyView is the view that is used in the scrollView
static func screenshotByDrawingItAgain(_ view: MyView) -> UIImage? {
    var image: UIImage?

    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, UIScreen.main.scale)

    guard let context = UIGraphicsGetCurrentContext() else {
        return nil
    }
    // This is where my chart data model is stored in memory
    guard let chart = view.chart else {
        return nil
    }

    // drawInRect is also called from MyView's draw(_:) method
    // so all drawing code is in one place
    view.drawInRect(context, with: chart, in: view.bounds, row: 0, col: 0)
    image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image!
}

Since charts can be any size, this means they can get quite large. I need a way to be able to export large images like this in some fashion. Example error:

BOUNDS (10200.0, 6360.0)
CGBitmapContextInfoCreate: unable to allocate 1037952000 bytes for bitmap data

Most of the posts I've seen deal with how to read in a large image (like a photo) and display it. I haven't been able to find any info on how to do the reverse and get an image of a view out. Is there a way I can generate smaller tiles of the view onto a file and then stitch it together and give them access to the resulting file? Thanks!

N.W
  • 672
  • 2
  • 8
  • 19
  • instead of capturing all of the view’s content as image, try capturing separate parts and then merge them in a file. Since bitmap is not compressed like png or jpg, they can take so much space when allocate like this. It seems to be complex but it is worthy for your kind of task. Use some `CGRect` instead `view.bounds` – Cosmos Man Jul 18 '18 at 04:31
  • So I could definitely use drawInRect to generate a smaller image as it does take a CGRect in and then do something with that. Any pointers for how to generate a file from that rect, and then combine all those files into one image that doesn't have to be read back into memory. Second step seems more problematic... – N.W Jul 18 '18 at 04:46

0 Answers0