This is a code snippet that demonstrates the effect you want, I think. You should be able to paste it into a new "single view" iOS project as the viewDidLoad()
method of the view controller that the Xcode template creates.
I needed some way to set the content of the mask view without creating a subclass of UIView
(because I'm lazy) so my sample creates an image (whose alpha channel is 1.0 for the most part with a 100x100 square of clear alpha channel). I set this to be the content of the mask view.
The timer at the end just cycles through a bunch of colors for the outer view because... it's fun.
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blue
let overallView = UIView(frame: CGRect(x:100, y:100, width:300, height:300))
overallView.backgroundColor = UIColor.green
// Draw a graphics with a mostly solid alpha channel
// and a square of "clear" alpha in there.
UIGraphicsBeginImageContext(overallView.bounds.size)
let cgContext = UIGraphicsGetCurrentContext()
cgContext?.setFillColor(UIColor.white.cgColor)
cgContext?.fill(overallView.bounds)
cgContext?.clear(CGRect(x:100, y:100, width: 100, height: 100))
let maskImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// Set the content of the mask view so that it uses our
// alpha channel image
let maskView = UIView(frame: overallView.bounds)
maskView.layer.contents = maskImage?.cgImage
overallView.mask = maskView
self.view.addSubview(overallView)
var hue = CGFloat(0)
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) {
(_) in
let color = UIColor(hue: hue, saturation: 1.0, brightness: 1.0, alpha: 1.0)
hue = hue + (1.0/20);
if hue >= 1.0 { hue = 0 }
overallView.backgroundColor = color
}
}