Drawing a grid on a UIView in Swift

Viewed 8745

I am very new to Swift. Am trying to draw a grid (like a graph page) on a UIView in Swift. The code is running but I don't see any lines. I don't see what I did wrong.

In the Storyboard I added a View onto the ViewController.

In code I created a GridView.swift and added it to the View above. Here is the code for GridView class. The function draw is being called and the code running without any errors. Its just doing what I thought it would do.

Its not even drawing one line (I remove the for loop and just try to draw one line). This seems so basic that it should work.

import Foundation
import UIKit

class GridView: UIView 
{
    fileprivate var gridWidthMultiple: CGFloat
    {
        return 10
    }
    fileprivate var gridHeightMultiple : CGFloat
    {
        return 20
    }

    fileprivate var gridWidth: CGFloat
    {   
        return bounds.width/CGFloat(gridWidthMultiple)
    }

    fileprivate var gridHeight: CGFloat
    {
        return bounds.height/CGFloat(gridHeightMultiple)
    }

    fileprivate var gridCenter: CGPoint {
        return CGPoint(x: bounds.midX, y: bounds.midY)
    }

    fileprivate func drawGrid()
    {
        let path = UIBezierPath()
        path.lineWidth = 5.0

        for index in 1...Int(gridWidthMultiple) - 1
        {
            let start = CGPoint(x: CGFloat(index) * gridWidth, y: 0)
            let end = CGPoint(x: CGFloat(index) * gridWidth, y:bounds.height)
            path.move(to: start)
            path.addLine(to: end)
        }
    }

    override func draw(_ rect: CGRect)
    {
        drawGrid()
    }
}
3 Answers

Just Copy and paste the below code and you will be good to go. I haven't check your logic of drawing correct grid i have just solved the not drawing issue. If it draw wrong grid then i will re-check your grid logic for now it just help you to draw something using UIBezierPath

class GridView: UIView
{
    private var path = UIBezierPath()
    fileprivate var gridWidthMultiple: CGFloat
    {
        return 10
    }
    fileprivate var gridHeightMultiple : CGFloat
    {
        return 20
    }

    fileprivate var gridWidth: CGFloat
    {
        return bounds.width/CGFloat(gridWidthMultiple)
    }

    fileprivate var gridHeight: CGFloat
    {
        return bounds.height/CGFloat(gridHeightMultiple)
    }

    fileprivate var gridCenter: CGPoint {
        return CGPoint(x: bounds.midX, y: bounds.midY)
    }

    fileprivate func drawGrid()
    {
        path = UIBezierPath()
        path.lineWidth = 5.0

        for index in 1...Int(gridWidthMultiple) - 1
        {
            let start = CGPoint(x: CGFloat(index) * gridWidth, y: 0)
            let end = CGPoint(x: CGFloat(index) * gridWidth, y:bounds.height)
            path.move(to: start)
            path.addLine(to: end)
        }

        for index in 1...Int(gridHeightMultiple) - 1 {
            let start = CGPoint(x: 0, y: CGFloat(index) * gridHeight)
            let end = CGPoint(x: bounds.width, y: CGFloat(index) * gridHeight)
            path.move(to: start)
            path.addLine(to: end)
        }

        //Close the path.
        path.close()

    }

    override func draw(_ rect: CGRect)
    {
        drawGrid()

        // Specify a border (stroke) color.
        UIColor.purple.setStroke()
        path.stroke()
    }
}

if you want make the draw logic when view is initialise but you actually want to draw the lines later i.e. when some special event occur. Bellow class have two methods drawGridWithStoreColor and removeGrid this will help you to draw grid when ever you want and remove grid when ever you want.

class GridView: UIView
{
    private var path = UIBezierPath()
    var gridLayer: CAShapeLayer?

    fileprivate var gridWidthMultiple: CGFloat
    {
        return 10
    }
    fileprivate var gridHeightMultiple : CGFloat
    {
        return 20
    }

    fileprivate var gridWidth: CGFloat
    {
        return bounds.width/CGFloat(gridWidthMultiple)
    }

    fileprivate var gridHeight: CGFloat
    {
        return bounds.height/CGFloat(gridHeightMultiple)
    }

    fileprivate var gridCenter: CGPoint {
        return CGPoint(x: bounds.midX, y: bounds.midY)
    }

    fileprivate func drawGrid()
    {
        path = UIBezierPath()
        path.lineWidth = 5.0

        for index in 1...Int(gridWidthMultiple) - 1
        {
            let start = CGPoint(x: CGFloat(index) * gridWidth, y: 0)
            let end = CGPoint(x: CGFloat(index) * gridWidth, y:bounds.height)
            path.move(to: start)
            path.addLine(to: end)
        }


    }

    //Call this method with your stroke color when you want to draw this grid
    func drawGridWithColor(borderColor: UIColor) {
        //Close the path.
        path.close()
        if gridLayer == nil {
            gridLayer = CAShapeLayer()
            gridLayer?.lineWidth = 5.0;
            gridLayer?.path = path.cgPath
            gridLayer?.strokeColor = borderColor.cgColor

            self.layer.addSublayer(gridLayer!)
            //Above line will add this grid at the very top of this view.



            // if you want to add this grid below some layer/object you can use method
            //self.layer.insertSublayer(gridLayer, at: 0)
            //Give the index number to this method so that it can place this grid at the index

        }else {
            gridLayer?.strokeColor = borderColor.cgColor
        }
    }

    func removeGrid() {
        guard let gLayer = gridLayer else {return}
        gLayer.removeFromSuperlayer()
    }

    override func draw(_ rect: CGRect)
    {
        drawGrid()
    }
}

This one works like Instagram's create mode text alignment grids. Add below two functions in viewDidLoad()...

func addVerticalGrid(){
    
    let Path = UIBezierPath()
    Path.move(to: CGPoint(x: view.bounds.midX, y: 0))
    Path.addLine(to: CGPoint(x: view.bounds.midX, y: view.frame.height))
    Path.close()
    
    let shapeLayer1 = CAShapeLayer()
    shapeLayer1.path = Path.cgPath
    shapeLayer1.strokeColor = UIColor.red.cgColor
    view.layer.addSublayer(shapeLayer1)
}

func addHorizontalGrid(){
    
    let Path = UIBezierPath()
    Path.move(to: CGPoint(x: 0, y: view.bounds.midY))
    Path.addLine(to: CGPoint(x: view.frame.width, y: view.bounds.midY))
    Path.close()
    
    let shapeLayer2 = CAShapeLayer()
    shapeLayer2.path = Path.cgPath
    shapeLayer2.strokeColor = UIColor.red.cgColor
    view.layer.addSublayer(shapeLayer2)
}
Related