I am fairly new to swift and Xcode and I am trying to make a tic tac toe game. I have everything figured out except how to draw a line through the three x's or o's. I have no idea on how to draw lines. I have looked on the web for the answer and can't figure it out.
-
6What research have you done on it? Which parts didn't you understand? – Wain Jul 22 '15 at 16:41
-
i don't know where to put the code. – Volkodav Jul 22 '15 at 16:50
-
For Swift 3 you may check [this article](http://stackoverflow.com/questions/38042933/swift-3-drawing-a-rectangle). – coarist Nov 24 '16 at 16:12
-
For Swift 3 please check [here](http://stackoverflow.com/questions/38042933/swift-3-drawing-a-rectangle). – coarist Nov 24 '16 at 16:55
-
Check this post. https://stackoverflow.com/a/50346827/1890317 – uplearned.com Dec 21 '18 at 09:15
11 Answers
Try looking into UIBezierPath, it will help you a lot for drawing lines. Here is documentation. Here is an example:
override func drawRect(rect: CGRect) {
let aPath = UIBezierPath()
aPath.move(to: CGPoint(x:<#start x#>, y:<#start y#>))
aPath.addLine(to: CGPoint(x: <#end x#>, y: <#end y#>))
// Keep using the method addLine until you get to the one where about to close the path
aPath.close()
// If you want to stroke it with a red color
UIColor.red.set()
aPath.lineWidth = <#line width#>
aPath.stroke()
}
Make sure you put this code in the drawRect
, like in the example above.
If you need to update the drawing just call setNeedsDisplay()
to update.

- 382
- 2
- 13

- 2,107
- 17
- 20
-
1i think this is the kind i was looking for but it doesn't show up the line is not showing up – Volkodav Jul 22 '15 at 17:04
-
it gives me an error that says "method does not override any method from its superclass" it is on the first line which is "override fun drawRect(rect: CGRect) {" – Volkodav Jul 22 '15 at 17:13
-
-
here is how i start the class "class TicTacToeViewController: UIViewController {" but this is a second viewControler not the default one i created this one to control a second viewControler – Volkodav Jul 22 '15 at 17:18
-
Sorry about that you probably have to create a custom UIView in the storyboard create a new file for it then implement this code in that new file – Epic Defeater Jul 22 '15 at 17:18
-
Because UIViewController doesn't have a function named drawRect there is nothing to override – Epic Defeater Jul 22 '15 at 17:20
-
By the way, make sure the new class you create is a subclass of UIView, not UIViewController – Epic Defeater Jul 22 '15 at 17:21
-
ok i put the view over top of my grid where the game is played and created a new file thats a uiview class and i put the code above in it and i did add the number to it but its not showing up – Volkodav Jul 22 '15 at 17:25
-
-
Make sure you clicked on the UIView and went to the identity inspector and added the custom class to it or else it won't work – Epic Defeater Jul 22 '15 at 17:28
-
ok so it draws the line but it set the view to black color and now i can't see the game board – Volkodav Jul 22 '15 at 17:29
-
Sorry again make sure you add aPath.lineWidth = 3 in the drawRect – Epic Defeater Jul 22 '15 at 17:29
-
-
If you want you can also remove aPath.closePath() from the drawRect – Epic Defeater Jul 22 '15 at 17:32
-
-
-
-
-
no just the view that i just added it is black with a line in it but i can't see the game board which is behind the view – Volkodav Jul 22 '15 at 17:37
-
Is it possible to move the gameBoard code into the new file that you made – Epic Defeater Jul 22 '15 at 17:37
-
-
ye thank you and i figured out how to get rid of the black background. you just unselect the opaque. – Volkodav Jul 22 '15 at 17:42
-
Thank you for wonderful code. It works can you please let me know how to increase the thickness of line. – Jeet Mar 20 '17 at 11:24
-
Update for Swift 3.x using Epic Defeater's example
override func draw(_ rect: CGRect) {
let aPath = UIBezierPath()
aPath.move(to: CGPoint(x:20, y:50))
aPath.addLine(to: CGPoint(x:300, y:50))
//Keep using the method addLineToPoint until you get to the one where about to close the path
aPath.close()
//If you want to stroke it with a red color
UIColor.red.set()
aPath.stroke()
//If you want to fill it as well
aPath.fill()
}

- 1,230
- 13
- 21
The questioner isn't really asking what code to use, he is asking where to put the code. It's actually a good question because if you put any of the graphics code in the 'wrong' place, nothing at all will be drawn. The 'wrong' place to put the code is in a class that is not a subclass of UIView. If you try doing that, the code will compile but when it runs, the call to get the graphics context will fail and the calls to the following graphics functions, such as context?.move(), will not run because the context is nil.
As an example, let's create a storyboard with a View, a Button and a Label by dragging the respective objects from the Object Library onto the storyboard. My example looks like this, where the white square is the View (actually a sub-view because the main screen is also a view):
It's possible to draw graphics on Button and Label controls (and the other types of UI controls) because UIButton and UILabel are subclasses of UIView.
I also created a new file in the project, of type Swift, and called it ExampleDraw.swift and put the following code in it. The code contains three classes to write graphics on the view, button and label. Each class overrides the draw() function in the base UIView class:
import UIKit
class DrawOnView: UIView {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setLineWidth(2.0)
context?.setStrokeColor(UIColor.blue.cgColor)
context?.move(to: CGPoint(x:0, y: 0))
context?.addLine(to: CGPoint(x: 20, y: 30))
context?.strokePath()
print("in DrawOnView")
}
}
class DrawOnButton: UIButton {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setLineWidth(4.0)
context?.setStrokeColor(UIColor.green.cgColor)
context?.move (to: CGPoint(x: 0, y: 0))
context?.addLine (to: CGPoint(x: 40, y: 45))
context?.strokePath()
print("in DrawOnButton")
}
}
class DrawOnLabel: UILabel {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setLineWidth(1.0)
context?.setStrokeColor(UIColor.red.cgColor)
context?.move (to: CGPoint(x: 0, y: 0))
context?.addLine (to: CGPoint(x: 35, y: 45))
context?.strokePath()
print("in DrawOnLabel")
}
}
Then in the main storyboard, select the view, like this:
Then open the Identity Inspector and associate this view with the custom class (i.e. the first class in ExampleDraw.swift) called DrawOnView() like this:
Do the same for the Button and the Label, like this:
Then run the project in the simulator and hopefully the graphics will write on the view, button and label like this:

- 2,637
- 1
- 21
- 15
Swift 3.1, inside a UIView:
public override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context!.setLineWidth(2.0)
context!.setStrokeColor(UIColor.red.cgColor)
context?.move(to: CGPoint(x: 0, y: self.frame.size.height))
context?.addLine(to: CGPoint(x: self.frame.size.width, y: 0))
context!.strokePath()
}
If you want to add a line to a UIViewController, just add a UIView with this function as a subview to the UIViewController, ei:
let line = LineView(CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
self.view.addSubview(line)

- 889
- 9
- 7
I've been struggling on this topic too. In XCode 7.3.1, with Swift version 2.2, the simplest way to draw a line is to create a playground and insert this code in it. Hope this helps other people with this simple task in mind.
import UIKit
import XCPlayground
public class SimpleLine: UIView {
public init() {
super.init(frame: CGRect(x: 0, y: 0, width: 480, height: 320))
backgroundColor = UIColor.whiteColor()
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
CGContextSetLineWidth(context, 4.0)
CGContextSetStrokeColorWithColor(context, UIColor.darkGrayColor().CGColor)
CGContextMoveToPoint(context, 100, 100)
CGContextAddLineToPoint(context, 300, 300)
CGContextStrokePath(context)
}
}
let firstLine = SimpleLine()
XCPlaygroundPage.currentPage.liveView = firstLine
Edit: Update for Xcode 10.1 with Swift version 4.2.1
import UIKit
import PlaygroundSupport
public class SimpleLine: UIView {
public init() {
super.init(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
backgroundColor = .white
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.setLineWidth(4.0)
context.setStrokeColor(UIColor.darkGray.cgColor)
context.move(to: CGPoint(x: 40, y: 40))
context.addLine(to: CGPoint(x: 280, y: 300))
context.strokePath()
}
}
PlaygroundPage.current.liveView = SimpleLine()

- 1,816
- 24
- 32
Simple SWIFT 4.1 Implementation:
public override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
let lineWidth: CGFloat = 1.0
context.setLineWidth(lineWidth)
context.setStrokeColor(UIColor(style: .tertiaryBackground).cgColor)
let startingPoint = CGPoint(x: 0, y: rect.size.height - lineWidth)
let endingPoint = CGPoint(x: rect.size.width, y: rect.size.height - lineWidth)
context.move(to: startingPoint )
context.addLine(to: endingPoint )
context.strokePath()
}
Obviously, you need to adjust the starting and ending point.

- 9,217
- 2
- 29
- 41
Are you using SpriteKit? If not, you really should do for any kind of iOS games as it makes manipulating and adding sprites (images) and other game-style objects very easy.
Although not at all the best way in terms of coding best-practices, a very simple way to accomplish this would be to create a new view when someone wins, check which direction (out of the possible 8) the row is and then set the image of this view accordingly. The images would be semi-transparent (e.g. PNGs) squares each containing a different possible line.
If you want to do it the proper way research how to draw paths in SpriteKit between coordinates.
Hope this is of some help! Steve

- 537
- 1
- 7
- 17
In general, you have to draw a path in Core Graphics. You can follow this example:
let context = UIGraphicsGetCurrentContext()
CGContextSetLineWidth(context, 2.0)
CGContextSetStrokeColorWithColor(context, color)
CGContextMoveToPoint(context, startPoint)
CGContextAddLineToPoint(context, endPoint)
CGContextStrokePath(context)

- 947
- 1
- 9
- 27
-
i have seen this example many times but i didn't get where to put that code. – Volkodav Jul 22 '15 at 16:50
-
Drawing in Swift 4.1
override func viewDidLoad() {
super.viewDidLoad()
self.lastPoint = CGPoint.zero
self.red = 0.0
self.green = 0.0
self.blue = 0.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Touch events
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
isSwiping = false
if let touch = touches.first{
lastPoint = touch.location(in: mainImageView)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
isSwiping = true;
if let touch = touches.first{
let currentPoint = touch.location(in: mainImageView)
UIGraphicsBeginImageContext(self.tempImageView.frame.size)
self.tempImageView.image?.draw(in: CGRect(x:0, y:0,width:self.tempImageView.frame.size.width, height:self.tempImageView.frame.size.height))
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: currentPoint.x, y: currentPoint.y))
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(9.0)
UIGraphicsGetCurrentContext()?.setStrokeColor(red: red, green: green, blue: blue, alpha: 1.0)
UIGraphicsGetCurrentContext()?.strokePath()
self.tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
lastPoint = currentPoint
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if(!isSwiping) {
// This is a single touch, draw a point
UIGraphicsBeginImageContext(self.tempImageView.frame.size)
self.tempImageView.image?.draw(in: CGRect(x:0, y:0,width:self.tempImageView.frame.size.width, height:self.tempImageView.frame.size.height))
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(9.0)
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.setStrokeColor(red: red, green: green, blue: blue, alpha: 1.0)
UIGraphicsGetCurrentContext()?.strokePath()
self.tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}

- 797
- 9
- 9
Quick and dirty fix in Storyboard:
- Create a UIView
- Set the background color to the color you want
- Set height constraint to the line width you want

- 203
- 3
- 5
-
although the question is about drawing a line for the tic tac toe, thus the line should be more like a slash \ – Mia Jan 26 '22 at 01:42
-
1Weird that you went for UILabel while you could've done the same with just a UIVIew which is a more basic class in UIKit. – rule_it_subir Feb 03 '22 at 08:16
-
import UIKit
@IBDesignable class DrawView: UIView {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setLineWidth(2.0)
context?.setStrokeColor(UIColor.red.cgColor)
context?.move(to: CGPoint(x: 210, y: 30))
context?.addLine(to: CGPoint(x: 300, y: 200))
context?.addLine(to: CGPoint(x: 100, y: 200))
context?.addLine(to: CGPoint(x: 210, y: 30))
context?.strokePath()
}
}

- 21,776
- 12
- 51
- 66

- 11
- 1