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
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.
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()
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()
}
}
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: