How do I Create my own Progressbar in swift? [closed] - swift

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I to create my own custom progressbar ie:NSProgressIndicator using swift how do I do that?

You can just make your own progress indicator, e.g.:
#IBDesignable
open class ColorfulProgressIndicator: NSView {
#IBInspectable open var doubleValue: Double = 50 { didSet { needsLayout = true } }
#IBInspectable open var minValue: Double = 0 { didSet { needsLayout = true } }
#IBInspectable open var maxValue: Double = 100 { didSet { needsLayout = true } }
#IBInspectable open var backgroundColor: NSColor = .lightGray { didSet { layer?.backgroundColor = backgroundColor.cgColor } }
#IBInspectable open var progressColor: NSColor = .blue { didSet { progressShapeLayer.fillColor = progressColor.cgColor } }
#IBInspectable open var borderColor: NSColor = .clear { didSet { layer?.borderColor = borderColor.cgColor } }
#IBInspectable open var borderWidth: CGFloat = 0 { didSet { layer?.borderWidth = borderWidth } }
#IBInspectable open var cornerRadius: CGFloat = 0 { didSet { layer?.cornerRadius = cornerRadius } }
private lazy var progressShapeLayer: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = progressColor.cgColor
return shapeLayer
}()
public override init(frame: NSRect = .zero) {
super.init(frame: frame)
configure()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
configure()
}
// needed because IB doesn't don't honor `wantsLayer`
open override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer = CALayer()
configure()
}
open override func layout() {
super.layout()
updateProgress()
}
open func animate(to doubleValue: Double? = nil, minValue: Double? = nil, maxValue: Double? = nil, duration: TimeInterval = 0.25) {
let currentPath = progressShapeLayer.presentation()?.path ?? progressShapeLayer.path
// stop prior animation, if any
progressShapeLayer.removeAnimation(forKey: "updatePath")
// update progress properties
if let doubleValue = doubleValue { self.doubleValue = doubleValue }
if let minValue = minValue { self.minValue = minValue }
if let maxValue = maxValue { self.maxValue = maxValue }
// create new animation
let animation = CABasicAnimation(keyPath: "path")
animation.duration = duration
animation.fromValue = currentPath
animation.toValue = progressPath
progressShapeLayer.add(animation, forKey: "updatePath")
}
}
private extension ColorfulProgressIndicator {
func configure() {
wantsLayer = true
layer?.cornerRadius = cornerRadius
layer?.backgroundColor = backgroundColor.cgColor
layer?.borderWidth = borderWidth
layer?.borderColor = borderColor.cgColor
layer?.addSublayer(progressShapeLayer)
}
func updateProgress() {
progressShapeLayer.path = progressPath
}
var progressPath: CGPath? {
guard minValue != maxValue else { return nil }
let percent = max(0, min(1, CGFloat((doubleValue - minValue) / (maxValue - minValue))))
let rect = NSRect(origin: bounds.origin, size: CGSize(width: bounds.width * percent, height: bounds.height))
return CGPath(rect: rect, transform: nil)
}
}
You can either just set its doubleValue, minValue and maxValue, or if you want to animate the change, just:
progressIndicator.animate(to: 75)
For example, below I set the progressColor and borderColor to .red, set the borderWidth to 1, set the cornerRadius to 10. I then started animating to 75, and then, before it’s even done, triggered another animation to 100 (to illustrate that animations can pick up from wherever it left off):
There are tons of ways of implementing this (so get too lost in the details of the implementation, above), but it illustrates that creating our own progress indicators is pretty easy.

You can subclass it just like any other view. But for all you're doing that is likely unnecessary.
class CustomIndicator: NSProgressIndicator {
// ...
}
As far as setting the height goes, you can do this by initializing the view with a custom frame.
let indicator = NSProgressIndicator(frame: NSRect(x: 0, y: 0, width: 100, height: 20))
There is a property called controlTint that you can set on NSProgressIndicator, but this only allows you to set the color to the predefined ones under NSControlTint. For truly custom colors, I'd recommend this route using Quartz filters via the Interface Builder.

Related

Swift: Make the outline of a UIView sketch-like

I want to make the outlines of a UIView look "wavey" like someone drew them.
I have this example from PowerPoint, which allows to do it (should work with any size and corner radius):
Currently this is what I have:
myView.layer.borderWidth = 10
myView.layer.borderColor = UIColor.blue.cgColor
myView.layer.cornerRadius = 5 // Optional
Thank
You can create "wavy" lines by using a UIBezierPath with a combination of quad-curves, lines, arcs, etc.
We'll start with a simple line, one-quarter of the width of the view:
Our path would consist of:
move to 0,0
add line to 80,0
If we change that to a quad-curve:
Now we're doing:
move to 0,0
add quad-curve to 80,0 with control point 40,40
If we add another quad-curve going the other way:
Now we're doing:
move to 0,0
add quad-curve to 80,0 with control point 40,40
add quad-curve to 160,0 with control point 120,-40
and we can extend that the width of the view:
of course, that doesn't look like your "sketch" target, so let's change the control-point offsets from 40 to 2:
Now it looks a bit more like a hand-draw "sketched" line.
It's too uniform, though, and it's partially outside the bounds of the view, so let's inset it by 8-pts and, instead of four 25% segments, we'll use (for example) five segments of these widths:
0.15, 0.2, 0.2, 0.27, 0.18
If we take the same approach to go down the right-hand side, back across the bottom, and up the left-hand side, we can get this:
Here's some example code to produce that view:
class SketchBorderView: UIView {
let borderLayer: CAShapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = UIColor.blue.cgColor
layer.addSublayer(borderLayer)
backgroundColor = .yellow
}
override func layoutSubviews() {
let incrementVals: [CGFloat] = [
0.15, 0.2, 0.2, 0.27, 0.18,
]
let lineOffsets: [[CGFloat]] = [
[ 1.0, -2.0],
[-1.0, 2.0],
[-1.0, -2.0],
[ 1.0, 2.0],
[ 0.0, -2.0],
]
let pth: UIBezierPath = UIBezierPath()
// inset bounds by 8-pts so we can draw the "wavy border"
// inside our bounds
let r: CGRect = bounds.insetBy(dx: 8.0, dy: 8.0)
var ptDest: CGPoint = .zero
var ptControl: CGPoint = .zero
// start at top-left
ptDest = r.origin
pth.move(to: ptDest)
// we're at top-left
for i in 0..<incrementVals.count {
ptDest.x += r.width * incrementVals[i]
ptDest.y = r.minY + lineOffsets[i][0]
ptControl.x = pth.currentPoint.x + ((ptDest.x - pth.currentPoint.x) * 0.5)
ptControl.y = r.minY + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
// now we're at top-right
for i in 0..<incrementVals.count {
ptDest.y += r.height * incrementVals[i]
ptDest.x = r.maxX + lineOffsets[i][0]
ptControl.y = pth.currentPoint.y + ((ptDest.y - pth.currentPoint.y) * 0.5)
ptControl.x = r.maxX + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
// now we're at bottom-right
for i in 0..<incrementVals.count {
ptDest.x -= r.width * incrementVals[i]
ptDest.y = r.maxY + lineOffsets[i][0]
ptControl.x = pth.currentPoint.x - ((pth.currentPoint.x - ptDest.x) * 0.5)
ptControl.y = r.maxY + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
// now we're at bottom-left
for i in 0..<incrementVals.count {
ptDest.y -= r.height * incrementVals[i]
ptDest.x = r.minX + lineOffsets[i][0]
ptControl.y = pth.currentPoint.y - ((pth.currentPoint.y - ptDest.y) * 0.5)
ptControl.x = r.minX + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
borderLayer.path = pth.cgPath
}
}
and an example controller:
class SketchTestVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = SketchBorderView()
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
v.centerXAnchor.constraint(equalTo: g.centerXAnchor),
v.centerYAnchor.constraint(equalTo: g.centerYAnchor),
v.widthAnchor.constraint(equalToConstant: 320.0),
v.heightAnchor.constraint(equalTo: v.widthAnchor),
])
}
}
Using that code, though, we still have too much uniformity, so in actual use we'd want to randomize the number of segments, the widths of the segments, and the control-point offsets.
Of course, to get your "rounded rect" you'd want to add arcs at the corners.
I expect this should get you on your way though.
use this extension to solve the issue
import Foundation
import UIKit
extension UIView {
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.2
layer.shadowOffset = .zero
layer.shadowRadius = 5
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
#IBInspectable
var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
#IBInspectable
var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set {
layer.borderWidth = newValue
}
}
#IBInspectable
var borderColor: UIColor? {
get {
let color = UIColor.init(cgColor: layer.borderColor!) //UIColor.init(CGColor: layer.borderColor!)
return color
}
set {
layer.borderColor = newValue?.cgColor
}
}
#IBInspectable
var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowRadius = newValue
}
}
#IBInspectable
var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
}
}
#IBInspectable
var shadowOffset: CGSize {
get {
return layer.shadowOffset
}
set {
layer.shadowOffset = newValue
}
}
#IBInspectable
var shadowColor: UIColor? {
get {
if let color = layer.shadowColor {
return UIColor(cgColor: color)
}
return nil
}
set {
if let color = newValue {
layer.shadowColor = color.cgColor
} else {
layer.shadowColor = nil
}
}
}
}
it will look like this

StoryboardUI how to make the label follow the slider

I'm doing a storyboardUI app. One part of the UI design is kind of like this:
I want the label position follows the slider position all the time, like below:
How can I do it?
Assign this class to UISlider.
In this class created one label and change the position according to the slider thumb.
class ThumbTextSlider: UISlider {
private var thumbTextLabel: UILabel = UILabel()
private var thumbFrame: CGRect {
return thumbRect(forBounds: bounds, trackRect: trackRect(forBounds: bounds), value: value)
}
private lazy var thumbView: UIView = {
let thumb = UIView()
return thumb
}()
override func layoutSubviews() {
super.layoutSubviews()
thumbTextLabel.frame = CGRect(x: thumbFrame.origin.x, y: thumbFrame.maxY - 5, width: thumbFrame.size.width, height: 30)
self.setValue()
}
private func setValue() {
thumbTextLabel.text = String(format: "%0.2f", self.value)
}
override func awakeFromNib() {
super.awakeFromNib()
addSubview(thumbTextLabel)
thumbTextLabel.textAlignment = .center
thumbTextLabel.textColor = .blue
thumbTextLabel.layer.zPosition = layer.zPosition + 1
thumbTextLabel.adjustsFontSizeToFitWidth = true
}
}

CAEmitterLayer Stops Displaying

I adapted this code for SwiftUI to display confetti particles, but sometimes the particle emitter does not work. I've noticed that this often happens after sending to background (not killing the app entirely) and reopening it, or simply letting the app sit for a while then trying again.
I've tried using beginTime as other answers have mentioned (on both the emitter and cells), but that fully breaks things. I've also tried toggling various other emitter properties (birthRate, isHidden). It might have to do with the fact that I'm adapting this with UIViewRepresentable. It seems like the emitter layer just disappears, even though the debug console says its still visible.
class ConfettiParticleView: UIView {
var emitter: CAEmitterLayer!
public var colors: [UIColor]!
public var intensity: Float!
private var active: Bool!
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
colors = [UIColor(Color.red),
UIColor(Color.blue),
UIColor(Color.orange),
]
intensity = 0.7
active = false
emitter = CAEmitterLayer()
emitter.emitterPosition = CGPoint(x: UIScreen.main.bounds.width / 2.0, y: 0) // emit from top of view
emitter.emitterShape = .line
emitter.emitterSize = CGSize(width: UIScreen.main.bounds.width, height: 100) // line spans the whole top of view
// emitter.beginTime = CACurrentMediaTime()
var cells = [CAEmitterCell]()
for color in colors {
cells.append(confettiWithColor(color: color))
}
emitter.emitterCells = cells
emitter.allowsGroupOpacity = false
self.layer.addSublayer(emitter)
}
func startConfetti() {
emitter.lifetime = 1
// i've tried toggling other properties here like birthRate, speed
active = true
}
func stopConfetti() {
emitter.lifetime = 0
active = false
}
func confettiWithColor(color: UIColor) -> CAEmitterCell {
let confetti = CAEmitterCell()
confetti.birthRate = 32.0 * intensity
confetti.lifetime = 15.0 * intensity
confetti.lifetimeRange = 0
confetti.name = "confetti"
confetti.color = color.cgColor
confetti.velocity = CGFloat(450.0 * intensity) // orig 450
confetti.velocityRange = CGFloat(80.0 * intensity)
confetti.emissionLongitude = .pi
confetti.emissionRange = .pi / 4
confetti.spin = CGFloat(3.5 * intensity)
confetti.spinRange = 300 * (.pi / 180.0)
confetti.scaleRange = CGFloat(intensity)
confetti.scaleSpeed = CGFloat(-0.1 * intensity)
confetti.contents = #imageLiteral(resourceName: "confetti").cgImage
confetti.beginTime = CACurrentMediaTime()
return confetti
}
func isActive() -> Bool {
return self.active
}
}
view representable
struct ConfettiView: UIViewRepresentable {
#Binding var isStarted: Bool
func makeUIView(context: Context) -> ConfettiParticleView {
return ConfettiParticleView()
}
func updateUIView(_ uiView: ConfettiParticleView, context: Context) {
if isStarted && !uiView.isActive() {
uiView.startConfetti()
print("confetti started")
} else if !isStarted {
uiView.stopConfetti()
print("confetti stopped")
}
}
}
swiftui view for testing
struct ConfettiViewTest: View {
#State var isStarted = false
var body: some View {
ZStack {
ConfettiView(isStarted: $isStarted)
.ignoresSafeArea()
Button(action: {
isStarted = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
isStarted = false
}
}) {
Text("toggle")
.padding()
.background(Color.white)
}
}
}
}

How to make a simple UILabel subclass for marquee/scrolling text effect in swift?

As you can see above i trying to code an simple(!) subclass of UILabel to make an marquee or scrolling text effect if the text of the label is too long. I know that there are already good classes out there (e.g https://cocoapods.org/pods/MarqueeLabel), but i want to make my own :)
Down below you can see my current class.
I can't also fix an issue where the new label(s) are scrolling right, but there is also a third label which shouldn't be there. I think it's the label itself. But when i try the replace the first additional label with that label i won't work. I hope it's not too confusing :/
It's important to me that i only have to assign the class in the storyboard to the label. So that there is no need go and add code e.g in an view controller (beside the outlets). I hope it's clear what i want :D
So again:
Simple subclass of UILabel
scrolling label
should work without any additional code in other classes (except of outlets to change the labels text for example,...)
(it's my first own subclass, so feel free to teach me how to do it right :) )
Thank you very much !
It's by far not perfect, but this is my current class:
import UIKit
class LoopLabel: UILabel {
var labelText : String?
var rect0: CGRect!
var rect1: CGRect!
var labelArray = [UILabel]()
var isStop = false
var timeInterval: TimeInterval!
let leadingBuffer = CGFloat(25.0)
let loopStartDelay = 2.0
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.lineBreakMode = .byClipping
}
override var text: String? {
didSet {
labelText = text
setup()
}
}
func setup() {
let label = UILabel()
label.frame = CGRect.zero
label.text = labelText
timeInterval = TimeInterval((labelText?.characters.count)! / 5)
let sizeOfText = label.sizeThatFits(CGSize.zero)
let textIsTooLong = sizeOfText.width > frame.size.width ? true : false
rect0 = CGRect(x: leadingBuffer, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
rect1 = CGRect(x: rect0.origin.x + rect0.size.width, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
label.frame = rect0
super.clipsToBounds = true
labelArray.append(label)
self.addSubview(label)
self.frame = CGRect(origin: self.frame.origin, size: CGSize(width: 0, height: 0))
if textIsTooLong {
let additionalLabel = UILabel(frame: rect1)
additionalLabel.text = labelText
self.addSubview(additionalLabel)
labelArray.append(additionalLabel)
animateLabelText()
}
}
func animateLabelText() {
if(!isStop) {
let labelAtIndex0 = labelArray[0]
let labelAtIndex1 = labelArray[1]
UIView.animate(withDuration: timeInterval, delay: loopStartDelay, options: [.curveLinear], animations: {
labelAtIndex0.frame = CGRect(x: -self.rect0.size.width,y: 0,width: self.rect0.size.width,height: self.rect0.size.height)
labelAtIndex1.frame = CGRect(x: labelAtIndex0.frame.origin.x + labelAtIndex0.frame.size.width,y: 0,width: labelAtIndex1.frame.size.width,height: labelAtIndex1.frame.size.height)
}, completion: { finishied in
labelAtIndex0.frame = self.rect1
labelAtIndex1.frame = self.rect0
self.labelArray[0] = labelAtIndex1
self.labelArray[1] = labelAtIndex0
self.animateLabelText()
})
} else {
self.layer.removeAllAnimations()
}
}
}
First of, I would keep the variables private if you don't need them to be accessed externally, especially labelText (since you're using the computed property text to be set).
Second, since you're adding labels as subviews, I'd rather use a UIView as container instead of UILabel. The only difference in the storyboard would be to add a View instead of a Label.
Third, if you use this approach, you should not set the frame (of the view) to zero.
Something like that would do:
import UIKit
class LoopLabelView: UIView {
private var labelText : String?
private var rect0: CGRect!
private var rect1: CGRect!
private var labelArray = [UILabel]()
private var isStop = false
private var timeInterval: TimeInterval!
private let leadingBuffer = CGFloat(25.0)
private let loopStartDelay = 2.0
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var text: String? {
didSet {
labelText = text
setup()
}
}
func setup() {
self.backgroundColor = UIColor.yellow
let label = UILabel()
label.text = labelText
label.frame = CGRect.zero
timeInterval = TimeInterval((labelText?.characters.count)! / 5)
let sizeOfText = label.sizeThatFits(CGSize.zero)
let textIsTooLong = sizeOfText.width > frame.size.width ? true : false
rect0 = CGRect(x: leadingBuffer, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
rect1 = CGRect(x: rect0.origin.x + rect0.size.width, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
label.frame = rect0
super.clipsToBounds = true
labelArray.append(label)
self.addSubview(label)
//self.frame = CGRect(origin: self.frame.origin, size: CGSize(width: 0, height: 0))
if textIsTooLong {
let additionalLabel = UILabel(frame: rect1)
additionalLabel.text = labelText
self.addSubview(additionalLabel)
labelArray.append(additionalLabel)
animateLabelText()
}
}
func animateLabelText() {
if(!isStop) {
let labelAtIndex0 = labelArray[0]
let labelAtIndex1 = labelArray[1]
UIView.animate(withDuration: timeInterval, delay: loopStartDelay, options: [.curveLinear], animations: {
labelAtIndex0.frame = CGRect(x: -self.rect0.size.width,y: 0,width: self.rect0.size.width,height: self.rect0.size.height)
labelAtIndex1.frame = CGRect(x: labelAtIndex0.frame.origin.x + labelAtIndex0.frame.size.width,y: 0,width: labelAtIndex1.frame.size.width,height: labelAtIndex1.frame.size.height)
}, completion: { finishied in
labelAtIndex0.frame = self.rect1
labelAtIndex1.frame = self.rect0
self.labelArray[0] = labelAtIndex1
self.labelArray[1] = labelAtIndex0
self.animateLabelText()
})
} else {
self.layer.removeAllAnimations()
}
}
}

How can I add a little white tick to SSRadioButton

The following is my code. I want to add a little white tick to middle when i clicked the button. How can i do that by programming but not using image...
import Foundation
import UIKit
#IBDesignable
class SSRadioButton: UIButton {
private var circleLayer = CAShapeLayer()
private var fillCircleLayer = CAShapeLayer()
override var selected: Bool {
didSet {
toggleButon()
}
}
/**
Color of the radio button circle. Default value is UIColor red.
*/
#IBInspectable var circleColor: UIColor = UIColor.redColor() {
didSet {
circleLayer.strokeColor = circleColor.CGColor
self.toggleButon()
}
}
/**
Radius of RadioButton circle.
*/
#IBInspectable var circleRadius: CGFloat = 5.0
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
private func circleFrame() -> CGRect {
var circleFrame = CGRect(x: 0, y: 0, width: 2*circleRadius, height: 2*circleRadius)
circleFrame.origin.x = 0 + circleLayer.lineWidth
circleFrame.origin.y = bounds.height/2 - circleFrame.height/2
return circleFrame
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
private func initialize() {
circleLayer.frame = bounds
circleLayer.lineWidth = 2
circleLayer.fillColor = UIColor.clearColor().CGColor
circleLayer.strokeColor = circleColor.CGColor
layer.addSublayer(circleLayer)
fillCircleLayer.frame = bounds
fillCircleLayer.lineWidth = 2
fillCircleLayer.fillColor = UIColor.clearColor().CGColor
fillCircleLayer.strokeColor = UIColor.clearColor().CGColor
layer.addSublayer(fillCircleLayer)
self.titleEdgeInsets = UIEdgeInsetsMake(0, (4*circleRadius + 4*circleLayer.lineWidth), 0, 0)
self.toggleButon()
}
/**
Toggles selected state of the button.
*/
func toggleButon() {
if self.selected {
fillCircleLayer.fillColor = circleColor.CGColor
} else {
fillCircleLayer.fillColor = UIColor.clearColor().CGColor
}
}
private func circlePath() -> UIBezierPath {
return UIBezierPath(ovalInRect: circleFrame())
}
private func fillCirclePath() -> UIBezierPath {
return UIBezierPath(ovalInRect: CGRectInset(circleFrame(), 2, 2))
}
override func layoutSubviews() {
super.layoutSubviews()
circleLayer.frame = bounds
circleLayer.path = circlePath().CGPath
fillCircleLayer.frame = bounds
fillCircleLayer.path = fillCirclePath().CGPath
self.titleEdgeInsets = UIEdgeInsetsMake(0, (2*circleRadius + 4*circleLayer.lineWidth), 0, 0)
}
override func prepareForInterfaceBuilder() {
initialize()
}
}
Something like this?
You could do achieve by using UIBezierPath to draw a couple of lines that make a tick. Unless you were looking for something more fancy or curvy? The answer to this question: Draw a line with UIBezierPath
has a nice little function that simplifies the process of drawing the lines.