Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions BlockLooper.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,11 @@
TargetAttributes = {
1320AB951B196C5B008B5188 = {
CreatedOnToolsVersion = 6.3;
LastSwiftMigration = 0810;
};
1320ABAA1B196C5B008B5188 = {
CreatedOnToolsVersion = 6.3;
LastSwiftMigration = 0810;
TestTargetID = 1320AB951B196C5B008B5188;
};
};
Expand Down Expand Up @@ -338,6 +340,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
Expand All @@ -349,6 +352,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
Expand All @@ -368,6 +372,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BlockLooper.app/BlockLooper";
};
name = Debug;
Expand All @@ -384,6 +389,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BlockLooper.app/BlockLooper";
};
name = Release;
Expand Down
14 changes: 7 additions & 7 deletions BlockLooper/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,31 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = ViewController()
self.window?.makeKeyAndVisible()

return true
}

func applicationWillResignActive(application: UIApplication) {
func applicationWillResignActive(_ application: UIApplication) {

}

func applicationDidEnterBackground(application: UIApplication) {
func applicationDidEnterBackground(_ application: UIApplication) {

}

func applicationWillEnterForeground(application: UIApplication) {
func applicationWillEnterForeground(_ application: UIApplication) {

}

func applicationDidBecomeActive(application: UIApplication) {
func applicationDidBecomeActive(_ application: UIApplication) {

}

func applicationWillTerminate(application: UIApplication) {
func applicationWillTerminate(_ application: UIApplication) {

}

Expand Down
63 changes: 33 additions & 30 deletions BlockLooper/Source/BlockLooper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,18 @@ import Foundation

public typealias LoopableBlock = () -> Bool

public class BlockLooper {
open class BlockLooper {

struct Static {
static var instance: Helper?
static var token: Int = 0
}

private static var __once: () = {
Static.instance = Helper()
}()

public class func executeBlockWithRate(rate: NSTimeInterval, block: LoopableBlock) {
open class func executeBlockWithRate(_ rate: TimeInterval, block: @escaping LoopableBlock) {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be better to update to Swift 3.0 syntax -- i.e: executeBlock(rate: TimeInterval, block: @escaping LoopableBlock)

let newLoopInstance = LoopInstance(rate: rate, loopableBlock: block)
newLoopInstance.index = self.helper.nextIndex
newLoopInstance.endBlock = {
Expand All @@ -41,38 +50,32 @@ public class BlockLooper {
//MARK- Singleton Methods

static var helper: Helper {
struct Static {
static var instance: Helper?
static var token: dispatch_once_t = 0
}

dispatch_once(&Static.token) {
Static.instance = Helper()
}

_ = BlockLooper.__once

return Static.instance!
}

//MARK- Helper Classes

class Helper {
private var loopIndex = 0
fileprivate var loopIndex = 0
var nextIndex: Int {
let result = self.loopIndex
++self.loopIndex
self.loopIndex += 1
return result
}

var loopInstances: LoopInstances = []

func isLoopInstanceScheduled(loopInstance: LoopInstance) -> Bool {
if let _ = self.loopInstances.indexOf(loopInstance) {
func isLoopInstanceScheduled(_ loopInstance: LoopInstance) -> Bool {
if let _ = self.loopInstances.index(of: loopInstance) {
return true
}
return false
}

func scheduleLoopInstance(loopInstance: LoopInstance) -> Bool {
func scheduleLoopInstance(_ loopInstance: LoopInstance) -> Bool {
if self.isLoopInstanceScheduled(loopInstance) == false {
self.loopInstances.append(loopInstance)
loopInstance.start()
Expand All @@ -81,28 +84,28 @@ public class BlockLooper {
return false
}

func dismissLoopInstance(loopInstance: LoopInstance) -> Bool {
if let index = self.loopInstances.indexOf(loopInstance) {
func dismissLoopInstance(_ loopInstance: LoopInstance) -> Bool {
if let index = self.loopInstances.index(of: loopInstance) {
loopInstance.cleanUp()
self.loopInstances.removeAtIndex(index)
self.loopInstances.remove(at: index)
return true
}
return false
}
}

class LoopInstance: NSObject {
private var rate: NSTimeInterval = 1.0
private var loopableBlock: LoopableBlock
private var loopTimer: NSTimer?
private var hasStarted = false
fileprivate var rate: TimeInterval = 1.0
fileprivate var loopableBlock: LoopableBlock
fileprivate var loopTimer: Timer?
fileprivate var hasStarted = false

var index = 0
var startBlock: LoopLifecycleBlock?
var stepBlock: LoopLifecycleBlock?
var endBlock: LoopLifecycleBlock?

init(rate: NSTimeInterval, loopableBlock: LoopableBlock!) {
init(rate: TimeInterval, loopableBlock: LoopableBlock!) {
self.rate = rate
self.loopableBlock = loopableBlock
}
Expand All @@ -112,10 +115,10 @@ public class BlockLooper {
hasStarted = true

if let startBlock = self.startBlock {
startBlock(loopInstance: self, event: .Start)
startBlock(self, .start)
}

self.loopTimer = NSTimer.scheduledTimerWithTimeInterval(self.rate, target: self, selector: "onTimerTick:", userInfo: nil, repeats: true)
self.loopTimer = Timer.scheduledTimer(timeInterval: self.rate, target: self, selector: #selector(LoopInstance.onTimerTick(_:)), userInfo: nil, repeats: true)
}
else {
if let timer = self.loopTimer {
Expand All @@ -137,27 +140,27 @@ public class BlockLooper {
self.endBlock = nil
}

func onTimerTick(sender: NSTimer!) {
func onTimerTick(_ sender: Timer!) {
if let stepBlock = self.stepBlock {
stepBlock(loopInstance: self, event: .Step)
stepBlock(self, .step)
}

let shouldFinish = self.loopableBlock()
if shouldFinish {
self.stop()
if let endBlock = self.endBlock {
endBlock(loopInstance: self, event: .End)
endBlock(self, .end)
}
}
}
}

enum LoopLifecycleEvent {
case Start, Step, End
case start, step, end
}

typealias LoopInstances = [LoopInstance]
typealias LoopLifecycleBlock = (loopInstance: LoopInstance, event: LoopLifecycleEvent) -> Void
typealias LoopLifecycleBlock = (_ loopInstance: LoopInstance, _ event: LoopLifecycleEvent) -> Void
}

func ==(lhs: BlockLooper.LoopInstance, rhs: BlockLooper.LoopInstance) -> Bool {
Expand Down
28 changes: 14 additions & 14 deletions BlockLooper/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ class ViewController: UIViewController {
var cellSpan: CGFloat = 0.0

override func loadView() {
self.view = UIView(frame: UIScreen.mainScreen().bounds)
self.view.backgroundColor = UIColor.whiteColor()
self.view = UIView(frame: UIScreen.main.bounds)
self.view.backgroundColor = UIColor.white

let screenSize = UIScreen.mainScreen().bounds.size
let screenSize = UIScreen.main.bounds.size
let squareSpan = min(screenSize.width, screenSize.height) - 100.0

self.sampleSquare = UIView(frame: CGRectMake(0.0, 0.0, squareSpan, squareSpan))
self.sampleSquare!.layer.borderColor = UIColor.blueColor().CGColor
self.sampleSquare = UIView(frame: CGRect(x: 0.0, y: 0.0, width: squareSpan, height: squareSpan))
self.sampleSquare!.layer.borderColor = UIColor.blue.cgColor
self.sampleSquare!.layer.borderWidth = 1.0
self.sampleSquare!.center = self.view.center

Expand All @@ -51,7 +51,7 @@ class ViewController: UIViewController {
self.cellSpan = self.sampleSquare!.frame.size.width / CGFloat(self.columns)
}

override func viewDidAppear(animated: Bool) {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.performSampleCode()
}
Expand All @@ -63,7 +63,7 @@ class ViewController: UIViewController {

//MARK- Helper Methods

private func performSampleCode() {
fileprivate func performSampleCode() {

//--- HERE IS HOW TO USE THE COMPONENT:
var cellI = 0
Expand All @@ -78,26 +78,26 @@ class ViewController: UIViewController {
let rowI = Int(floor(Double(cellI) / Double(self.rows)))

let newLabel = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: self.cellSpan, height: self.cellSpan))
newLabel.textColor = UIColor.blueColor()
newLabel.font = UIFont.boldSystemFontOfSize(24.0)
newLabel.textAlignment = .Center
newLabel.textColor = UIColor.blue
newLabel.font = UIFont.boldSystemFont(ofSize: 24.0)
newLabel.textAlignment = .center
newLabel.text = "\(cellI)"
newLabel.layer.borderColor = UIColor.blueColor().CGColor
newLabel.layer.borderColor = UIColor.blue.cgColor
newLabel.layer.borderWidth = 1.0
newLabel.backgroundColor = UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: currentColorShade)
newLabel.alpha = 0.0

self.sampleSquare!.addSubview(newLabel)

UIView.animateWithDuration(0.5) {
UIView.animate(withDuration: 0.5, animations: {
var newFrame = newLabel.frame
newFrame.origin.x = self.cellSpan * CGFloat(columnI)
newFrame.origin.y = self.cellSpan * CGFloat(rowI)
newLabel.frame = newFrame
newLabel.alpha = 1.0
}
})

cellI++
cellI += cellI
currentColorShade += colorIncrement
if cellI >= totalCells {
return true
Expand Down
2 changes: 1 addition & 1 deletion BlockLooperTests/BlockLooperTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class BlockLooperTests: XCTestCase {

func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock() {
self.measure() {
// Put the code you want to measure the time of here.
}
}
Expand Down