├── BlockLooper.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── .gitignore ├── BlockLooper.podspec ├── BlockLooperTests ├── Info.plist └── BlockLooperTests.swift ├── LICENSE ├── BlockLooper ├── AppDelegate.swift ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Launch Screen.xib ├── ViewController.swift └── Source │ └── BlockLooper.swift └── README.md /BlockLooper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | -------------------------------------------------------------------------------- /BlockLooper.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "BlockLooper" 4 | s.version = "0.0.3" 5 | s.summary = "Helper class that lets you loop a closure until you tell it to stop. In Swift." 6 | 7 | s.homepage = "http://github.com/al7/BlockLooper" 8 | s.license = "MIT" 9 | s.author = { "Alex Leite" => "admin@al7dev.com" } 10 | s.ios.deployment_target = "8.0" 11 | s.osx.deployment_target = "10.9" 12 | s.source = { :git => "https://github.com/al7/BlockLooper.git", :tag => "0.0.3" } 13 | s.source_files = "BlockLooper/Source", "BlockLooper/Source/**/*.{h,m,swift}" 14 | s.requires_arc = true 15 | 16 | end 17 | -------------------------------------------------------------------------------- /BlockLooperTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /BlockLooperTests/BlockLooperTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlockLooperTests.swift 3 | // BlockLooperTests 4 | // 5 | // Created by Alexandre Leite on 5/29/15. 6 | // Copyright (c) 2015 Alexandre Leite. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class BlockLooperTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 - Alex Leite (al7dev) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /BlockLooper/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // BlockLooper 4 | // 5 | // Created by Alexandre Leite on 5/29/15. 6 | // Copyright (c) 2015 Alexandre Leite. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | self.window = UIWindow(frame: UIScreen.mainScreen().bounds) 19 | self.window?.rootViewController = ViewController() 20 | self.window?.makeKeyAndVisible() 21 | 22 | return true 23 | } 24 | 25 | func applicationWillResignActive(application: UIApplication) { 26 | 27 | } 28 | 29 | func applicationDidEnterBackground(application: UIApplication) { 30 | 31 | } 32 | 33 | func applicationWillEnterForeground(application: UIApplication) { 34 | 35 | } 36 | 37 | func applicationDidBecomeActive(application: UIApplication) { 38 | 39 | } 40 | 41 | func applicationWillTerminate(application: UIApplication) { 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /BlockLooper/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /BlockLooper/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 0.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | Launch Screen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | BlockLooper 2 | ===================== 3 | 4 | ### About 5 | 6 | This is a helper class that allows you to easily execute a closure on a loop, at a certain rate, until you tell it to stop. It's is very useful for creating, for instance, quick sequential animations using *UIKit*. To better understand what this class does, run the sample project on the iPhone Simulator, then look at the source code. 7 | 8 | ### Sample Code 9 | 10 | Using this class is pretty simple and straight-forward. You just need to run the following code: 11 | 12 | ```swift 13 | //-- Scheduling a loopable closure: 14 | 15 | BlockLooper.executeBlockWithRate(0.5) { 16 | 17 | // loop code goes here... 18 | 19 | return true 20 | } 21 | ``` 22 | 23 | In the function call, ```rate``` corresponds to the *NSTimeInterval* value of the frequency in which the closure should be looped. In the sample above, the closure will be executed once, and then stop. 24 | 25 | The closure signature is: ```() -> Bool ```, where the return value indicates if the loop should be interrupted. In the sample below, we are running the loop 10 times until it stops: 26 | 27 | ```swift 28 | var loopI = 0 29 | 30 | BlockLooper.executeBlockWithRate(0.5) { 31 | 32 | println("Loop i: \(loopI)") 33 | ++loopI 34 | 35 | return (loopI >= 10) 36 | } 37 | ``` 38 | You can also execute multiple loops at once. 39 | 40 | ### How to install 41 | 42 | To use this control, you can either copy the [*BlockLooper.swift*](BlockLooper/Source/BlockLooper.swift) file to your project (you can find it at the '[Source](BlockLooper/Source)' folder of this project), or add the following pod to your Podfile, using CocoaPods 0.36 and up: 43 | 44 | ``` 45 | pod 'BlockLooper' 46 | ``` 47 | 48 | ### License 49 | 50 | This component is available under MIT license. 51 | -------------------------------------------------------------------------------- /BlockLooper/Launch Screen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /BlockLooper/ViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015 - Alex Leite (al7dev) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | import UIKit 26 | 27 | class ViewController: UIViewController { 28 | 29 | var sampleSquare: UIView? 30 | var columns = 5 31 | var rows: Int { return self.columns } 32 | var cellSpan: CGFloat = 0.0 33 | 34 | override func loadView() { 35 | self.view = UIView(frame: UIScreen.mainScreen().bounds) 36 | self.view.backgroundColor = UIColor.whiteColor() 37 | 38 | let screenSize = UIScreen.mainScreen().bounds.size 39 | let squareSpan = min(screenSize.width, screenSize.height) - 100.0 40 | 41 | self.sampleSquare = UIView(frame: CGRectMake(0.0, 0.0, squareSpan, squareSpan)) 42 | self.sampleSquare!.layer.borderColor = UIColor.blueColor().CGColor 43 | self.sampleSquare!.layer.borderWidth = 1.0 44 | self.sampleSquare!.center = self.view.center 45 | 46 | self.view.addSubview(self.sampleSquare!) 47 | } 48 | 49 | override func viewDidLoad() { 50 | super.viewDidLoad() 51 | self.cellSpan = self.sampleSquare!.frame.size.width / CGFloat(self.columns) 52 | } 53 | 54 | override func viewDidAppear(animated: Bool) { 55 | super.viewDidAppear(animated) 56 | self.performSampleCode() 57 | } 58 | 59 | override func didReceiveMemoryWarning() { 60 | super.didReceiveMemoryWarning() 61 | 62 | } 63 | 64 | //MARK- Helper Methods 65 | 66 | private func performSampleCode() { 67 | 68 | //--- HERE IS HOW TO USE THE COMPONENT: 69 | var cellI = 0 70 | let totalCells = self.columns * self.rows 71 | let colorIncrement = 1.0 / CGFloat(totalCells) 72 | var currentColorShade: CGFloat = 0.0 73 | 74 | BlockLooper.executeBlockWithRate(0.1) { 75 | [unowned self] in 76 | 77 | let columnI = cellI % self.columns 78 | let rowI = Int(floor(Double(cellI) / Double(self.rows))) 79 | 80 | let newLabel = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: self.cellSpan, height: self.cellSpan)) 81 | newLabel.textColor = UIColor.blueColor() 82 | newLabel.font = UIFont.boldSystemFontOfSize(24.0) 83 | newLabel.textAlignment = .Center 84 | newLabel.text = "\(cellI)" 85 | newLabel.layer.borderColor = UIColor.blueColor().CGColor 86 | newLabel.layer.borderWidth = 1.0 87 | newLabel.backgroundColor = UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: currentColorShade) 88 | newLabel.alpha = 0.0 89 | 90 | self.sampleSquare!.addSubview(newLabel) 91 | 92 | UIView.animateWithDuration(0.5) { 93 | var newFrame = newLabel.frame 94 | newFrame.origin.x = self.cellSpan * CGFloat(columnI) 95 | newFrame.origin.y = self.cellSpan * CGFloat(rowI) 96 | newLabel.frame = newFrame 97 | newLabel.alpha = 1.0 98 | } 99 | 100 | cellI++ 101 | currentColorShade += colorIncrement 102 | if cellI >= totalCells { 103 | return true 104 | } 105 | else { 106 | return false 107 | } 108 | } 109 | } 110 | 111 | } 112 | 113 | -------------------------------------------------------------------------------- /BlockLooper/Source/BlockLooper.swift: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2015 - Alex Leite (al7dev) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | import Foundation 26 | 27 | public typealias LoopableBlock = () -> Bool 28 | 29 | public class BlockLooper { 30 | 31 | public class func executeBlockWithRate(rate: NSTimeInterval, block: LoopableBlock) { 32 | let newLoopInstance = LoopInstance(rate: rate, loopableBlock: block) 33 | newLoopInstance.index = self.helper.nextIndex 34 | newLoopInstance.endBlock = { 35 | loopInstance, event in 36 | BlockLooper.helper.scheduleLoopInstance(loopInstance) 37 | } 38 | BlockLooper.helper.scheduleLoopInstance(newLoopInstance) 39 | } 40 | 41 | //MARK- Singleton Methods 42 | 43 | static var helper: Helper { 44 | struct Static { 45 | static var instance: Helper? 46 | static var token: dispatch_once_t = 0 47 | } 48 | 49 | dispatch_once(&Static.token) { 50 | Static.instance = Helper() 51 | } 52 | 53 | return Static.instance! 54 | } 55 | 56 | //MARK- Helper Classes 57 | 58 | class Helper { 59 | private var loopIndex = 0 60 | var nextIndex: Int { 61 | let result = self.loopIndex 62 | ++self.loopIndex 63 | return result 64 | } 65 | 66 | var loopInstances: LoopInstances = [] 67 | 68 | func isLoopInstanceScheduled(loopInstance: LoopInstance) -> Bool { 69 | if let _ = self.loopInstances.indexOf(loopInstance) { 70 | return true 71 | } 72 | return false 73 | } 74 | 75 | func scheduleLoopInstance(loopInstance: LoopInstance) -> Bool { 76 | if self.isLoopInstanceScheduled(loopInstance) == false { 77 | self.loopInstances.append(loopInstance) 78 | loopInstance.start() 79 | return true 80 | } 81 | return false 82 | } 83 | 84 | func dismissLoopInstance(loopInstance: LoopInstance) -> Bool { 85 | if let index = self.loopInstances.indexOf(loopInstance) { 86 | loopInstance.cleanUp() 87 | self.loopInstances.removeAtIndex(index) 88 | return true 89 | } 90 | return false 91 | } 92 | } 93 | 94 | class LoopInstance: NSObject { 95 | private var rate: NSTimeInterval = 1.0 96 | private var loopableBlock: LoopableBlock 97 | private var loopTimer: NSTimer? 98 | private var hasStarted = false 99 | 100 | var index = 0 101 | var startBlock: LoopLifecycleBlock? 102 | var stepBlock: LoopLifecycleBlock? 103 | var endBlock: LoopLifecycleBlock? 104 | 105 | init(rate: NSTimeInterval, loopableBlock: LoopableBlock!) { 106 | self.rate = rate 107 | self.loopableBlock = loopableBlock 108 | } 109 | 110 | func start() { 111 | if hasStarted == false { 112 | hasStarted = true 113 | 114 | if let startBlock = self.startBlock { 115 | startBlock(loopInstance: self, event: .Start) 116 | } 117 | 118 | self.loopTimer = NSTimer.scheduledTimerWithTimeInterval(self.rate, target: self, selector: "onTimerTick:", userInfo: nil, repeats: true) 119 | } 120 | else { 121 | if let timer = self.loopTimer { 122 | timer.fire() 123 | } 124 | } 125 | } 126 | 127 | func stop() { 128 | if let timer = self.loopTimer { 129 | timer.invalidate() 130 | } 131 | } 132 | 133 | func cleanUp() { 134 | self.loopTimer = nil 135 | self.startBlock = nil 136 | self.stepBlock = nil 137 | self.endBlock = nil 138 | } 139 | 140 | func onTimerTick(sender: NSTimer!) { 141 | if let stepBlock = self.stepBlock { 142 | stepBlock(loopInstance: self, event: .Step) 143 | } 144 | 145 | let shouldFinish = self.loopableBlock() 146 | if shouldFinish { 147 | self.stop() 148 | if let endBlock = self.endBlock { 149 | endBlock(loopInstance: self, event: .End) 150 | } 151 | } 152 | } 153 | } 154 | 155 | enum LoopLifecycleEvent { 156 | case Start, Step, End 157 | } 158 | 159 | typealias LoopInstances = [LoopInstance] 160 | typealias LoopLifecycleBlock = (loopInstance: LoopInstance, event: LoopLifecycleEvent) -> Void 161 | } 162 | 163 | func ==(lhs: BlockLooper.LoopInstance, rhs: BlockLooper.LoopInstance) -> Bool { 164 | return lhs.index == rhs.index 165 | } 166 | -------------------------------------------------------------------------------- /BlockLooper.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1320AB9C1B196C5B008B5188 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1320AB9B1B196C5B008B5188 /* AppDelegate.swift */; }; 11 | 1320AB9E1B196C5B008B5188 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1320AB9D1B196C5B008B5188 /* ViewController.swift */; }; 12 | 1320ABA31B196C5B008B5188 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1320ABA21B196C5B008B5188 /* Images.xcassets */; }; 13 | 1320ABB21B196C5B008B5188 /* BlockLooperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1320ABB11B196C5B008B5188 /* BlockLooperTests.swift */; }; 14 | 1320ABBD1B19750A008B5188 /* BlockLooper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1320ABBC1B19750A008B5188 /* BlockLooper.swift */; }; 15 | 1320ABC81B1F4C5A008B5188 /* Launch Screen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1320ABC71B1F4C5A008B5188 /* Launch Screen.xib */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 1320ABAC1B196C5B008B5188 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 1320AB8E1B196C5B008B5188 /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 1320AB951B196C5B008B5188; 24 | remoteInfo = BlockLooper; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 1320AB961B196C5B008B5188 /* BlockLooper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BlockLooper.app; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 1320AB9A1B196C5B008B5188 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 1320AB9B1B196C5B008B5188 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 32 | 1320AB9D1B196C5B008B5188 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 33 | 1320ABA21B196C5B008B5188 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 34 | 1320ABAB1B196C5B008B5188 /* BlockLooperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BlockLooperTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 1320ABB01B196C5B008B5188 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 1320ABB11B196C5B008B5188 /* BlockLooperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockLooperTests.swift; sourceTree = ""; }; 37 | 1320ABBC1B19750A008B5188 /* BlockLooper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockLooper.swift; sourceTree = ""; }; 38 | 1320ABC71B1F4C5A008B5188 /* Launch Screen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "Launch Screen.xib"; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 1320AB931B196C5B008B5188 /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | ); 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | 1320ABA81B196C5B008B5188 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXFrameworksBuildPhase section */ 57 | 58 | /* Begin PBXGroup section */ 59 | 1320AB8D1B196C5B008B5188 = { 60 | isa = PBXGroup; 61 | children = ( 62 | 1320AB981B196C5B008B5188 /* BlockLooper */, 63 | 1320ABAE1B196C5B008B5188 /* BlockLooperTests */, 64 | 1320AB971B196C5B008B5188 /* Products */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 1320AB971B196C5B008B5188 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 1320AB961B196C5B008B5188 /* BlockLooper.app */, 72 | 1320ABAB1B196C5B008B5188 /* BlockLooperTests.xctest */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 1320AB981B196C5B008B5188 /* BlockLooper */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 1320ABBB1B196D16008B5188 /* Source */, 81 | 1320AB9B1B196C5B008B5188 /* AppDelegate.swift */, 82 | 1320AB9D1B196C5B008B5188 /* ViewController.swift */, 83 | 1320ABA21B196C5B008B5188 /* Images.xcassets */, 84 | 1320AB991B196C5B008B5188 /* Supporting Files */, 85 | 1320ABC71B1F4C5A008B5188 /* Launch Screen.xib */, 86 | ); 87 | path = BlockLooper; 88 | sourceTree = ""; 89 | }; 90 | 1320AB991B196C5B008B5188 /* Supporting Files */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 1320AB9A1B196C5B008B5188 /* Info.plist */, 94 | ); 95 | name = "Supporting Files"; 96 | sourceTree = ""; 97 | }; 98 | 1320ABAE1B196C5B008B5188 /* BlockLooperTests */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 1320ABB11B196C5B008B5188 /* BlockLooperTests.swift */, 102 | 1320ABAF1B196C5B008B5188 /* Supporting Files */, 103 | ); 104 | path = BlockLooperTests; 105 | sourceTree = ""; 106 | }; 107 | 1320ABAF1B196C5B008B5188 /* Supporting Files */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 1320ABB01B196C5B008B5188 /* Info.plist */, 111 | ); 112 | name = "Supporting Files"; 113 | sourceTree = ""; 114 | }; 115 | 1320ABBB1B196D16008B5188 /* Source */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 1320ABBC1B19750A008B5188 /* BlockLooper.swift */, 119 | ); 120 | path = Source; 121 | sourceTree = ""; 122 | }; 123 | /* End PBXGroup section */ 124 | 125 | /* Begin PBXNativeTarget section */ 126 | 1320AB951B196C5B008B5188 /* BlockLooper */ = { 127 | isa = PBXNativeTarget; 128 | buildConfigurationList = 1320ABB51B196C5B008B5188 /* Build configuration list for PBXNativeTarget "BlockLooper" */; 129 | buildPhases = ( 130 | 1320AB921B196C5B008B5188 /* Sources */, 131 | 1320AB931B196C5B008B5188 /* Frameworks */, 132 | 1320AB941B196C5B008B5188 /* Resources */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | ); 138 | name = BlockLooper; 139 | productName = BlockLooper; 140 | productReference = 1320AB961B196C5B008B5188 /* BlockLooper.app */; 141 | productType = "com.apple.product-type.application"; 142 | }; 143 | 1320ABAA1B196C5B008B5188 /* BlockLooperTests */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = 1320ABB81B196C5B008B5188 /* Build configuration list for PBXNativeTarget "BlockLooperTests" */; 146 | buildPhases = ( 147 | 1320ABA71B196C5B008B5188 /* Sources */, 148 | 1320ABA81B196C5B008B5188 /* Frameworks */, 149 | 1320ABA91B196C5B008B5188 /* Resources */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | 1320ABAD1B196C5B008B5188 /* PBXTargetDependency */, 155 | ); 156 | name = BlockLooperTests; 157 | productName = BlockLooperTests; 158 | productReference = 1320ABAB1B196C5B008B5188 /* BlockLooperTests.xctest */; 159 | productType = "com.apple.product-type.bundle.unit-test"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 1320AB8E1B196C5B008B5188 /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | LastSwiftMigration = 0700; 168 | LastSwiftUpdateCheck = 0700; 169 | LastUpgradeCheck = 0700; 170 | ORGANIZATIONNAME = "Alexandre Leite"; 171 | TargetAttributes = { 172 | 1320AB951B196C5B008B5188 = { 173 | CreatedOnToolsVersion = 6.3; 174 | }; 175 | 1320ABAA1B196C5B008B5188 = { 176 | CreatedOnToolsVersion = 6.3; 177 | TestTargetID = 1320AB951B196C5B008B5188; 178 | }; 179 | }; 180 | }; 181 | buildConfigurationList = 1320AB911B196C5B008B5188 /* Build configuration list for PBXProject "BlockLooper" */; 182 | compatibilityVersion = "Xcode 3.2"; 183 | developmentRegion = English; 184 | hasScannedForEncodings = 0; 185 | knownRegions = ( 186 | en, 187 | Base, 188 | ); 189 | mainGroup = 1320AB8D1B196C5B008B5188; 190 | productRefGroup = 1320AB971B196C5B008B5188 /* Products */; 191 | projectDirPath = ""; 192 | projectRoot = ""; 193 | targets = ( 194 | 1320AB951B196C5B008B5188 /* BlockLooper */, 195 | 1320ABAA1B196C5B008B5188 /* BlockLooperTests */, 196 | ); 197 | }; 198 | /* End PBXProject section */ 199 | 200 | /* Begin PBXResourcesBuildPhase section */ 201 | 1320AB941B196C5B008B5188 /* Resources */ = { 202 | isa = PBXResourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 1320ABA31B196C5B008B5188 /* Images.xcassets in Resources */, 206 | 1320ABC81B1F4C5A008B5188 /* Launch Screen.xib in Resources */, 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | 1320ABA91B196C5B008B5188 /* Resources */ = { 211 | isa = PBXResourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXResourcesBuildPhase section */ 218 | 219 | /* Begin PBXSourcesBuildPhase section */ 220 | 1320AB921B196C5B008B5188 /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 1320ABBD1B19750A008B5188 /* BlockLooper.swift in Sources */, 225 | 1320AB9E1B196C5B008B5188 /* ViewController.swift in Sources */, 226 | 1320AB9C1B196C5B008B5188 /* AppDelegate.swift in Sources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | 1320ABA71B196C5B008B5188 /* Sources */ = { 231 | isa = PBXSourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | 1320ABB21B196C5B008B5188 /* BlockLooperTests.swift in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | /* End PBXSourcesBuildPhase section */ 239 | 240 | /* Begin PBXTargetDependency section */ 241 | 1320ABAD1B196C5B008B5188 /* PBXTargetDependency */ = { 242 | isa = PBXTargetDependency; 243 | target = 1320AB951B196C5B008B5188 /* BlockLooper */; 244 | targetProxy = 1320ABAC1B196C5B008B5188 /* PBXContainerItemProxy */; 245 | }; 246 | /* End PBXTargetDependency section */ 247 | 248 | /* Begin XCBuildConfiguration section */ 249 | 1320ABB31B196C5B008B5188 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | ALWAYS_SEARCH_USER_PATHS = NO; 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 254 | CLANG_CXX_LIBRARY = "libc++"; 255 | CLANG_ENABLE_MODULES = YES; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_BOOL_CONVERSION = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 260 | CLANG_WARN_EMPTY_BODY = YES; 261 | CLANG_WARN_ENUM_CONVERSION = YES; 262 | CLANG_WARN_INT_CONVERSION = YES; 263 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 264 | CLANG_WARN_UNREACHABLE_CODE = YES; 265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 266 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 267 | COPY_PHASE_STRIP = NO; 268 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 269 | ENABLE_STRICT_OBJC_MSGSEND = YES; 270 | ENABLE_TESTABILITY = YES; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_NO_COMMON_BLOCKS = YES; 274 | GCC_OPTIMIZATION_LEVEL = 0; 275 | GCC_PREPROCESSOR_DEFINITIONS = ( 276 | "DEBUG=1", 277 | "$(inherited)", 278 | ); 279 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 287 | MTL_ENABLE_DEBUG_INFO = YES; 288 | ONLY_ACTIVE_ARCH = YES; 289 | SDKROOT = iphoneos; 290 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 291 | TARGETED_DEVICE_FAMILY = "1,2"; 292 | }; 293 | name = Debug; 294 | }; 295 | 1320ABB41B196C5B008B5188 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 300 | CLANG_CXX_LIBRARY = "libc++"; 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | CLANG_WARN_BOOL_CONVERSION = YES; 304 | CLANG_WARN_CONSTANT_CONVERSION = YES; 305 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INT_CONVERSION = YES; 309 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 310 | CLANG_WARN_UNREACHABLE_CODE = YES; 311 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 312 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 313 | COPY_PHASE_STRIP = NO; 314 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 315 | ENABLE_NS_ASSERTIONS = NO; 316 | ENABLE_STRICT_OBJC_MSGSEND = YES; 317 | GCC_C_LANGUAGE_STANDARD = gnu99; 318 | GCC_NO_COMMON_BLOCKS = YES; 319 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 320 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 321 | GCC_WARN_UNDECLARED_SELECTOR = YES; 322 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 323 | GCC_WARN_UNUSED_FUNCTION = YES; 324 | GCC_WARN_UNUSED_VARIABLE = YES; 325 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 326 | MTL_ENABLE_DEBUG_INFO = NO; 327 | SDKROOT = iphoneos; 328 | TARGETED_DEVICE_FAMILY = "1,2"; 329 | VALIDATE_PRODUCT = YES; 330 | }; 331 | name = Release; 332 | }; 333 | 1320ABB61B196C5B008B5188 /* Debug */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 337 | INFOPLIST_FILE = BlockLooper/Info.plist; 338 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 339 | PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)"; 340 | PRODUCT_NAME = "$(TARGET_NAME)"; 341 | }; 342 | name = Debug; 343 | }; 344 | 1320ABB71B196C5B008B5188 /* Release */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 348 | INFOPLIST_FILE = BlockLooper/Info.plist; 349 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 350 | PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)"; 351 | PRODUCT_NAME = "$(TARGET_NAME)"; 352 | }; 353 | name = Release; 354 | }; 355 | 1320ABB91B196C5B008B5188 /* Debug */ = { 356 | isa = XCBuildConfiguration; 357 | buildSettings = { 358 | BUNDLE_LOADER = "$(TEST_HOST)"; 359 | FRAMEWORK_SEARCH_PATHS = ( 360 | "$(SDKROOT)/Developer/Library/Frameworks", 361 | "$(inherited)", 362 | ); 363 | GCC_PREPROCESSOR_DEFINITIONS = ( 364 | "DEBUG=1", 365 | "$(inherited)", 366 | ); 367 | INFOPLIST_FILE = BlockLooperTests/Info.plist; 368 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 369 | PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)"; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BlockLooper.app/BlockLooper"; 372 | }; 373 | name = Debug; 374 | }; 375 | 1320ABBA1B196C5B008B5188 /* Release */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | BUNDLE_LOADER = "$(TEST_HOST)"; 379 | FRAMEWORK_SEARCH_PATHS = ( 380 | "$(SDKROOT)/Developer/Library/Frameworks", 381 | "$(inherited)", 382 | ); 383 | INFOPLIST_FILE = BlockLooperTests/Info.plist; 384 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 385 | PRODUCT_BUNDLE_IDENTIFIER = "com.al7dev.$(PRODUCT_NAME:rfc1034identifier)"; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BlockLooper.app/BlockLooper"; 388 | }; 389 | name = Release; 390 | }; 391 | /* End XCBuildConfiguration section */ 392 | 393 | /* Begin XCConfigurationList section */ 394 | 1320AB911B196C5B008B5188 /* Build configuration list for PBXProject "BlockLooper" */ = { 395 | isa = XCConfigurationList; 396 | buildConfigurations = ( 397 | 1320ABB31B196C5B008B5188 /* Debug */, 398 | 1320ABB41B196C5B008B5188 /* Release */, 399 | ); 400 | defaultConfigurationIsVisible = 0; 401 | defaultConfigurationName = Release; 402 | }; 403 | 1320ABB51B196C5B008B5188 /* Build configuration list for PBXNativeTarget "BlockLooper" */ = { 404 | isa = XCConfigurationList; 405 | buildConfigurations = ( 406 | 1320ABB61B196C5B008B5188 /* Debug */, 407 | 1320ABB71B196C5B008B5188 /* Release */, 408 | ); 409 | defaultConfigurationIsVisible = 0; 410 | defaultConfigurationName = Release; 411 | }; 412 | 1320ABB81B196C5B008B5188 /* Build configuration list for PBXNativeTarget "BlockLooperTests" */ = { 413 | isa = XCConfigurationList; 414 | buildConfigurations = ( 415 | 1320ABB91B196C5B008B5188 /* Debug */, 416 | 1320ABBA1B196C5B008B5188 /* Release */, 417 | ); 418 | defaultConfigurationIsVisible = 0; 419 | defaultConfigurationName = Release; 420 | }; 421 | /* End XCConfigurationList section */ 422 | }; 423 | rootObject = 1320AB8E1B196C5B008B5188 /* Project object */; 424 | } 425 | --------------------------------------------------------------------------------