Last active
May 10, 2016 18:27
-
-
Save stonetip/be654788d94d901960e00167c4781f6b to your computer and use it in GitHub Desktop.
donut builder with timer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import XCPlayground | |
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true | |
// all angles need to be converted to radians | |
func Degrees2Radians(degrees: Double) -> CGFloat{ | |
return CGFloat( degrees * M_PI / 180) | |
} | |
// set width and height that will be used by the view and layers | |
let width = 1000 | |
let height = 1000 | |
let lineWidthScaleFactor = 0.1875 | |
// values that will be used to draw the arc | |
var lineWidth = Double(width) * lineWidthScaleFactor | |
var radius = Double(width) / 2 | |
// tweak values if height is less than width | |
if(width >= height){ | |
lineWidth = Double(height) * lineWidthScaleFactor | |
radius = Double(height) / 2 | |
} | |
// make the arc fit and look pretty | |
radius -= lineWidth / 2 | |
let bounds = CGRect(x: 0, y: 0, width: width, height: height) | |
let view = UIView(frame: bounds) | |
// provide a shape layer and set its path to the arc | |
let shapeLayer = CAShapeLayer() | |
shapeLayer.frame = bounds // need this for the rotation transform to work correctly | |
view.layer.addSublayer(shapeLayer) | |
// define a start and end angle for the test arc | |
var startAngle = Degrees2Radians(0) | |
var endAngle = Degrees2Radians(180) | |
// give the layer some properties | |
shapeLayer.backgroundColor = UIColor.yellowColor().CGColor | |
shapeLayer.fillColor = UIColor.clearColor().CGColor | |
shapeLayer.strokeColor = UIColor.redColor().CGColor | |
shapeLayer.lineWidth = CGFloat(lineWidth) | |
// create the arc | |
shapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: width / 2, y: height / 2), radius: CGFloat(radius), startAngle: startAngle, endAngle: endAngle, clockwise: true).CGPath | |
// Test using a different angle to see if if the donut redraws completely | |
endAngle = Degrees2Radians(45) | |
shapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: width / 2, y: height / 2), radius: CGFloat(radius), startAngle: startAngle, endAngle: endAngle, clockwise: true).CGPath | |
// this gives us a handy way to see the final results | |
view.backgroundColor = UIColor.purpleColor() | |
var testAngle: Double = 0 | |
func drawDonut(){ | |
print("incrementing...") | |
testAngle += 6 | |
endAngle = Degrees2Radians(testAngle) | |
print(testAngle) | |
shapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: width / 2, y: height / 2), radius: CGFloat(radius), startAngle: startAngle, endAngle: endAngle, clockwise: true).CGPath | |
// this gives us a handy way to see the final results | |
view.backgroundColor = UIColor.lightGrayColor() | |
} | |
// Extend NSTimeInterval to provide the conversion functions. | |
extension NSTimeInterval { | |
var nSecMultiplier: Double { | |
return Double(NSEC_PER_SEC) | |
} | |
public func nSecs() -> Int64 { | |
return Int64(self * nSecMultiplier) | |
} | |
public func nSecs() -> UInt64 { | |
return UInt64(self * nSecMultiplier) | |
} | |
public func dispatchTime() -> dispatch_time_t { | |
// Since the last parameter takes an Int64, the version that returns an Int64 is used. | |
return dispatch_time(DISPATCH_TIME_NOW, self.nSecs()) | |
} | |
} | |
// Define a simple function for getting a timer dispatch source. | |
func repeatingTimerWithInterval(interval: NSTimeInterval, leeway: NSTimeInterval, action: dispatch_block_t) -> dispatch_source_t { | |
let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()) | |
guard timer != nil else { fatalError() } | |
dispatch_source_set_event_handler(timer, action) | |
// This function takes the UInt64 for the last two parameters | |
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval.nSecs(), leeway.nSecs()) | |
dispatch_resume(timer) | |
return timer | |
} | |
// The interval that we will use | |
let interval: NSTimeInterval = 0.01 // 1.0 and 0.1 work fine, 0.01 does not | |
// Create the timer | |
let timer = repeatingTimerWithInterval(interval, leeway: 0.0) { () -> Void in | |
drawDonut() | |
} | |
// Turn off the timer after a few seconds | |
dispatch_after((interval * 60).dispatchTime(), dispatch_get_main_queue()) { () -> Void in | |
dispatch_source_cancel(timer) | |
XCPlaygroundPage.currentPage.finishExecution() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment