Convert a UIImage into cgContext

I have a UIImageView that will serve as a drawing canvas and i want to implement a function that will get the content inside of UIImageView and convert it into a cgContect so it could be set as a background for the canvas to draw over but i ran into an issue. I have a reset button that will set the UIImageView.image to nil (to clear the current UIview) for that I tried to save the UIImageView into a canvasArray array to save it into a second view savedImageView

this is my reset function that will delete the content of mainImageView

@objc func resetPressed(_ sender: Any) {
        mainImageView.image = nil
    }

The array that will is store and object that receives mainImageView as a param and the function that saved it

  var canvasArray: [Canvas] = []

  @objc func saveCanvas(_ sender: Any)   {.      
                                                   //here is the UIImageView
        guard let canvas = Canvas(name: "", canvas: mainImageView, numOfPages: 0) else {
            return
        }
    
        canvasArray.append(canvas)
        
        if canvasArray.count > 0 {
            canvasArray.forEach{ canvas in
                print("\(canvas.canvas.image)")
              
            }
        }
    }

And the function that will get the iUIImageView.image and will convert it into cgContext

 @objc func changeImagefunc(_ sender: Any) {
        if canvasArray.count < pages {
            return
        }

   
        if let savedImage = canvasArray[pages].canvas.image {
   
            UIGraphicsBeginImageContext(view.frame.size)

          
            savedImage.draw(in: view.bounds)

       
            if let drawnImage = UIGraphicsGetImageFromCurrentImageContext() {
             
                mainImageView.image = drawnImage
            }

           
            UIGraphicsEndImageContext()
            print("clicked button ")
        }
    }

I have 3 different UIViewImage that will ser a specific purpose mainImageView and tempImageView that will check the start and and of the drawing (function(which works fine) and the savedImageView that will receive the image converted into "cgContext " . Three of them stored in a function that then gets passed into the viewDidLoad section

 func setupImageViews() {
        view.addSubview(tempImageView)
        tempImageView.frame = view.bounds
        
        if savedImageView.image != nil {
            view.addSubview(savedImageView)
            savedImageView.frame = view.bounds
        } else {
            view.addSubview(mainImageView)
            mainImageView.frame = view.bounds
        }
    }

Like I said i can not get this to work because the resetButton/function is deleted not only the current UIImageView (which is what is intended to do ) but also deletes the content inside the canvasArray which I want to avoid. Would there ve a different approach to it or what else do you recommend?

Replies

Instead of using the UIImageView as the source of truth for your drawing, I would instead recommend tracking your drawing separately and then updating the UIImageView as necessary – then you never need to get content from the image view and you can reset it at your whim without worry. By doing this you will never need to snapshot the image view either – you always draw to the canvas's CGContext, and then grab an image from that to place in the UIImageView.

When the data of your app is drawing, the views you use to display that drawing should be treated as implementation details, not as the source of truth.

Add a Comment

I see @Rincewind and by keeping track of the only think i could think of was to create an array var savedDrawings: [CGContext] = [] as a storing method and use it inside of my saveCanvas function like this: savedDrawings.append(savedImage as! CGContext) but that would crash my app showing Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) error. Do you have any suggestions for other methods to keep track of the drawings?

My best guess would be that you are running out of memory – images can be quite large so if you are trying to store many of them in memory at once you can pretty easily exhaust the amount of memory you have available.