Simply mask a UIView with a rectangle Simply mask a UIView with a rectangle ios ios

Simply mask a UIView with a rectangle


Thanks to the link from MSK, this is the way I went with which works well:

// Create a mask layer and the frame to determine what will be visible in the view.CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];CGRect maskRect = CGRectMake(0, 0, 50, 100);// Create a path with the rectangle in it.CGPathRef path = CGPathCreateWithRect(maskRect, NULL);// Set the path to the mask layer.maskLayer.path = path;// Release the path since it's not covered by ARC.CGPathRelease(path);// Set the mask of the view.viewToMask.layer.mask = maskLayer;


Thanks for answers guys.

In case someone can't find suitable answer on SO for this question for hours, like i just did, i've assembled a working gist in Swift 2.2 for masking/clipping UIView with CGRect/UIBezierPath:

https://gist.github.com/Flar49/7e977e81f1d2827f5fcd5c6c6a3c3d94

extension UIView {    func mask(withRect rect: CGRect, inverse: Bool = false) {        let path = UIBezierPath(rect: rect)        let maskLayer = CAShapeLayer()        if inverse {            path.append(UIBezierPath(rect: self.bounds))            maskLayer.fillRule = kCAFillRuleEvenOdd        }        maskLayer.path = path.cgPath        self.layer.mask = maskLayer    }    func mask(withPath path: UIBezierPath, inverse: Bool = false) {        let path = path        let maskLayer = CAShapeLayer()        if inverse {            path.append(UIBezierPath(rect: self.bounds))            maskLayer.fillRule = kCAFillRuleEvenOdd        }        maskLayer.path = path.cgPath        self.layer.mask = maskLayer    }}

Usage:

let viewSize = targetView.bounds.sizelet rect = CGRect(x: 20, y: 20, width: viewSize.width - 20*2, height: viewSize.height - 20*2)// Cuts rectangle inside view, leaving 20pt borders aroundtargetView.mask(withRect: rect, inverse: true)// Cuts 20pt borders around the view, keeping part inside rect intacttargetView.mask(withRect: rect)

Hope it will save someone some time in the future :)


No need any mask at all.Just put it into a wrapper view with the smaller frame, and set clipsToBounds.

wrapper.clipsToBounds = true