Draw Custom Shape Swift - ios

I'm trying to draw a shape which would resemble a ticket - something like the image below. I'm just really interested in the outline and none of the inner details. I know this can be done by creating a custom UIView and overriding the drawRect method. I know how to draw simple shapes like a rectangle, as seen in the code below, however I'm not sure how to draw the curves as required in this case.
override func drawRect(rect: CGRect) {
let size = self.bounds.size
let p1 = self.bounds.origin
let p2 = CGPoint(x:p1.x + size.width, y:p1.y)
let p3 = CGPoint(x:p2.x, y:p2.y + size.height)
let p4 = CGPoint(x:p1.x, y:p1.y + size.height)
let path = UIBezierPath()
path.moveToPoint(p1)
path.addLineToPoint(p2)
path.addLineToPoint(p3)
path.addLineToPoint(p4)
path.closePath()
UIColor.blackColor().set()
path.fill()
}

Use addCurve with controlPoints. You can/should make some adjustments to this snippet:
// Color Declaration
let color = UIColor(red: 0.964, green: 0.952, blue: 0.000, alpha: 1.000)
// Bezier Drawing
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 144.5, y: 82.5))
bezierPath.addLine(to: CGPoint(x: 969.5, y: 82.5))
bezierPath.addCurve(to: CGPoint(x: 969.5, y: 138.5), controlPoint1: CGPoint(x: 969.5, y: 82.5), controlPoint2: CGPoint(x: 957.5, y: 118.25))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 163.5), controlPoint1: CGPoint(x: 981.5, y: 158.75), controlPoint2: CGPoint(x: 1017.5, y: 163.5))
bezierPath.addCurve(to: CGPoint(x: 997.5, y: 184.5), controlPoint1: CGPoint(x: 1017.5, y: 163.5), controlPoint2: CGPoint(x: 997.5, y: 173.5))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 207.5), controlPoint1: CGPoint(x: 997.5, y: 195.5), controlPoint2: CGPoint(x: 1017.5, y: 207.5))
bezierPath.addCurve(to: CGPoint(x: 997.5, y: 234.5), controlPoint1: CGPoint(x: 1017.5, y: 207.5), controlPoint2: CGPoint(x: 997.5, y: 222.25))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 256.5), controlPoint1: CGPoint(x: 997.5, y: 246.75), controlPoint2: CGPoint(x: 1017.5, y: 256.5))
bezierPath.addCurve(to: CGPoint(x: 997.5, y: 280.5), controlPoint1: CGPoint(x: 1017.5, y: 256.5), controlPoint2: CGPoint(x: 997.5, y: 267.5))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 308.5), controlPoint1: CGPoint(x: 997.5, y: 293.5), controlPoint2: CGPoint(x: 1017.5, y: 308.5))
bezierPath.addCurve(to: CGPoint(x: 997.5, y: 330.5), controlPoint1: CGPoint(x: 1017.5, y: 308.5), controlPoint2: CGPoint(x: 997.5, y: 318.75))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 355.5), controlPoint1: CGPoint(x: 997.5, y: 342.25), controlPoint2: CGPoint(x: 1017.5, y: 355.5))
bezierPath.addCurve(to: CGPoint(x: 997.5, y: 384.5), controlPoint1: CGPoint(x: 1017.5, y: 355.5), controlPoint2: CGPoint(x: 997.5, y: 372))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 405.5), controlPoint1: CGPoint(x: 997.5, y: 397), controlPoint2: CGPoint(x: 1017.5, y: 405.5))
bezierPath.addCurve(to: CGPoint(x: 997.5, y: 427.5), controlPoint1: CGPoint(x: 1017.5, y: 405.5), controlPoint2: CGPoint(x: 997.5, y: 415.5))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 453.5), controlPoint1: CGPoint(x: 997.5, y: 439.5), controlPoint2: CGPoint(x: 1017.5, y: 453.5))
bezierPath.addCurve(to: CGPoint(x: 997.5, y: 479.5), controlPoint1: CGPoint(x: 1017.5, y: 453.5), controlPoint2: CGPoint(x: 997.5, y: 466.75))
bezierPath.addCurve(to: CGPoint(x: 1017.5, y: 504.5), controlPoint1: CGPoint(x: 997.5, y: 492.25), controlPoint2: CGPoint(x: 1017.5, y: 504.5))
bezierPath.addCurve(to: CGPoint(x: 969.5, y: 504.5), controlPoint1: CGPoint(x: 1017.5, y: 504.5), controlPoint2: CGPoint(x: 981.5, y: 489.5))
bezierPath.addCurve(to: CGPoint(x: 969.5, y: 564.5), controlPoint1: CGPoint(x: 957.5, y: 519.5), controlPoint2: CGPoint(x: 969.5, y: 564.5))
bezierPath.addLine(to: CGPoint(x: 144.5, y: 564.5))
bezierPath.addCurve(to: CGPoint(x: 122.5, y: 504.5), controlPoint1: CGPoint(x: 144.5, y: 564.5), controlPoint2: CGPoint(x: 143, y: 519.5))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 504.5), controlPoint1: CGPoint(x: 102, y: 489.5), controlPoint2: CGPoint(x: 62.5, y: 504.5))
bezierPath.addCurve(to: CGPoint(x: 86.5, y: 479.5), controlPoint1: CGPoint(x: 62.5, y: 504.5), controlPoint2: CGPoint(x: 86.5, y: 492.25))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 453.5), controlPoint1: CGPoint(x: 86.5, y: 466.75), controlPoint2: CGPoint(x: 62.5, y: 453.5))
bezierPath.addCurve(to: CGPoint(x: 86.5, y: 427.5), controlPoint1: CGPoint(x: 62.5, y: 453.5), controlPoint2: CGPoint(x: 86.5, y: 439.5))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 405.5), controlPoint1: CGPoint(x: 86.5, y: 415.5), controlPoint2: CGPoint(x: 62.5, y: 405.5))
bezierPath.addCurve(to: CGPoint(x: 86.5, y: 384.5), controlPoint1: CGPoint(x: 62.5, y: 405.5), controlPoint2: CGPoint(x: 86.5, y: 397))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 355.5), controlPoint1: CGPoint(x: 86.5, y: 372), controlPoint2: CGPoint(x: 62.5, y: 355.5))
bezierPath.addCurve(to: CGPoint(x: 86.5, y: 330.5), controlPoint1: CGPoint(x: 62.5, y: 355.5), controlPoint2: CGPoint(x: 86.5, y: 342.25))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 308.5), controlPoint1: CGPoint(x: 86.5, y: 318.75), controlPoint2: CGPoint(x: 62.5, y: 308.5))
bezierPath.addCurve(to: CGPoint(x: 86.5, y: 280.5), controlPoint1: CGPoint(x: 62.5, y: 308.5), controlPoint2: CGPoint(x: 86.5, y: 293.5))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 256.5), controlPoint1: CGPoint(x: 86.5, y: 267.5), controlPoint2: CGPoint(x: 62.5, y: 256.5))
bezierPath.addCurve(to: CGPoint(x: 86.5, y: 234.5), controlPoint1: CGPoint(x: 62.5, y: 256.5), controlPoint2: CGPoint(x: 86.5, y: 246.75))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 207.5), controlPoint1: CGPoint(x: 86.5, y: 222.25), controlPoint2: CGPoint(x: 62.5, y: 207.5))
bezierPath.addCurve(to: CGPoint(x: 86.5, y: 184.5), controlPoint1: CGPoint(x: 62.5, y: 207.5), controlPoint2: CGPoint(x: 86.5, y: 195.5))
bezierPath.addCurve(to: CGPoint(x: 62.5, y: 163.5), controlPoint1: CGPoint(x: 86.5, y: 173.5), controlPoint2: CGPoint(x: 62.5, y: 163.5))
bezierPath.addCurve(to: CGPoint(x: 122.5, y: 138.5), controlPoint1: CGPoint(x: 62.5, y: 163.5), controlPoint2: CGPoint(x: 102, y: 158.75))
bezierPath.addCurve(to: CGPoint(x: 144.5, y: 82.5), controlPoint1: CGPoint(x: 143, y: 118.25), controlPoint2: CGPoint(x: 144.5, y: 82.5))
bezierPath.close()
color.setFill()
bezierPath.fill()
UIColor.black.setStroke()
bezierPath.lineWidth = 1
bezierPath.stroke()
And here is the result:

Related

The effect displayed by SKShapeNode is different from that of CAShapelayer

I am going to use SKShapeNode to display a Bezier curve graph, but the displayed effect is very strange, and it is not the same as the one displayed by CAShapeLayer. I don't know what is wrong. Does anyone know the problem?
Here is a screenshot of the effect I showed in two different ways.
The effect displayed by CAShapeLayer looks normal and is as expected
the effect displayed by SKShapeNode misses some lines
here is my main code:
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 54.5, y: 244.5))
bezierPath.addCurve(to: CGPoint(x: 54.5, y: 164.5), controlPoint1: CGPoint(x: 53.5, y: 243.5), controlPoint2: CGPoint(x: 29.5, y: 201.5))
bezierPath.addCurve(to: CGPoint(x: 54.5, y: 70.5), controlPoint1: CGPoint(x: 79.5, y: 127.5), controlPoint2: CGPoint(x: 54.5, y: 70.5))
bezierPath.addLine(to: CGPoint(x: 227.5, y: 70.5))
bezierPath.addCurve(to: CGPoint(x: 227.5, y: 164.5), controlPoint1: CGPoint(x: 227.5, y: 70.5), controlPoint2: CGPoint(x: 254.5, y: 127.5))
bezierPath.addCurve(to: CGPoint(x: 227.5, y: 244.5), controlPoint1: CGPoint(x: 200.5, y: 201.5), controlPoint2: CGPoint(x: 227.5, y: 244.5))
bezierPath.addCurve(to: CGPoint(x: 54.5, y: 244.5), controlPoint1: CGPoint(x: 227.5, y: 244.5), controlPoint2: CGPoint(x: 55.5, y: 245.5))
bezierPath.close()
let scene = SKScene.init(size: CGSize.init(width: 300, height: 300))
scene.backgroundColor = UIColor.white
self.contentView.presentScene(scene)
let node = SKShapeNode.init()
node.path = bezierPath.cgPath
node.lineJoin = .miter
node.lineCap = .round
node.miterLimit = 10
node.strokeColor = SKColor.blue
node.fillColor = SKColor.red
node.lineWidth = 10
node.isAntialiased = true
scene.addChild(node)
this code should work for you -- adding the path elements in a clockwise direction
let N:CGFloat = 300 //box size
let C:CGFloat = 20 //control offset
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 0, y: 0))
bezierPath.addCurve(to: CGPoint(x:0, y:N*0.5),
controlPoint1: CGPoint(x:C, y:N*0.15),
controlPoint2: CGPoint(x:C, y:N*0.35))
bezierPath.addCurve(to: CGPoint(x:0, y:N),
controlPoint1: CGPoint(x:-C, y:N*0.65),
controlPoint2: CGPoint(x:-C, y:N*0.85))
bezierPath.addLine(to: CGPoint(x:N, y:N))
bezierPath.addCurve(to: CGPoint(x:N, y:N*0.5),
controlPoint1: CGPoint(x:N-C, y:N*0.85),
controlPoint2: CGPoint(x:N-C, y:N*0.65))
bezierPath.addCurve(to: CGPoint(x:N, y:0),
controlPoint1: CGPoint(x:N+C, y:N*0.35),
controlPoint2: CGPoint(x:N+C, y:N*0.15))
bezierPath.close()

CAShapeLayer draws different line width for one path, Swift

i have a problem while drawing curve:
strokePath = UIBezierPath()
strokePath.move(to: CGPoint(x:curveWidth / 2.0 - headerWidth, y: headerHeight))
strokePath.addLine(to: CGPoint(x: 0, y: headerHeight))
strokePath.addCurve(to: CGPoint(x: curveRadius, y: headerHeight - curveRadius),
controlPoint1: CGPoint(x: degree, y: headerHeight),
controlPoint2: CGPoint(x: curveRadius, y: headerHeight - curveRadius))
strokePath.addLine(to: CGPoint(x: curveWidth - curveRadius, y: curveRadius))
strokePath.addCurve(to: CGPoint(x: curveWidth, y: 0),
controlPoint1: CGPoint(x: curveWidth - curveRadius + curveRadius * 0.25, y: 0),
controlPoint2: CGPoint(x: curveWidth, y: 0))
strokePath.addLine(to: CGPoint(x: self.frame.size.width, y: 0.0))
strokeLayer.path = strokePath.cgPath
strokeLayer.strokeColor = uiConfig.color.misc.tabGrayBorder.cgColor
strokeLayer.fillColor = UIColor.clear.cgColor
strokeLayer.lineWidth = 0.5
self.layer.addSublayer(strokeLayer)
and i have unexpectable result:
curve is bold than the line, have somebody idea why it happened and how it fixing?
sorry, its my mistake after review many lines of code i find active "Clip to bounds" property of one of my parent view

Swift- Detect tap on NSMutableAttributedString

Is there anyway I can detect tap on NSMutableAttributedString. I have a Sunburst chart. On click of every element I want to show a alert and save that value in Core Data. Right now I have posted only some part of code because the original code is too long to read. I know I can't show alert on UIBezierPath because it is being drawn together for a group of elements so I have no choice but to show alert on NSMutableAttributedString only.
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()!
/// Group 5
do {
context.saveGState()
context.translateBy(x: 337.7, y: 334.39)
context.rotate(by: -1654 * CGFloat.pi/180)
context.translateBy(x: -321.5, y: -318)
/// Group 4
do {
context.saveGState()
/// Group 8
do {
context.saveGState()
context.translateBy(x: 0.35, y: 0.03)
/// Path
let path8 = UIBezierPath()
path8.move(to: CGPoint(x: 0, y: 32.29))
path8.addCurve(to: CGPoint(x: 141.21, y: 0), controlPoint1: CGPoint(x: 42.61, y: 11.61), controlPoint2: CGPoint(x: 90.54, y: 0))
path8.addCurve(to: CGPoint(x: 213.67, y: 8.12), controlPoint1: CGPoint(x: 166.13, y: 0), controlPoint2: CGPoint(x: 190.39, y: 2.81))
path8.addLine(to: CGPoint(x: 196.1, y: 78.67))
path8.addCurve(to: CGPoint(x: 137.83, y: 71.74), controlPoint1: CGPoint(x: 177.42, y: 74.14), controlPoint2: CGPoint(x: 157.9, y: 71.74))
path8.addCurve(to: CGPoint(x: 28.81, y: 97.08), controlPoint1: CGPoint(x: 98.69, y: 71.74), controlPoint2: CGPoint(x: 61.69, y: 80.85))
path8.addLine(to: CGPoint(x: 0, y: 32.29))
path8.close()
context.saveGState()
context.translateBy(x: 179.79, y: 0)
path8.usesEvenOddFillRule = true
UIColor(hue: 0.133, saturation: 0.137, brightness: 1, alpha: 1).setFill()
path8.fill()
path8.lineWidth = 1
UIColor(white: 0.592, alpha: 1).setStroke()
path8.stroke()
context.restoreGState()
/// Path
let path10 = UIBezierPath()
path10.move(to: CGPoint(x: 77.66, y: 347.23))
path10.addLine(to: CGPoint(x: 11.79, y: 310.67))
path10.addCurve(to: CGPoint(x: 44.49, y: 187.63), controlPoint1: CGPoint(x: 32.59, y: 274.44), controlPoint2: CGPoint(x: 44.49, y: 232.43))
path10.addCurve(to: CGPoint(x: 0, y: 46.03), controlPoint1: CGPoint(x: 44.49, y: 134.96), controlPoint2: CGPoint(x: 28.04, y: 86.13))
path10.addLine(to: CGPoint(x: 61.01, y: 0))
path10.addCurve(to: CGPoint(x: 121.96, y: 186.18), controlPoint1: CGPoint(x: 99.35, y: 52.3), controlPoint2: CGPoint(x: 121.96, y: 116.63))
path10.addCurve(to: CGPoint(x: 77.66, y: 347.23), controlPoint1: CGPoint(x: 121.96, y: 244.96), controlPoint2: CGPoint(x: 105.81, y: 300.01))
path10.close()
context.saveGState()
context.translateBy(x: 520.04, y: 131.32)
path10.usesEvenOddFillRule = true
UIColor(hue: 0.582, saturation: 0.882, brightness: 1, alpha: 1).setFill()
path10.fill()
path10.lineWidth = 1
UIColor(white: 0.592, alpha: 1).setStroke()
path10.stroke()
context.restoreGState()
/// Path
let path12 = UIBezierPath()
path12.move(to: CGPoint(x: 202.13, y: 121.2))
path12.addLine(to: CGPoint(x: 141.15, y: 167.21))
path12.addCurve(to: CGPoint(x: 0, y: 70.57), controlPoint1: CGPoint(x: 107.58, y: 119.98), controlPoint2: CGPoint(x: 57.83, y: 85.06))
path12.addLine(to: CGPoint(x: 17.57, y: 0))
path12.addCurve(to: CGPoint(x: 202.13, y: 121.2), controlPoint1: CGPoint(x: 92.8, y: 17.64), controlPoint2: CGPoint(x: 157.78, y: 61.47))
path12.close()
context.saveGState()
context.translateBy(x: 377.77, y: 8.56)
path12.usesEvenOddFillRule = true
UIColor(hue: 0.208, saturation: 0.328, brightness: 0.91, alpha: 1).setFill()
path12.fill()
path12.lineWidth = 1
UIColor(white: 0.592, alpha: 1).setStroke()
path12.stroke()
context.restoreGState()
context.restoreGState()
}
context.restoreGState()
}
/// Geranium
let geranium = NSMutableAttributedString(string: "Geranium")
geranium.addAttribute(.font, value: UIFont(name: "Helvetica-Bold", size: 10)!, range: NSRange(location: 0, length: geranium.length))
context.saveGState()
context.translateBy(x: 130.07, y: 523.08)
context.rotate(by: 490 * CGFloat.pi/180)
context.translateBy(x: -23.5, y: -6)
geranium.draw(at: CGPoint.zero)
context.restoreGState()
/// Lavender
let lavender = NSMutableAttributedString(string: "Lavender")
lavender.addAttribute(.font, value: UIFont(name: "Helvetica-Bold", size: 10)!, range: NSRange(location: 0, length: lavender.length))
context.saveGState()
context.translateBy(x: 81.5, y: 464.82)
context.rotate(by: 872 * CGFloat.pi/180)
context.translateBy(x: -22.5, y: -6)
lavender.draw(at: CGPoint.zero)
context.restoreGState()
}
}
Output:
You aren't able to detect tap on drawn NSAttributedString because tap is a abstraction from UIKit layer but drawing in rect isn't. So you can use hitTest(_:with:) for tap detection and use its coordinates to compare with coordinates of your NSAttributedString.

Mask UIView (UICollectionView) correctly

Ok, I need to mask a horizontal UICollectionViewso it looks like a ribbon. My web dev counterpart got it done with an SVG that he used as a masking layer.
Here is my current situation:
And here is what I need (Photo from our web app):
Small detail in image spacing aside, I have an SVG like this:
Which I can successfully convert into UIBezierPath code (Paintcode):
let pathPath = UIBezierPath()
pathPath.move(to: CGPoint(x: 0.05, y: 0))
pathPath.addCurve(to: CGPoint(x: 162.02, y: 3.8), controlPoint1: CGPoint(x: 0.05, y: 2.1), controlPoint2: CGPoint(x: 72.57, y: 3.8))
pathPath.addCurve(to: CGPoint(x: 324, y: 0), controlPoint1: CGPoint(x: 251.48, y: 3.8), controlPoint2: CGPoint(x: 324, y: 2.1))
pathPath.addLine(to: CGPoint(x: 324, y: 150.2))
pathPath.addCurve(to: CGPoint(x: 162.02, y: 154), controlPoint1: CGPoint(x: 324, y: 152.3), controlPoint2: CGPoint(x: 251.48, y: 154))
pathPath.addCurve(to: CGPoint(x: 0.05, y: 150.2), controlPoint1: CGPoint(x: 72.57, y: 154), controlPoint2: CGPoint(x: 0.05, y: 152.3))
pathPath.addCurve(to: CGPoint(x: 0, y: 0.17), controlPoint1: CGPoint(x: 0.05, y: 148.1), controlPoint2: CGPoint(x: 0, y: 0.17))
pathPath.usesEvenOddFillRule = true
UIColor.lightGray.setFill()
pathPath.fill()
Now what do I do?
You should use the mask property of your UICollectionView by setting it to a view whose alpha channel indicates what part of the UICollectionView you want to mask out. In outline it will probably be something like:
// If you don't have a custom subclass of UICollectionView... you can handle the resize in the
// UICollectionViewController or whatever view contoller is handling your view.
//
// If you do have a custom subclass of UICollectionView... you could do something similar
// in layoutSubviews.
class MyViewController : UICollectionViewController {
// recreate the mask after the view lays out it's subviews
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let maskImage = createMaskingImage(size: self.view.bounds.size) {
let maskView = UIView(frame: self.view.bounds)
maskView.layer.contents = maskImage
self.view.mask = maskView
}
}
}
// create a masking image for a view of the given size
func createMaskingImage(size: CGSize) -> UIImage? {
let drawingBounds = CGRect(origin: CGPoint.zero, size: size)
UIGraphicsBeginImageContext(size)
// We're going to jump down to the level of cgContext for scaling
// You might be able to do this from the level of UIGraphics, but I don't know how so...
// Implicitly unwrapped optional, but if we can't get a CGContext we're in trouble
let cgContext = UIGraphicsGetCurrentContext()!
let maskingPath = createMaskingPath()
let pathBounds = maskingPath.bounds;
cgContext.saveGState()
// Clearing the image may not strictly be necessary
cgContext.clear(drawingBounds)
// Scale the context so that when we draw the path it fits in the drawing bounds
// Could just use "size" here instead of drawingBounds.size, but I think this makes it a
// little more explicit that we're matching up two rects
cgContext.scaleBy(x: drawingBounds.size.width / pathBounds.size.width,
y: drawingBounds.size.height / pathBounds.size.height)
cgContext.setFillColor(UIColor.lightGray.cgColor)
cgContext.addPath(maskingPath.cgPath)
cgContext.fillPath(using: .evenOdd)
cgContext.restoreGState()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
func createMaskingPath() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0.05, y: 0))
path.addCurve(to: CGPoint(x: 162.02, y: 3.8), controlPoint1: CGPoint(x: 0.05, y: 2.1), controlPoint2: CGPoint(x: 72.57, y: 3.8))
path.addCurve(to: CGPoint(x: 324, y: 0), controlPoint1: CGPoint(x: 251.48, y: 3.8), controlPoint2: CGPoint(x: 324, y: 2.1))
path.addLine(to: CGPoint(x: 324, y: 150.2))
path.addCurve(to: CGPoint(x: 162.02, y: 154), controlPoint1: CGPoint(x: 324, y: 152.3), controlPoint2: CGPoint(x: 251.48, y: 154))
path.addCurve(to: CGPoint(x: 0.05, y: 150.2), controlPoint1: CGPoint(x: 72.57, y: 154), controlPoint2: CGPoint(x: 0.05, y: 152.3))
path.addCurve(to: CGPoint(x: 0, y: 0.17), controlPoint1: CGPoint(x: 0.05, y: 148.1), controlPoint2: CGPoint(x: 0, y: 0.17))
return path
}
/*
This is a UICollectionView, which clips normally on the left and right,
but allows some extra space horizontally.
A typical example is you need to clip the scrolling items but you
still need to allow shadows.
*/
import Foundation
import UIKit
class CustomClipCollectionView: UICollectionView {
private lazy var extraSpaceOnBaseButStillClipSidesNormally: CALayer = {
let l = CALayer()
l.backgroundColor = UIColor.black.cgColor
return l
}()
override func layoutSubviews() {
extraSpaceOnBaseButStillClipSidesNormally.frame = bounds.insetBy(
dx: 0, dy: -10)
layer.mask = extraSpaceOnBaseButStillClipSidesNormally
super.layoutSubviews()
}
}

drawRect doesn't draws the right shape

I have a UIView subclass called TestView with an overriding of DrawRect like that:
import Foundation
import UIKit
class TestView: UIView {
override func drawRect(rect: CGRect) {
let rectangle5Color = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000)
let rectangle5StrokeColor = UIColor(red: 1.000, green: 1.000, blue: 1.000, alpha: 1.000)
let rectangle5Path = UIBezierPath(ovalInRect: rect)
rectangle5Path.moveToPoint(CGPoint(x: 758, y: 1467))
rectangle5Path.addLineToPoint(CGPoint(x: 748, y: 1467))
rectangle5Path.addLineToPoint(CGPoint(x: 204, y: 1467))
rectangle5Path.addLineToPoint(CGPoint(x: 204, y: 1205))
rectangle5Path.addCurveToPoint(CGPoint(x: 266, y: 1205), controlPoint1: CGPoint(x: 204, y: 1205), controlPoint2: CGPoint(x: 248.33, y: 1205))
rectangle5Path.addCurveToPoint(CGPoint(x: 754, y: 1135), controlPoint1: CGPoint(x: 411.79, y: 1205), controlPoint2: CGPoint(x: 627.68, y: 1135))
rectangle5Path.addLineToPoint(CGPoint(x: 758, y: 1135))
rectangle5Path.addCurveToPoint(CGPoint(x: 1232, y: 1205), controlPoint1: CGPoint(x: 884.32, y: 1135), controlPoint2: CGPoint(x: 1086.21, y: 1205))
rectangle5Path.addCurveToPoint(CGPoint(x: 1296, y: 1205), controlPoint1: CGPoint(x: 1233.67, y: 1205), controlPoint2: CGPoint(x: 1296, y: 1205))
rectangle5Path.addLineToPoint(CGPoint(x: 1296, y: 1467))
rectangle5Path.addLineToPoint(CGPoint(x: 758, y: 1467))
rectangle5Path.closePath()
rectangle5Path.moveToPoint(CGPoint(x: 752.5, y: 1009))
rectangle5Path.addCurveToPoint(CGPoint(x: 867, y: 1122.5), controlPoint1: CGPoint(x: 815.74, y: 1009), controlPoint2: CGPoint(x: 867, y: 1059.82))
rectangle5Path.addCurveToPoint(CGPoint(x: 752.5, y: 1236), controlPoint1: CGPoint(x: 867, y: 1185.18), controlPoint2: CGPoint(x: 815.74, y: 1236))
rectangle5Path.addCurveToPoint(CGPoint(x: 638, y: 1122.5), controlPoint1: CGPoint(x: 689.26, y: 1236), controlPoint2: CGPoint(x: 638, y: 1185.18))
rectangle5Path.addCurveToPoint(CGPoint(x: 752.5, y: 1009), controlPoint1: CGPoint(x: 638, y: 1059.82), controlPoint2: CGPoint(x: 689.26, y: 1009))
rectangle5Path.closePath()
rectangle5Color.setFill()
rectangle5Path.fill()
rectangle5StrokeColor.setStroke()
rectangle5Path.lineWidth = 5
rectangle5Path.stroke()
}
}
On my ViewController I'm adding this view as a subclass to the view like that:
let testView = TestView(frame: CGRectMake(0,0, 100, 100))
self.view.addSubview(testView)
but the only thing it draws it a white circle instead of the shape it should draw.
What am I doing wrong here?
You're doing UIBezierPath(ovalInRect: rect), with a rect of 100 x 100. So I'd expect a circle.
If you don't want to draw the circle, initialize the path with UIBezierPath() instead.
In terms of why you didn't see anything else, your paths are well outside the 100 x 100 size, so I'm not sure what you expected it to render. You should adjust those coordinates to fall within the size of the TestView if you want it to render this path within the view.

Resources