Search code examples
swiftcore-graphics

How to make a dashed or dotted line in Swift 4


I've been trying to do this in a playground like this:

import UIKit
import XCPlayground

let path = UIBezierPath()
path.move(to: CGPoint(x:10,y:10))
path.addLine(to: CGPoint(x:290,y:10))
path.lineWidth = 2

let dashPattern : [CGFloat] = [0, 16] 
path.setLineDash(dashPattern, count: 2, phase: 0)
path.lineCapStyle = CGLineCap.round
path.lineCapStyle = .butt
UIGraphicsBeginImageContextWithOptions(CGSize(width:300, height:20), false, 2)
path.stroke()

XCPlaygroundPage.currentPage.captureValue(value: UIGraphicsGetImageFromCurrentImageContext(), withIdentifier: "image")
UIGraphicsEndImageContext()

But the result is:

enter image description here


Solution

  • 1) A dash pattern of [0, 16] doesn't make sense in my opinion. Both values should be greater than 0.

    2) Aside from that, your code is correct, but the playground preview for the UIBezierPath in Xcode ignores the dash pattern (just like it ignores colors and many other settings — it just displays the path in an abstract way).

    If you render the path into an image, the dash pattern becomes visible. Here's the code I used (I changed the dash pattern array to [16,16]):

    import UIKit
    import XCPlayground
    
    let path = UIBezierPath()
    path.move(to: CGPoint(x:10,y:10))
    path.addLine(to: CGPoint(x:290,y:10))
    path.lineWidth = 2
    
    let dashPattern : [CGFloat] = [16, 16]
    path.setLineDash(dashPattern, count: 2, phase: 0)
    path.lineCapStyle = CGLineCap.round
    path.lineCapStyle = .butt
    
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 300, height: 20))
    let image = renderer.image { context in
        path.stroke()
    }
    // image now contains an image of the path