Here is one way, using paths that convert to an image (this function creates a random circle, square, or triangle):
func getRandomShape() -> UIImage {
    let rect = CGRect(x: 0, y: 0, width: 12, height: 12)
    let options = [1,2,3]
    var path:CGPath? = nil
    switch options.randomElement() {
    case 1:
        path =  CGPath(ellipseIn: rect, transform: nil)
    case 2:
        let cmp = CGMutablePath()
        cmp.addLines(between: [
            CGPoint(x: rect.midX, y: 0),
            CGPoint(x: rect.maxX, y: rect.maxY),
            CGPoint(x: rect.minX, y: rect.maxY),
            CGPoint(x: rect.midX, y: 0)
        ])
        path = cmp
    case 3:
        path = CGPath(rect: rect, transform: nil)
    default:
        path = CGPath(rect: rect, transform: nil)
    }
    
    return UIGraphicsImageRenderer(size: rect.size).image { context in
        context.cgContext.setFillColor(UIColor.white.cgColor)
        context.cgContext.addPath(path!)
        context.cgContext.fillPath()
    }
}
Don't forget to take the .cgImage of the UIImage this returns.  E.g.:  getRandomShape().cgImage