read
There is a common pitfall with using Core Graphics API to draw.
It is to do with the retina devices, which has more pixels packed in 1 point.
Take this example of drawing a round rect:
// Draw a 1 pt border line with radius 5 in the rect
let rect = CGRect(x: 0, y: 0, width: 200, height: 100)
let borderWidth: CGFloat = 1
let radius: CGFloat = 5
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
// Note: Because stroke will overflow, we need to make the actual round rect smaller
// http://stackoverflow.com/a/11176658/242682
let roundRect = CGRectMake(borderWidth/2, borderWidth/2, (rect.width - borderWidth), (rect.height - borderWidth))
// Fill and stroke
let path = UIBezierPath(roundedRect: roundRect, cornerRadius: radius)
UIColor.whiteColor().setFill()
path.fill()
UIColor.redColor().setStroke()
path.lineWidth = borderWidth
path.stroke()
// Draw it
CGContextAddPath(context, path.CGPath);
// Get the final image from context
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
When the image is shown on a retina device (@2x or @3x), the 1pt line border will be blurry.
The solution is simple:
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
Use UIGraphicsBeginImageContextWithOptions
API instead of the old UIGraphicsBeginImageContext
.
The third parameter passed in is the scale. Passing in 0.0
will use the device scale automatically.
Remember: Drawing is always specified in points, but when you “begin image context”, you have to use UIGraphicsBeginImageContextWithOptions
to specific the correct scale.