├── assets ├── icon@2x.png ├── icon@3x.png ├── appstore.png ├── icon-ipad.png ├── appstore@2x.png ├── icon-ipad@2x.png ├── icon-ipad-pro@2x.png ├── icon-settings@2x.png ├── icon-settings@3x.png ├── icon-spotlight@2x.png ├── icon-spotlight@3x.png ├── icon-ipad-settings.png ├── icon-ipad-spotlight.png ├── icon-ipad-settings@2x.png └── icon-ipad-spotlight@2x.png ├── himbo ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── appstore.png │ │ ├── icon@2x.png │ │ ├── icon@3x.png │ │ ├── icon-ipad.png │ │ ├── icon-ipad@2x.png │ │ ├── icon-ipad-pro@2x.png │ │ ├── icon-ipad-settings.png │ │ ├── icon-settings@2x.png │ │ ├── icon-settings@3x.png │ │ ├── icon-spotlight@2x.png │ │ ├── icon-spotlight@3x.png │ │ ├── icon-ipad-spotlight.png │ │ ├── icon-ipad-settings@2x.png │ │ ├── icon-ipad-spotlight@2x.png │ │ └── Contents.json │ ├── icon-close.imageset │ │ ├── icon-close@2x.png │ │ └── Contents.json │ ├── icon-email.imageset │ │ ├── icon-email@2x.png │ │ └── Contents.json │ ├── icon-share.imageset │ │ ├── icon-share@2x.png │ │ └── Contents.json │ ├── icon-gallery.imageset │ │ ├── icon-gallery@2x.png │ │ └── Contents.json │ ├── icon-twitter.imageset │ │ ├── icon-twitter@2x.png │ │ └── Contents.json │ └── icon-facebook.imageset │ │ ├── icon-facebook@2x.png │ │ └── Contents.json ├── himbo.entitlements ├── Colors.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── ShakeView.swift ├── Info.plist ├── AppDelegate.swift ├── Exporter.swift ├── PulsingLayer.swift ├── InfoView.swift ├── ViewController.swift ├── Tutorial.swift └── SphereMenu.swift ├── himbo.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── mkida.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── project.pbxproj ├── .gitignore ├── README.md ├── himboTests ├── Info.plist └── ColorigTests.swift └── LICENSE.md /assets/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon@2x.png -------------------------------------------------------------------------------- /assets/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon@3x.png -------------------------------------------------------------------------------- /assets/appstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/appstore.png -------------------------------------------------------------------------------- /assets/icon-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-ipad.png -------------------------------------------------------------------------------- /assets/appstore@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/appstore@2x.png -------------------------------------------------------------------------------- /assets/icon-ipad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-ipad@2x.png -------------------------------------------------------------------------------- /assets/icon-ipad-pro@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-ipad-pro@2x.png -------------------------------------------------------------------------------- /assets/icon-settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-settings@2x.png -------------------------------------------------------------------------------- /assets/icon-settings@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-settings@3x.png -------------------------------------------------------------------------------- /assets/icon-spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-spotlight@2x.png -------------------------------------------------------------------------------- /assets/icon-spotlight@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-spotlight@3x.png -------------------------------------------------------------------------------- /assets/icon-ipad-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-ipad-settings.png -------------------------------------------------------------------------------- /assets/icon-ipad-spotlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-ipad-spotlight.png -------------------------------------------------------------------------------- /assets/icon-ipad-settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-ipad-settings@2x.png -------------------------------------------------------------------------------- /assets/icon-ipad-spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/assets/icon-ipad-spotlight@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/appstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/appstore.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon@3x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-ipad.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-ipad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-ipad@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-close.imageset/icon-close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/icon-close.imageset/icon-close@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-email.imageset/icon-email@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/icon-email.imageset/icon-email@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-share.imageset/icon-share@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/icon-share.imageset/icon-share@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-pro@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-pro@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-settings.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-settings@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-settings@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-settings@3x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-spotlight@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-spotlight@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-spotlight@3x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-gallery.imageset/icon-gallery@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/icon-gallery.imageset/icon-gallery@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-twitter.imageset/icon-twitter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/icon-twitter.imageset/icon-twitter@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-spotlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-spotlight.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-facebook.imageset/icon-facebook@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/icon-facebook.imageset/icon-facebook@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-settings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-settings@2x.png -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-spotlight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimar/Himbo/HEAD/himbo/Images.xcassets/AppIcon.appiconset/icon-ipad-spotlight@2x.png -------------------------------------------------------------------------------- /himbo/himbo.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /himbo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 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 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Himbo 2 | 3 | ```text 4 | In need for a new Wallpaper? 5 | Tired of all the overloaded, distracting ones? 6 | 7 | Make yourself a new, single-color one in seconds. 8 | ``` 9 | 10 | Get it in the [App Store](https://itunes.apple.com/us/app/himbo/id946738439?ls=1&mt=8) and check it out. 11 | 12 | * Written in Swift 1.x and migrated to Swift 2.x, Swift 3.x and Swift 4 13 | * Supports 3D Touch (if available) 14 | * MIT License 15 | -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon-close@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-email.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon-email@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon-share@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-facebook.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon-facebook@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-gallery.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon-gallery@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /himbo/Images.xcassets/icon-twitter.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon-twitter@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /himbo/Colors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Colors.swift 3 | // himbo 4 | // 5 | // Created by Marcus Kida on 30/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor { 12 | class func himboRed() -> UIColor { 13 | // return UIColor(hue: 0.95, saturation: 0.9, brightness: 0.8, alpha: 1.0) 14 | return UIColor(red: 234.0/255.0, green: 84.0/255.0, blue: 122.0/255.0, alpha: 1.0) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /himbo.xcodeproj/xcuserdata/mkida.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | himbo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | EC1AEC621A1C6B4A00D1FA48 16 | 17 | primary 18 | 19 | 20 | EC1AEC771A1C6B4A00D1FA48 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /himboTests/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 | -------------------------------------------------------------------------------- /himboTests/ColorigTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorigTests.swift 3 | // ColorigTests 4 | // 5 | // Created by Marcus Kida on 19/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class ColorigTests: 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.md: -------------------------------------------------------------------------------- 1 | **The MIT License (MIT)** 2 | 3 | Copyright (c) 2014 - 2015 by Marcus Kida 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /himbo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /himbo/ShakeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShakeView.swift 3 | // himbo 4 | // 5 | // Created by Marcus Kida on 29/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum ShakeDirection { 12 | case Horizontal, Vertical 13 | } 14 | 15 | extension UIView { 16 | func shake(times: Int, direction: ShakeDirection) { 17 | shake(times: times, iteration: 0, direction: 1, shakeDirection: direction, delta: 10, speed: 0.08) 18 | } 19 | private func shake(times: Int, iteration: Int, direction: CGFloat, shakeDirection: ShakeDirection, delta: CGFloat, speed: TimeInterval) { 20 | UIView.animate(withDuration: speed, animations: { () -> Void in 21 | self.layer.setAffineTransform((shakeDirection == ShakeDirection.Horizontal) ? CGAffineTransform(translationX: delta * direction, y: 0) : CGAffineTransform(translationX: 0, y: delta * direction)) 22 | }) { (finished: Bool) -> Void in 23 | if iteration >= times { 24 | UIView.animate(withDuration: speed, animations: { () -> Void in 25 | self.layer.setAffineTransform(CGAffineTransform.identity) 26 | }) 27 | return 28 | } 29 | self.shake(times: (times - 1), iteration: (iteration + 1), direction: (direction * -1), shakeDirection: shakeDirection, delta: delta, speed: speed) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /himbo/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 | 1.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 7 23 | LSRequiresIPhoneOS 24 | 25 | NSPhotoLibraryAddUsageDescription 26 | Himbo needs access to your Photo Library to store the Wallpaper there. None of your exiting photos are being accessed. 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIStatusBarHidden 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /himbo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Colorig 4 | // 5 | // Created by Marcus Kida on 19/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /himbo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "icon-settings@2x.png", 17 | "scale" : "2x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "icon-settings@3x.png", 23 | "scale" : "3x" 24 | }, 25 | { 26 | "size" : "40x40", 27 | "idiom" : "iphone", 28 | "filename" : "icon-spotlight@2x.png", 29 | "scale" : "2x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "iphone", 34 | "filename" : "icon-spotlight@3x.png", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "size" : "60x60", 39 | "idiom" : "iphone", 40 | "filename" : "icon@2x.png", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "size" : "60x60", 45 | "idiom" : "iphone", 46 | "filename" : "icon@3x.png", 47 | "scale" : "3x" 48 | }, 49 | { 50 | "idiom" : "ipad", 51 | "size" : "20x20", 52 | "scale" : "1x" 53 | }, 54 | { 55 | "idiom" : "ipad", 56 | "size" : "20x20", 57 | "scale" : "2x" 58 | }, 59 | { 60 | "size" : "29x29", 61 | "idiom" : "ipad", 62 | "filename" : "icon-ipad-settings.png", 63 | "scale" : "1x" 64 | }, 65 | { 66 | "size" : "29x29", 67 | "idiom" : "ipad", 68 | "filename" : "icon-ipad-settings@2x.png", 69 | "scale" : "2x" 70 | }, 71 | { 72 | "size" : "40x40", 73 | "idiom" : "ipad", 74 | "filename" : "icon-ipad-spotlight.png", 75 | "scale" : "1x" 76 | }, 77 | { 78 | "size" : "40x40", 79 | "idiom" : "ipad", 80 | "filename" : "icon-ipad-spotlight@2x.png", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "size" : "76x76", 85 | "idiom" : "ipad", 86 | "filename" : "icon-ipad.png", 87 | "scale" : "1x" 88 | }, 89 | { 90 | "size" : "76x76", 91 | "idiom" : "ipad", 92 | "filename" : "icon-ipad@2x.png", 93 | "scale" : "2x" 94 | }, 95 | { 96 | "size" : "83.5x83.5", 97 | "idiom" : "ipad", 98 | "filename" : "icon-ipad-pro@2x.png", 99 | "scale" : "2x" 100 | }, 101 | { 102 | "size" : "1024x1024", 103 | "idiom" : "ios-marketing", 104 | "filename" : "appstore.png", 105 | "scale" : "1x" 106 | } 107 | ], 108 | "info" : { 109 | "version" : 1, 110 | "author" : "xcode" 111 | } 112 | } -------------------------------------------------------------------------------- /himbo/Exporter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Exporter.swift 3 | // himbo 4 | // 5 | // Created by Marcus Kida on 27/09/2015. 6 | // Copyright © 2015 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import AssetsLibrary 11 | 12 | public struct Exporter { 13 | 14 | let view: UIView 15 | let flashView: UIView 16 | 17 | init(view: UIView, flashView: UIView) { 18 | self.view = view 19 | self.flashView = flashView 20 | } 21 | 22 | func temporaryBackground() -> URL? { 23 | let image = self.renderedImage() 24 | let url = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("himbo.png") 25 | guard let imageData = UIImagePNGRepresentation(image), 26 | let aUrl = url 27 | else { 28 | return nil 29 | } 30 | try? imageData.write(to: aUrl) 31 | return aUrl 32 | } 33 | 34 | func checkAssetsAuthorization() -> Bool { 35 | let status = ALAssetsLibrary.authorizationStatus() 36 | if status == ALAuthorizationStatus.denied { 37 | self.view.shake(times: 10, direction: ShakeDirection.Horizontal) 38 | return false 39 | } 40 | return true 41 | } 42 | 43 | public func flashView(closure: @escaping () -> Void) { 44 | self.flashView.alpha = 1.0 45 | UIView.animate(withDuration: 0.3, animations: { () -> Void in 46 | self.flashView.alpha = 0.0 47 | }, completion: { (completed: Bool) -> Void in 48 | closure() 49 | }) 50 | } 51 | 52 | public func saveToLibrary() { 53 | self.flashView { () -> Void in 54 | let image = self.renderedImage() 55 | ALAssetsLibrary().writeImage(toSavedPhotosAlbum: image.cgImage, orientation: .up, completionBlock: { (url, error) in 56 | if error != nil { 57 | UIAlertView(title: "Error", message: "The Photo could not be saved.", delegate: nil, cancelButtonTitle: "OK").show() 58 | } 59 | }) 60 | } 61 | } 62 | 63 | func renderedImage() -> UIImage { 64 | let bounds = UIScreen.main.bounds 65 | let scale = UIScreen.main.scale 66 | let size = CGSize(width: bounds.width * scale, height: bounds.height * scale) 67 | let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) 68 | return self.imageWithColor(rect: rect, color: self.view.backgroundColor!) 69 | } 70 | 71 | func imageWithColor(rect: CGRect, color: UIColor) -> UIImage { 72 | UIGraphicsBeginImageContext(rect.size) 73 | let ctx = UIGraphicsGetCurrentContext() 74 | ctx!.setFillColor(color.cgColor) 75 | ctx!.fill(rect) 76 | let image = UIGraphicsGetImageFromCurrentImageContext() 77 | UIGraphicsEndImageContext() 78 | return image! 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /himbo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /himbo/PulsingLayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PulsingLayer.swift 3 | // himbo 4 | // 5 | // Created by Marcus Kida on 30/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import QuartzCore 11 | 12 | 13 | class PulsingLayer: CALayer { 14 | 15 | var radius: CGFloat { 16 | set(r) { 17 | setupRadius(radius: r) 18 | } 19 | get { 20 | return cornerRadius 21 | } 22 | } 23 | 24 | var animationDuration: TimeInterval = 10.0 25 | var pulseInterval: TimeInterval = 3.0 26 | var pulseColor: UIColor = UIColor(red: 0.0, green: 0.478, blue: 1.0, alpha: 1.0) 27 | 28 | private var animationGroup: CAAnimationGroup! 29 | 30 | override init() { 31 | super.init() 32 | 33 | self.contentsScale = UIScreen.main.scale 34 | self.opacity = 0 35 | 36 | self.radius = 60.0 37 | self.backgroundColor = pulseColor.cgColor 38 | 39 | DispatchQueue.global().async { 40 | self.setupAnimationGroup() 41 | if self.pulseInterval != Double.infinity { 42 | DispatchQueue.main.async { 43 | self.add(self.animationGroup, forKey: "pulse") 44 | } 45 | } 46 | } 47 | } 48 | 49 | convenience init(pulseColor: UIColor) { 50 | self.init() 51 | self.pulseColor = pulseColor 52 | self.backgroundColor = self.pulseColor.cgColor 53 | } 54 | 55 | required init(coder aDecoder: NSCoder) { 56 | fatalError("init(coder:) has not been implemented") 57 | } 58 | 59 | private func setupRadius(radius: CGFloat) { 60 | 61 | let tempPos = self.position 62 | let diameter = radius * 2 63 | 64 | self.bounds = CGRect(x: 0, y: 0, width: diameter, height: diameter) 65 | self.cornerRadius = radius 66 | self.position = tempPos 67 | } 68 | 69 | 70 | private func setupAnimationGroup() { 71 | let defaultCurve = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault) 72 | self.animationGroup = CAAnimationGroup() as CAAnimationGroup 73 | self.animationGroup.duration = self.animationDuration + self.pulseInterval 74 | self.animationGroup.repeatCount = Float.infinity 75 | self.animationGroup.isRemovedOnCompletion = false 76 | self.animationGroup.timingFunction = defaultCurve 77 | self.animationGroup.animations = [scaleAnimation(), opacityAnimation()] 78 | } 79 | 80 | private func scaleAnimation() -> CABasicAnimation { 81 | let scaleAnimation = CABasicAnimation(keyPath: "transform.scale.xy") 82 | scaleAnimation.fromValue = 0.0 83 | scaleAnimation.toValue = 1.0 84 | scaleAnimation.duration = self.animationDuration 85 | return scaleAnimation 86 | } 87 | 88 | private func opacityAnimation() -> CAKeyframeAnimation { 89 | let opacityAnimation = CAKeyframeAnimation(keyPath: "opacity") 90 | opacityAnimation.duration = self.animationDuration 91 | opacityAnimation.values = [0.45, 0.45, 0] 92 | opacityAnimation.keyTimes = [0, 0.2, 1] 93 | opacityAnimation.isRemovedOnCompletion = false 94 | return opacityAnimation; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /himbo/InfoView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InfoView.swift 3 | // himbo 4 | // 5 | // Created by Marcus Kida on 30/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class InfoView: UIView { 12 | 13 | private let kPadding: CGFloat = 50.0 14 | private let kInfoPadding: CGFloat = 10.0 15 | 16 | private var parentView: UIView! 17 | private var infoView: UIView! 18 | private var infoLabel: UILabel! 19 | 20 | private var onHide: (() -> Void)? 21 | private var tapGesture: UITapGestureRecognizer? 22 | 23 | private var haloLayer: PulsingLayer! 24 | 25 | // UIKitDynamics 26 | var gravity: UIGravityBehavior! 27 | var animator: UIDynamicAnimator! 28 | 29 | convenience init(text: String, parentView: UIView) { 30 | self.init(frame: parentView.frame) 31 | 32 | self.parentView = parentView 33 | 34 | self.backgroundColor = UIColor.himboRed() 35 | self.alpha = 0.0 36 | 37 | let width = parentView.frame.width - (kPadding * 2) 38 | let center = CGPoint(x: self.parentView.frame.width/2, y: self.parentView.frame.height/2) 39 | 40 | self.infoView = UIView(frame: CGRect(x: kPadding, y: kPadding, width: width, height: width)) 41 | self.infoView.backgroundColor = UIColor.white 42 | self.infoView.layer.cornerRadius = self.infoView.frame.height / 2 43 | self.infoView.center = center 44 | 45 | self.infoLabel = UILabel(frame: CGRect(x: kInfoPadding, y: kInfoPadding, width: self.infoView.frame.width - (kInfoPadding * 2), height: self.infoView.frame.height - (kInfoPadding * 2))) 46 | self.infoLabel.text = text 47 | self.infoLabel.textColor = UIColor.himboRed() 48 | self.infoLabel.numberOfLines = 0 49 | self.infoLabel.textAlignment = NSTextAlignment.center 50 | self.infoLabel.font = UIFont.boldSystemFont(ofSize: 32.0) 51 | self.infoView.addSubview(self.infoLabel) 52 | 53 | self.animator = UIDynamicAnimator(referenceView: self) 54 | self.gravity = UIGravityBehavior(items: [self.infoView]) 55 | 56 | // Halo 57 | haloLayer = PulsingLayer(pulseColor: UIColor(white: 1.0, alpha: 1.0)) 58 | haloLayer.radius = self.infoView.frame.size.width 59 | haloLayer.animationDuration = 5 60 | haloLayer.pulseInterval = 0 61 | haloLayer.position = CGPoint(x: self.infoView.frame.width/2, y: self.infoView.frame.height/2) 62 | self.infoView.layer.addSublayer(haloLayer) 63 | 64 | self.tapGesture = UITapGestureRecognizer(target: self, action: #selector(InfoView.tap(tapGestureRecognizer:))) 65 | self.addGestureRecognizer(self.tapGesture!) 66 | 67 | self.addSubview(infoView) 68 | } 69 | 70 | override init(frame: CGRect) { 71 | super.init(frame: frame) 72 | } 73 | 74 | required init?(coder aDecoder: NSCoder) { 75 | fatalError("init(coder:) has not been implemented") 76 | } 77 | 78 | func show(onHide: @escaping () -> Void) { 79 | self.onHide = onHide; 80 | self.parentView.addSubview(self) 81 | UIView.animate(withDuration: 0.3, animations: { () -> Void in 82 | self.alpha = 1.0 83 | }) 84 | } 85 | 86 | func hide() { 87 | self.animator.addBehavior(self.gravity) 88 | UIView.animate(withDuration: 0.8, animations: { () -> Void in 89 | self.alpha = 0.0 90 | }, completion: { (finished: Bool) -> Void in 91 | self.removeFromSuperview() 92 | self.onHide?(); 93 | }) 94 | } 95 | 96 | @objc func tap(tapGestureRecognizer: UITapGestureRecognizer) { 97 | self.hide() 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /himbo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Colorig 4 | // 5 | // Created by Marcus Kida on 19/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias computedValues = (hue: CGFloat, saturation: CGFloat, brightness: CGFloat) 12 | 13 | class ViewController: UIViewController, SphereMenuDelegate { 14 | 15 | @IBOutlet weak var flashView: UIView! 16 | 17 | let defaults = UserDefaults.standard 18 | 19 | var doubleTap: UITapGestureRecognizer? 20 | var lastHue: CGFloat = 0.0 21 | var lastSaturation: CGFloat = 0.0 22 | var lastBrightness: CGFloat = 1.0 23 | var lastTouchPoint: CGPoint? 24 | 25 | var infoVisible: Bool = false 26 | var tutorialRunning: Bool = false 27 | 28 | var theTutorial: Tutorial? 29 | var sphereMenu: SphereMenu? 30 | var infoView: InfoView? 31 | var exporter: Exporter? 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | exporter = Exporter(view: self.view, flashView: self.flashView) 36 | 37 | doubleTap = UITapGestureRecognizer(target: self, action: #selector(ViewController.doubleTap(gestureRecognizer:))) 38 | doubleTap!.numberOfTapsRequired = 2 39 | self.view.addGestureRecognizer(doubleTap!) 40 | 41 | let images: [UIImage] = [UIImage(named: "icon-share")!, UIImage(named: "icon-facebook")!, UIImage(named: "icon-twitter")!, UIImage(named: "icon-email")!, UIImage(named: "icon-gallery")!] 42 | sphereMenu = SphereMenu(startPoint: CGPoint(x: self.view.frame.width / 2, y: self.view.frame.height / 2), submenuImages: images) 43 | sphereMenu?.delegate = self 44 | self.view.addSubview(sphereMenu!) 45 | } 46 | 47 | override func viewDidAppear(_ animated: Bool) { 48 | super.viewDidAppear(animated) 49 | if self.defaults.bool(forKey: "tutorial_shown") { 50 | self.updateColor(vals: (hue: 0.95, saturation: 0.8, brightness: 0.9)) 51 | return; 52 | } 53 | self.showInfo(); 54 | } 55 | 56 | private func showInfo() { 57 | self.infoVisible = true 58 | self.infoView = nil; 59 | self.infoView = InfoView(text: "Start\nTutorial", parentView: self.view) 60 | self.infoView?.show(onHide: { () -> Void in 61 | self.defaults.set(true, forKey: "tutorial_shown") 62 | self.infoVisible = false 63 | self.tutorialRunning = true 64 | self.tutorial() 65 | }) 66 | } 67 | 68 | override func didReceiveMemoryWarning() { 69 | super.didReceiveMemoryWarning() 70 | // Dispose of any resources that can be recreated. 71 | } 72 | 73 | override var prefersStatusBarHidden: Bool { 74 | return true 75 | } 76 | 77 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 78 | if lastTouchPoint == nil { 79 | lastTouchPoint = touches.first?.location(in: self.view) 80 | } 81 | } 82 | 83 | override func touchesMoved(_ touches: Set, with event: UIEvent?) { 84 | if !infoVisible { 85 | updateColor(vals: colorComponents(touches: touches)) 86 | lastTouchPoint = touches.first?.location(in: self.view) 87 | } 88 | } 89 | 90 | func updateColor(vals: computedValues) { 91 | self.view.backgroundColor = UIColor(hue: vals.hue, saturation: vals.saturation, brightness: vals.brightness, alpha: 1.0) 92 | } 93 | 94 | private func colorComponents (touches: Set) -> computedValues { 95 | let touch = touches.first 96 | guard let location = touch?.location(in: self.view) else { 97 | return computedValues(0,0,0) 98 | } 99 | 100 | let viewHeight = self.view.frame.height 101 | let viewWidth = self.view.frame.width 102 | 103 | func computeAttribute () -> CGFloat { 104 | return ultimateFormula(x: viewWidth, y: location.x) 105 | } 106 | 107 | // Detect significant change in up/down movement (and set hue accordingly) 108 | if let last = lastTouchPoint { 109 | if fabs(location.y - last.y) > 5 && fabs(location.y - last.y) < 100 { 110 | lastHue = ultimateFormula(x: viewHeight, y: location.y) 111 | } 112 | } 113 | 114 | // calculate S/B 115 | var classic = true 116 | var force: CGFloat = 0.0 117 | if #available(iOS 9.0, *) { 118 | if traitCollection.forceTouchCapability == .available { 119 | classic = false 120 | force = (touches.first?.force)! 121 | } 122 | } 123 | 124 | if classic { 125 | if location.y <= viewHeight / 2 { 126 | lastSaturation = computeAttribute() 127 | } else { 128 | lastBrightness = computeAttribute() 129 | } 130 | } else { 131 | lastSaturation = computeAttribute() 132 | lastBrightness = ultimateFormula(x: viewWidth, y: force * 100) 133 | } 134 | 135 | return (lastHue, lastSaturation, lastBrightness) 136 | } 137 | 138 | private func lastComponents() -> computedValues { 139 | return (lastHue, lastSaturation, lastBrightness) 140 | } 141 | 142 | private func ultimateFormula(x: CGFloat, y: CGFloat) -> CGFloat { 143 | return (1 / x) * (x - y) 144 | } 145 | 146 | @objc func doubleTap(gestureRecognizer: UITapGestureRecognizer) { 147 | guard let exporter = exporter else { 148 | //fixme: handle non existing exporter 149 | return 150 | } 151 | exporter.flashView { () -> Void in 152 | if let url = exporter.temporaryBackground() { 153 | let activity = UIActivityViewController(activityItems: [url], applicationActivities: nil) 154 | self.present(activity, animated: true, completion: nil) 155 | } 156 | } 157 | } 158 | 159 | private func toggleMenu() { 160 | if let menu = self.sphereMenu { 161 | menu.toggle() 162 | } 163 | } 164 | 165 | private func tutorial() { 166 | theTutorial = Tutorial(view: self.view) 167 | theTutorial?.start(closure: { (hue, saturation, brightness) -> Void in 168 | self.updateColor(vals: (hue: hue, saturation: saturation, brightness: brightness)) 169 | }, menuToggle: { () -> Void in 170 | self.toggleMenu() 171 | }, finished: { () -> Void in 172 | self.tutorialRunning = false 173 | }) 174 | } 175 | 176 | func sphereDidSelected(index: Int) { 177 | if index == 4 { 178 | guard let exporter = exporter else { 179 | // fixme: handle non existing exporter 180 | return 181 | } 182 | if !exporter.checkAssetsAuthorization() { 183 | UIAlertView(title: "Error", message: "Please go into your Device's Settings and allow Album Access for himbo. This App will only save the current Wallpaper to your Albums. No Access to this or other Photos is gained.", delegate: nil, cancelButtonTitle: "OK").show() 184 | return 185 | } 186 | exporter.saveToLibrary(); 187 | } 188 | } 189 | 190 | override var canBecomeFirstResponder: Bool { 191 | return true 192 | } 193 | 194 | override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) { 195 | if let event = event, event.subtype == UIEventSubtype.motionShake { 196 | if !infoVisible && !tutorialRunning { 197 | self.showInfo() 198 | } 199 | } 200 | } 201 | } 202 | 203 | -------------------------------------------------------------------------------- /himbo/Tutorial.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tutorial.swift 3 | // himbo 4 | // 5 | // Created by Marcus Kida on 30/11/2014. 6 | // Copyright (c) 2014 Marcus Kida. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias aClosure = (_ hue: CGFloat, _ saturation: CGFloat, _ brightness: CGFloat) -> Void 12 | 13 | // fixme: make this a struct 14 | class Tutorial: NSObject { 15 | 16 | private var parentView: UIView! 17 | private var haloView: UIView! 18 | private var haloLayer: PulsingLayer! 19 | 20 | private let kMovementDuration = 1.5 21 | private let kTapDuration = 0.3 22 | 23 | private var menuToggle: (() -> Void)? 24 | private var finished: (() -> Void)? 25 | 26 | private var kHue: CGFloat = 0.0 27 | private var kSat: CGFloat = 0.0 28 | private var kBri: CGFloat = 0.0 29 | 30 | init(view: UIView) { 31 | super.init() 32 | self.parentView = view 33 | UIColor.himboRed().getHue(&kHue, saturation: &kSat, brightness: &kBri, alpha: nil) 34 | } 35 | 36 | func hasForceTouch () -> Bool { 37 | if #available(iOS 9, *) { 38 | if parentView.traitCollection.forceTouchCapability == .available { 39 | return true 40 | } 41 | } 42 | return false 43 | } 44 | 45 | func conditionalHue () -> CGFloat { 46 | if hasForceTouch() { 47 | return kHue 48 | } 49 | return 0.6 50 | } 51 | 52 | func start(closure: @escaping aClosure, menuToggle: @escaping () -> Void, finished: @escaping () -> Void) { 53 | 54 | self.menuToggle = menuToggle 55 | self.finished = finished 56 | 57 | haloLayer = PulsingLayer(pulseColor: UIColor(white: 1.0, alpha: 1.0)) 58 | haloLayer.radius = 90.0 59 | haloLayer.animationDuration = 1 60 | haloLayer.pulseInterval = 0 61 | 62 | haloView = UIView(frame: CGRect(x: 65, y: 65, width: 50, height: 50)) 63 | haloLayer.position = CGPoint(x: haloView.frame.height/2, y: haloView.frame.width/2) 64 | haloView.layer.addSublayer(haloLayer) 65 | 66 | haloView.backgroundColor = .white 67 | haloView.layer.cornerRadius = haloView.frame.height / 2 68 | 69 | parentView.addSubview(haloView) 70 | 71 | // down / up 72 | UIView.animate(withDuration: kMovementDuration, animations: { () -> Void in 73 | self.haloView.transform = CGAffineTransform(translationX: 0, y: self.parentView.frame.size.height - 130) 74 | closure(0.6, self.kSat, self.kBri) 75 | }, completion: { (finished: Bool) -> Void in 76 | if self.hasForceTouch() { 77 | return self.forceTouch(closure: closure) 78 | } 79 | self.step1(closure: closure) 80 | }) 81 | } 82 | 83 | // right 84 | func step1(closure: @escaping aClosure) { 85 | UIView.animate(withDuration: kMovementDuration, animations: { () -> Void in 86 | self.haloView.transform = CGAffineTransform(translationX: self.parentView.frame.size.width - 130, y: self.parentView.frame.size.height - 130) 87 | closure(self.conditionalHue(), self.kSat, 0.1) 88 | }, completion: { (finished: Bool) -> Void in 89 | self.step2(closure: closure) 90 | 91 | }) 92 | } 93 | 94 | // left 95 | func step2(closure: @escaping aClosure) { 96 | UIView.animate(withDuration: kMovementDuration, animations: { () -> Void in 97 | self.haloView.transform = CGAffineTransform(translationX: 0, y: self.parentView.frame.size.height - 130) 98 | closure(self.conditionalHue(), self.kSat, self.kBri) 99 | }, completion: { (finished: Bool) -> Void in 100 | self.step3(closure: closure) 101 | }) 102 | } 103 | 104 | // right (saturation) 105 | func step3(closure: @escaping aClosure) { 106 | self.haloView.transform = CGAffineTransform.identity 107 | UIView.animate(withDuration: kMovementDuration, animations: { () -> Void in 108 | self.haloView.transform = CGAffineTransform(translationX: self.parentView.frame.size.width - 130, y: 0) 109 | closure(self.conditionalHue(), 0.1, self.kBri) 110 | }, completion: { (finished: Bool) -> Void in 111 | self.step4(closure: closure) 112 | }) 113 | } 114 | 115 | // left (saturation) 116 | func step4(closure: @escaping aClosure) { 117 | UIView.animate(withDuration: kMovementDuration, animations: { () -> Void in 118 | self.haloView.transform = CGAffineTransform.identity 119 | closure(self.conditionalHue(), self.kSat, self.kBri) 120 | }, completion: { (finished: Bool) -> Void in 121 | self.step5(closure: closure) 122 | }) 123 | } 124 | 125 | func forceTouch(closure: @escaping aClosure) { 126 | UIView.animate(withDuration: kMovementDuration, animations: { () -> Void in 127 | self.haloView.transform = CGAffineTransform.identity 128 | closure(self.kHue, self.kSat, self.kBri) 129 | }, completion: { (finished: Bool) -> Void in 130 | UIView.animate(withDuration: self.kMovementDuration, animations: { () -> Void in 131 | self.haloView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) 132 | closure(self.kHue, self.kSat, 0.1) 133 | }, completion: { (finished: Bool) -> Void in 134 | UIView.animate(withDuration: self.kMovementDuration, animations: { () -> Void in 135 | self.haloView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) 136 | closure(self.kHue, self.kSat, self.kBri) 137 | }, completion: { (finished: Bool) -> Void in 138 | self.step3(closure: closure) 139 | }) 140 | }) 141 | 142 | }) 143 | } 144 | 145 | // Move to center and do double tap 146 | func step5(closure: @escaping aClosure) { 147 | self.haloView.center = CGPoint(x: self.parentView.frame.width / 2, y: self.parentView.frame.height / 2) 148 | UIView.animate(withDuration: kMovementDuration) { 149 | self.stepTap(closure: closure, done: { step2 in 150 | self.stepTap(closure: step2, done: { step3 in 151 | self.step7(closure: step3) 152 | }) 153 | }) 154 | } 155 | } 156 | 157 | // Tap 158 | func stepTap(closure: @escaping aClosure, done: @escaping (_ doneClosure: @escaping aClosure) -> Void) { 159 | UIView.animate(withDuration: kTapDuration, animations: { () -> Void in 160 | self.haloView.transform = CGAffineTransform(scaleX: 2.0, y: 2.0) 161 | }, completion: { (finished: Bool) -> Void in 162 | UIView.animate(withDuration: self.kTapDuration, animations: { () -> Void in 163 | self.haloView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) 164 | }, completion: { (finished: Bool) -> Void in 165 | done(closure) 166 | }) 167 | }) 168 | } 169 | 170 | func step7(closure: @escaping aClosure) { 171 | self.menuToggle?() 172 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.5) { 173 | self.stepTap(closure: closure, done: { (doneClosure) -> Void in 174 | self.stepTap(closure: closure, done: { (doneClosure) -> Void in 175 | self.step8(closure: closure) 176 | }) 177 | }) 178 | } 179 | } 180 | 181 | func step8(closure: aClosure) { 182 | self.menuToggle?() 183 | self.step9(closure: closure) 184 | } 185 | 186 | // Remove haloView, end Tutorial 187 | func step9(closure: aClosure) { 188 | self.haloView.removeFromSuperview() 189 | self.finished?() 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /himbo/SphereMenu.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SphereMenu.swift 3 | // Sphere Menu 4 | // 5 | // Created by Camilo Morales on 10/21/14. 6 | // Copyright (c) 2014 Camilo Morales. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | @objc protocol SphereMenuDelegate{ 13 | func sphereDidSelected(index:Int) 14 | @objc optional func sphereDidOpen() 15 | @objc optional func sphereDidClose() 16 | } 17 | 18 | // fixme: make this a struct 19 | class SphereMenu:UIView, UICollisionBehaviorDelegate{ 20 | 21 | 22 | let kItemInitTag:Int = 1001 23 | let kAngleOffset:CGFloat = CGFloat(Double.pi / 2) / 2.0 24 | let kSphereLength:CGFloat = 80 25 | let kSphereDamping:Float = 1.0 26 | 27 | var delegate:SphereMenuDelegate? 28 | var count:Int = 0 29 | var images:Array? 30 | var items:Array? 31 | var positions:Array? 32 | 33 | // animator and behaviors 34 | var animator:UIDynamicAnimator? 35 | var collision:UICollisionBehavior? 36 | var itemBehavior:UIDynamicItemBehavior? 37 | var snaps:Array? 38 | 39 | var bumper:UIDynamicItem? 40 | var expanded:Bool? 41 | 42 | required init(startPoint:CGPoint, submenuImages:Array){ 43 | self.init() 44 | self.images = submenuImages; 45 | self.count = self.images!.count; 46 | self.center = startPoint; 47 | } 48 | 49 | required init?(coder aDecoder: NSCoder) { 50 | self.count = 0; 51 | self.images = Array() 52 | self.init() 53 | } 54 | 55 | required override init(frame: CGRect) { 56 | self.count = 0; 57 | self.images = Array() 58 | super.init(frame: frame) 59 | } 60 | 61 | override func didMoveToSuperview() { 62 | self.commonSetup() 63 | } 64 | 65 | 66 | func commonSetup() 67 | { 68 | self.items = Array() 69 | self.positions = Array() 70 | self.snaps = Array() 71 | 72 | guard let images = images else { return } 73 | 74 | var i = 0 75 | // setup the items 76 | for image in images { 77 | let item = UIImageView(image: image) 78 | item.tag = kItemInitTag + i; 79 | item.isUserInteractionEnabled = true; 80 | self.superview?.addSubview(item) 81 | 82 | let position = self.centerForSphereAtIndex(index: i) 83 | item.center = self.center; 84 | self.positions?.append(NSValue(cgPoint: position)) 85 | 86 | let tap = UITapGestureRecognizer(target: self, action: #selector(SphereMenu.tapped(gesture:))) 87 | item.addGestureRecognizer(tap) 88 | 89 | // let pan = UIPanGestureRecognizer(target: self, action: "panned:") 90 | // item.addGestureRecognizer(pan) 91 | 92 | item.alpha = 0.0 93 | self.items?.append(item) 94 | i += 1 95 | } 96 | 97 | self.superview?.bringSubview(toFront: self) 98 | 99 | // setup animator and behavior 100 | self.animator = UIDynamicAnimator(referenceView: self.superview!) 101 | self.collision = UICollisionBehavior(items: self.items!) 102 | self.collision?.translatesReferenceBoundsIntoBoundary = true; 103 | self.collision?.collisionDelegate = self; 104 | 105 | guard let items = items else { return } 106 | for item in items { 107 | let snap = UISnapBehavior(item: item, snapTo: self.center) 108 | snap.damping = CGFloat(kSphereDamping) 109 | self.snaps?.append(snap) 110 | } 111 | 112 | self.itemBehavior = UIDynamicItemBehavior(items: self.items!) 113 | self.itemBehavior?.allowsRotation = false; 114 | self.itemBehavior?.elasticity = 0.25; 115 | self.itemBehavior?.density = 0.5; 116 | self.itemBehavior?.angularResistance = 4; 117 | self.itemBehavior?.resistance = 10; 118 | self.itemBehavior?.elasticity = 0.8; 119 | self.itemBehavior?.friction = 0.5; 120 | } 121 | 122 | func centerForSphereAtIndex(index:Int) -> CGPoint{ 123 | let firstAngle:CGFloat = CGFloat(Double.pi) /*+ (CGFloat(M_PI_2) - kAngleOffset)*/ + CGFloat(index) * kAngleOffset 124 | let startPoint = self.center 125 | let x = startPoint.x + cos(firstAngle) * kSphereLength; 126 | let y = startPoint.y + sin(firstAngle) * kSphereLength; 127 | let position = CGPoint(x: x, y: y); 128 | return position; 129 | } 130 | 131 | func startTapped(gesture:UITapGestureRecognizer){ 132 | self.animator?.removeBehavior(self.collision!) 133 | self.animator?.removeBehavior(self.itemBehavior!) 134 | toggle() 135 | } 136 | 137 | func toggle() { 138 | if (self.expanded == true) { 139 | self.shrinkSubmenu() 140 | self.delegate?.sphereDidClose?() 141 | } else { 142 | self.expandSubmenu() 143 | self.delegate?.sphereDidOpen?() 144 | } 145 | } 146 | 147 | @objc func tapped(gesture:UITapGestureRecognizer) 148 | { 149 | var tag = gesture.view?.tag 150 | tag? -= Int(kItemInitTag) 151 | self.delegate?.sphereDidSelected(index: tag!) 152 | self.shrinkSubmenu() 153 | } 154 | 155 | func panned(gesture:UIPanGestureRecognizer) 156 | { 157 | let touchedView = gesture.view; 158 | if (gesture.state == UIGestureRecognizerState.began) { 159 | self.animator?.removeBehavior(self.itemBehavior!) 160 | self.animator?.removeBehavior(self.collision!) 161 | self.removeSnapBehaviors() 162 | } else if (gesture.state == UIGestureRecognizerState.changed) { 163 | touchedView?.center = gesture.location(in: self.superview) 164 | } else if (gesture.state == UIGestureRecognizerState.ended) { 165 | self.bumper = touchedView; 166 | self.animator?.addBehavior(self.collision!) 167 | let index = self.indexOfItemInArray(dataArray: self.items!, item: touchedView!) 168 | 169 | if (index >= 0) { 170 | self.snapToPostionsWithIndex(index: index) 171 | } 172 | 173 | } 174 | } 175 | 176 | func indexOfItemInArray(dataArray:Array, item:AnyObject) -> Int{ 177 | var index = -1 178 | var i = 0 179 | for thing in dataArray { 180 | if thing === item { 181 | index = i 182 | break 183 | } 184 | i += 1 185 | } 186 | return index 187 | } 188 | 189 | func shrinkSubmenu(){ 190 | self.animator?.removeBehavior(self.collision!) 191 | 192 | for index in 0.. Void in 210 | item.alpha = 0.0 211 | }) 212 | let snap = UISnapBehavior(item: item, snapTo: self.center) 213 | snap.damping = CGFloat(kSphereDamping) 214 | let snapToRemove = self.snaps![index]; 215 | self.snaps![index] = snap; 216 | self.animator?.removeBehavior(snapToRemove) 217 | self.animator?.addBehavior(snap) 218 | } 219 | 220 | func snapToPostionsWithIndex(index:Int) 221 | { 222 | let positionValue:AnyObject = self.positions![index]; 223 | let position = positionValue.cgPointValue 224 | let item = self.items![index] 225 | UIView.animate(withDuration: 0.3, animations: { () -> Void in 226 | item.alpha = 1.0 227 | }) 228 | let snap = UISnapBehavior(item: item, snapTo: position!) 229 | snap.damping = CGFloat(kSphereDamping) 230 | let snapToRemove = self.snaps![index]; 231 | self.snaps![index] = snap; 232 | self.animator?.removeBehavior(snapToRemove) 233 | self.animator?.addBehavior(snap) 234 | } 235 | 236 | func removeSnapBehaviors() 237 | { 238 | for index in 0...self.snaps!.count { 239 | self.animator?.removeBehavior(self.snaps![index]) 240 | } 241 | } 242 | 243 | func collisionBehavior(_ behavior: UICollisionBehavior, endedContactFor item1: UIDynamicItem, with item2: UIDynamicItem) { 244 | self.animator?.addBehavior(self.itemBehavior!) 245 | 246 | if (item1 !== self.bumper){ 247 | let index = self.indexOfItemInArray(dataArray: self.items!, item: item1) 248 | if (index >= 0) { 249 | self.snapToPostionsWithIndex(index: index) 250 | } 251 | } 252 | 253 | if (item2 !== self.bumper){ 254 | let index = self.indexOfItemInArray(dataArray: self.items!, item: item2) 255 | if (index >= 0) { 256 | self.snapToPostionsWithIndex(index: index) 257 | } 258 | } 259 | } 260 | 261 | } 262 | 263 | -------------------------------------------------------------------------------- /himbo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2A589C9F1BB793C50051FFF3 /* Exporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A589C9E1BB793C50051FFF3 /* Exporter.swift */; }; 11 | EC3F24CE1A2AAA9000C58377 /* PulsingLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3F24CD1A2AAA9000C58377 /* PulsingLayer.swift */; }; 12 | EC3F24D01A2AB78E00C58377 /* Tutorial.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3F24CF1A2AB78E00C58377 /* Tutorial.swift */; }; 13 | EC3F24D21A2ABF6600C58377 /* SphereMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3F24D11A2ABF6600C58377 /* SphereMenu.swift */; }; 14 | EC3F24D41A2AEC1900C58377 /* InfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3F24D31A2AEC1900C58377 /* InfoView.swift */; }; 15 | EC3F24D61A2B125700C58377 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3F24D51A2B125700C58377 /* Colors.swift */; }; 16 | EC6165521A295B9800658455 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC6165511A295B9800658455 /* AssetsLibrary.framework */; }; 17 | EC61658A1A29B76B00658455 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6165821A29B76B00658455 /* AppDelegate.swift */; }; 18 | EC61658B1A29B76B00658455 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC6165831A29B76B00658455 /* LaunchScreen.xib */; }; 19 | EC61658C1A29B76B00658455 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC6165851A29B76B00658455 /* Main.storyboard */; }; 20 | EC61658D1A29B76B00658455 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC6165871A29B76B00658455 /* Images.xcassets */; }; 21 | EC61658F1A29B76B00658455 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6165891A29B76B00658455 /* ViewController.swift */; }; 22 | EC6165931A29B77000658455 /* ColorigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6165911A29B77000658455 /* ColorigTests.swift */; }; 23 | EC6165961A29BA6400658455 /* ShakeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6165951A29BA6400658455 /* ShakeView.swift */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | EC1AEC791A1C6B4A00D1FA48 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = EC1AEC5B1A1C6B4A00D1FA48 /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = EC1AEC621A1C6B4A00D1FA48; 32 | remoteInfo = Colorig; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 07EC7E731FD89578005F40DA /* himbo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = himbo.entitlements; sourceTree = ""; }; 38 | 0E981CFA1105CA64BCEAE9CD /* Pods-himbo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-himbo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-himbo/Pods-himbo.debug.xcconfig"; sourceTree = ""; }; 39 | 2A589C9E1BB793C50051FFF3 /* Exporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Exporter.swift; sourceTree = ""; }; 40 | 49FD340327310FF0989AD5A9 /* Pods-himbo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-himbo.release.xcconfig"; path = "Pods/Target Support Files/Pods-himbo/Pods-himbo.release.xcconfig"; sourceTree = ""; }; 41 | DF2C223F57198A8D1A0C9A34 /* libPods-himbo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-himbo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | EC1AEC631A1C6B4A00D1FA48 /* himbo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = himbo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | EC1AEC781A1C6B4A00D1FA48 /* himboTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = himboTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | EC3F24CD1A2AAA9000C58377 /* PulsingLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PulsingLayer.swift; sourceTree = ""; }; 45 | EC3F24CF1A2AB78E00C58377 /* Tutorial.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tutorial.swift; sourceTree = ""; }; 46 | EC3F24D11A2ABF6600C58377 /* SphereMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SphereMenu.swift; sourceTree = ""; }; 47 | EC3F24D31A2AEC1900C58377 /* InfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InfoView.swift; sourceTree = ""; }; 48 | EC3F24D51A2B125700C58377 /* Colors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; 49 | EC6165511A295B9800658455 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; 50 | EC6165821A29B76B00658455 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 51 | EC6165841A29B76B00658455 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 52 | EC6165861A29B76B00658455 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | EC6165871A29B76B00658455 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 54 | EC6165881A29B76B00658455 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | EC6165891A29B76B00658455 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 56 | EC6165911A29B77000658455 /* ColorigTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorigTests.swift; sourceTree = ""; }; 57 | EC6165921A29B77000658455 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | EC6165951A29BA6400658455 /* ShakeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShakeView.swift; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | EC1AEC601A1C6B4A00D1FA48 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | EC6165521A295B9800658455 /* AssetsLibrary.framework in Frameworks */, 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | EC1AEC751A1C6B4A00D1FA48 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | /* End PBXFrameworksBuildPhase section */ 78 | 79 | /* Begin PBXGroup section */ 80 | 11FEA6B53EAB55CDDDED51AD /* Pods */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 0E981CFA1105CA64BCEAE9CD /* Pods-himbo.debug.xcconfig */, 84 | 49FD340327310FF0989AD5A9 /* Pods-himbo.release.xcconfig */, 85 | ); 86 | name = Pods; 87 | sourceTree = ""; 88 | }; 89 | 16326F37C70C58EECAE3587F /* Frameworks */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | EC6165511A295B9800658455 /* AssetsLibrary.framework */, 93 | DF2C223F57198A8D1A0C9A34 /* libPods-himbo.a */, 94 | ); 95 | name = Frameworks; 96 | sourceTree = ""; 97 | }; 98 | EC1AEC5A1A1C6B4A00D1FA48 = { 99 | isa = PBXGroup; 100 | children = ( 101 | EC6165811A29B76B00658455 /* himbo */, 102 | EC6165901A29B77000658455 /* himboTests */, 103 | EC1AEC641A1C6B4A00D1FA48 /* Products */, 104 | 11FEA6B53EAB55CDDDED51AD /* Pods */, 105 | 16326F37C70C58EECAE3587F /* Frameworks */, 106 | ); 107 | sourceTree = ""; 108 | }; 109 | EC1AEC641A1C6B4A00D1FA48 /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | EC1AEC631A1C6B4A00D1FA48 /* himbo.app */, 113 | EC1AEC781A1C6B4A00D1FA48 /* himboTests.xctest */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | EC6165811A29B76B00658455 /* himbo */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 07EC7E731FD89578005F40DA /* himbo.entitlements */, 122 | EC6165821A29B76B00658455 /* AppDelegate.swift */, 123 | EC6165891A29B76B00658455 /* ViewController.swift */, 124 | 2A589C9E1BB793C50051FFF3 /* Exporter.swift */, 125 | EC3F24CF1A2AB78E00C58377 /* Tutorial.swift */, 126 | EC6165951A29BA6400658455 /* ShakeView.swift */, 127 | EC3F24D11A2ABF6600C58377 /* SphereMenu.swift */, 128 | EC3F24CD1A2AAA9000C58377 /* PulsingLayer.swift */, 129 | EC3F24D31A2AEC1900C58377 /* InfoView.swift */, 130 | EC3F24D51A2B125700C58377 /* Colors.swift */, 131 | EC6165831A29B76B00658455 /* LaunchScreen.xib */, 132 | EC6165851A29B76B00658455 /* Main.storyboard */, 133 | EC6165871A29B76B00658455 /* Images.xcassets */, 134 | EC6165881A29B76B00658455 /* Info.plist */, 135 | ); 136 | path = himbo; 137 | sourceTree = ""; 138 | }; 139 | EC6165901A29B77000658455 /* himboTests */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | EC6165911A29B77000658455 /* ColorigTests.swift */, 143 | EC6165921A29B77000658455 /* Info.plist */, 144 | ); 145 | path = himboTests; 146 | sourceTree = ""; 147 | }; 148 | /* End PBXGroup section */ 149 | 150 | /* Begin PBXNativeTarget section */ 151 | EC1AEC621A1C6B4A00D1FA48 /* himbo */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = EC1AEC821A1C6B4A00D1FA48 /* Build configuration list for PBXNativeTarget "himbo" */; 154 | buildPhases = ( 155 | EC1AEC5F1A1C6B4A00D1FA48 /* Sources */, 156 | 07CB32C21FD8985A001647EE /* Bump Build Number */, 157 | EC1AEC601A1C6B4A00D1FA48 /* Frameworks */, 158 | EC1AEC611A1C6B4A00D1FA48 /* Resources */, 159 | ); 160 | buildRules = ( 161 | ); 162 | dependencies = ( 163 | ); 164 | name = himbo; 165 | productName = Colorig; 166 | productReference = EC1AEC631A1C6B4A00D1FA48 /* himbo.app */; 167 | productType = "com.apple.product-type.application"; 168 | }; 169 | EC1AEC771A1C6B4A00D1FA48 /* himboTests */ = { 170 | isa = PBXNativeTarget; 171 | buildConfigurationList = EC1AEC851A1C6B4A00D1FA48 /* Build configuration list for PBXNativeTarget "himboTests" */; 172 | buildPhases = ( 173 | EC1AEC741A1C6B4A00D1FA48 /* Sources */, 174 | EC1AEC751A1C6B4A00D1FA48 /* Frameworks */, 175 | EC1AEC761A1C6B4A00D1FA48 /* Resources */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | EC1AEC7A1A1C6B4A00D1FA48 /* PBXTargetDependency */, 181 | ); 182 | name = himboTests; 183 | productName = ColorigTests; 184 | productReference = EC1AEC781A1C6B4A00D1FA48 /* himboTests.xctest */; 185 | productType = "com.apple.product-type.bundle.unit-test"; 186 | }; 187 | /* End PBXNativeTarget section */ 188 | 189 | /* Begin PBXProject section */ 190 | EC1AEC5B1A1C6B4A00D1FA48 /* Project object */ = { 191 | isa = PBXProject; 192 | attributes = { 193 | LastSwiftMigration = 0700; 194 | LastSwiftUpdateCheck = 0700; 195 | LastUpgradeCheck = 0920; 196 | ORGANIZATIONNAME = "Marcus Kida"; 197 | TargetAttributes = { 198 | EC1AEC621A1C6B4A00D1FA48 = { 199 | CreatedOnToolsVersion = 6.1; 200 | DevelopmentTeam = 857XYUU5FE; 201 | SystemCapabilities = { 202 | com.apple.iCloud = { 203 | enabled = 0; 204 | }; 205 | }; 206 | }; 207 | EC1AEC771A1C6B4A00D1FA48 = { 208 | CreatedOnToolsVersion = 6.1; 209 | DevelopmentTeam = 857XYUU5FE; 210 | TestTargetID = EC1AEC621A1C6B4A00D1FA48; 211 | }; 212 | }; 213 | }; 214 | buildConfigurationList = EC1AEC5E1A1C6B4A00D1FA48 /* Build configuration list for PBXProject "himbo" */; 215 | compatibilityVersion = "Xcode 3.2"; 216 | developmentRegion = English; 217 | hasScannedForEncodings = 0; 218 | knownRegions = ( 219 | en, 220 | Base, 221 | ); 222 | mainGroup = EC1AEC5A1A1C6B4A00D1FA48; 223 | productRefGroup = EC1AEC641A1C6B4A00D1FA48 /* Products */; 224 | projectDirPath = ""; 225 | projectRoot = ""; 226 | targets = ( 227 | EC1AEC621A1C6B4A00D1FA48 /* himbo */, 228 | EC1AEC771A1C6B4A00D1FA48 /* himboTests */, 229 | ); 230 | }; 231 | /* End PBXProject section */ 232 | 233 | /* Begin PBXResourcesBuildPhase section */ 234 | EC1AEC611A1C6B4A00D1FA48 /* Resources */ = { 235 | isa = PBXResourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | EC61658D1A29B76B00658455 /* Images.xcassets in Resources */, 239 | EC61658B1A29B76B00658455 /* LaunchScreen.xib in Resources */, 240 | EC61658C1A29B76B00658455 /* Main.storyboard in Resources */, 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | EC1AEC761A1C6B4A00D1FA48 /* Resources */ = { 245 | isa = PBXResourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXResourcesBuildPhase section */ 252 | 253 | /* Begin PBXShellScriptBuildPhase section */ 254 | 07CB32C21FD8985A001647EE /* Bump Build Number */ = { 255 | isa = PBXShellScriptBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | ); 259 | inputPaths = ( 260 | ); 261 | name = "Bump Build Number"; 262 | outputPaths = ( 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | shellPath = /bin/sh; 266 | shellScript = "if [ $CONFIGURATION == Release ] || [ $CONFIGURATION == TestFlight ]; then\n echo \"Bumping build number...\"\n plist=${PROJECT_DIR}/${INFOPLIST_FILE}\n\n # increment the build number (ie 115 to 116)\n buildnum=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"${plist}\")\n if [[ \"${buildnum}\" == \"\" ]]; then\n echo \"No build number in $plist\"\n exit 2\n fi\n\n buildnum=$(expr $buildnum + 1)\n /usr/libexec/Plistbuddy -c \"Set CFBundleVersion $buildnum\" \"${plist}\"\n echo \"Bumped build number to $buildnum\"\nelse\n echo $CONFIGURATION \" build - Not bumping build number.\"\nfi"; 267 | }; 268 | /* End PBXShellScriptBuildPhase section */ 269 | 270 | /* Begin PBXSourcesBuildPhase section */ 271 | EC1AEC5F1A1C6B4A00D1FA48 /* Sources */ = { 272 | isa = PBXSourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | EC3F24CE1A2AAA9000C58377 /* PulsingLayer.swift in Sources */, 276 | 2A589C9F1BB793C50051FFF3 /* Exporter.swift in Sources */, 277 | EC3F24D61A2B125700C58377 /* Colors.swift in Sources */, 278 | EC61658F1A29B76B00658455 /* ViewController.swift in Sources */, 279 | EC61658A1A29B76B00658455 /* AppDelegate.swift in Sources */, 280 | EC6165961A29BA6400658455 /* ShakeView.swift in Sources */, 281 | EC3F24D01A2AB78E00C58377 /* Tutorial.swift in Sources */, 282 | EC3F24D21A2ABF6600C58377 /* SphereMenu.swift in Sources */, 283 | EC3F24D41A2AEC1900C58377 /* InfoView.swift in Sources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | EC1AEC741A1C6B4A00D1FA48 /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | EC6165931A29B77000658455 /* ColorigTests.swift in Sources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | /* End PBXSourcesBuildPhase section */ 296 | 297 | /* Begin PBXTargetDependency section */ 298 | EC1AEC7A1A1C6B4A00D1FA48 /* PBXTargetDependency */ = { 299 | isa = PBXTargetDependency; 300 | target = EC1AEC621A1C6B4A00D1FA48 /* himbo */; 301 | targetProxy = EC1AEC791A1C6B4A00D1FA48 /* PBXContainerItemProxy */; 302 | }; 303 | /* End PBXTargetDependency section */ 304 | 305 | /* Begin PBXVariantGroup section */ 306 | EC6165831A29B76B00658455 /* LaunchScreen.xib */ = { 307 | isa = PBXVariantGroup; 308 | children = ( 309 | EC6165841A29B76B00658455 /* Base */, 310 | ); 311 | name = LaunchScreen.xib; 312 | sourceTree = ""; 313 | }; 314 | EC6165851A29B76B00658455 /* Main.storyboard */ = { 315 | isa = PBXVariantGroup; 316 | children = ( 317 | EC6165861A29B76B00658455 /* Base */, 318 | ); 319 | name = Main.storyboard; 320 | sourceTree = ""; 321 | }; 322 | /* End PBXVariantGroup section */ 323 | 324 | /* Begin XCBuildConfiguration section */ 325 | EC1AEC801A1C6B4A00D1FA48 /* Debug */ = { 326 | isa = XCBuildConfiguration; 327 | buildSettings = { 328 | ALWAYS_SEARCH_USER_PATHS = NO; 329 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 330 | CLANG_CXX_LIBRARY = "libc++"; 331 | CLANG_ENABLE_MODULES = YES; 332 | CLANG_ENABLE_OBJC_ARC = YES; 333 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 334 | CLANG_WARN_BOOL_CONVERSION = YES; 335 | CLANG_WARN_COMMA = YES; 336 | CLANG_WARN_CONSTANT_CONVERSION = YES; 337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 338 | CLANG_WARN_EMPTY_BODY = YES; 339 | CLANG_WARN_ENUM_CONVERSION = YES; 340 | CLANG_WARN_INFINITE_RECURSION = YES; 341 | CLANG_WARN_INT_CONVERSION = YES; 342 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 343 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 344 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 345 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 346 | CLANG_WARN_STRICT_PROTOTYPES = YES; 347 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 348 | CLANG_WARN_UNREACHABLE_CODE = YES; 349 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 350 | CODE_SIGN_IDENTITY = "iPhone Developer"; 351 | COPY_PHASE_STRIP = NO; 352 | DEVELOPMENT_TEAM = 857XYUU5FE; 353 | ENABLE_STRICT_OBJC_MSGSEND = YES; 354 | ENABLE_TESTABILITY = YES; 355 | GCC_C_LANGUAGE_STANDARD = gnu99; 356 | GCC_DYNAMIC_NO_PIC = NO; 357 | GCC_NO_COMMON_BLOCKS = YES; 358 | GCC_OPTIMIZATION_LEVEL = 0; 359 | GCC_PREPROCESSOR_DEFINITIONS = ( 360 | "DEBUG=1", 361 | "$(inherited)", 362 | ); 363 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 365 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 366 | GCC_WARN_UNDECLARED_SELECTOR = YES; 367 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 368 | GCC_WARN_UNUSED_FUNCTION = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | MTL_ENABLE_DEBUG_INFO = YES; 371 | ONLY_ACTIVE_ARCH = YES; 372 | SDKROOT = iphoneos; 373 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 374 | SWIFT_VERSION = 4.0; 375 | TARGETED_DEVICE_FAMILY = "1,2"; 376 | }; 377 | name = Debug; 378 | }; 379 | EC1AEC811A1C6B4A00D1FA48 /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ALWAYS_SEARCH_USER_PATHS = NO; 383 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 384 | CLANG_CXX_LIBRARY = "libc++"; 385 | CLANG_ENABLE_MODULES = YES; 386 | CLANG_ENABLE_OBJC_ARC = YES; 387 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 388 | CLANG_WARN_BOOL_CONVERSION = YES; 389 | CLANG_WARN_COMMA = YES; 390 | CLANG_WARN_CONSTANT_CONVERSION = YES; 391 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 392 | CLANG_WARN_EMPTY_BODY = YES; 393 | CLANG_WARN_ENUM_CONVERSION = YES; 394 | CLANG_WARN_INFINITE_RECURSION = YES; 395 | CLANG_WARN_INT_CONVERSION = YES; 396 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 400 | CLANG_WARN_STRICT_PROTOTYPES = YES; 401 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 402 | CLANG_WARN_UNREACHABLE_CODE = YES; 403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 404 | CODE_SIGN_IDENTITY = "iPhone Developer"; 405 | COPY_PHASE_STRIP = YES; 406 | DEVELOPMENT_TEAM = 857XYUU5FE; 407 | ENABLE_NS_ASSERTIONS = NO; 408 | ENABLE_STRICT_OBJC_MSGSEND = YES; 409 | GCC_C_LANGUAGE_STANDARD = gnu99; 410 | GCC_NO_COMMON_BLOCKS = YES; 411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 413 | GCC_WARN_UNDECLARED_SELECTOR = YES; 414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 415 | GCC_WARN_UNUSED_FUNCTION = YES; 416 | GCC_WARN_UNUSED_VARIABLE = YES; 417 | MTL_ENABLE_DEBUG_INFO = NO; 418 | SDKROOT = iphoneos; 419 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 420 | SWIFT_VERSION = 4.0; 421 | TARGETED_DEVICE_FAMILY = "1,2"; 422 | VALIDATE_PRODUCT = YES; 423 | }; 424 | name = Release; 425 | }; 426 | EC1AEC831A1C6B4A00D1FA48 /* Debug */ = { 427 | isa = XCBuildConfiguration; 428 | buildSettings = { 429 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 430 | DEVELOPMENT_TEAM = 857XYUU5FE; 431 | INFOPLIST_FILE = himbo/Info.plist; 432 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 433 | PRODUCT_BUNDLE_IDENTIFIER = "io.kida.$(PRODUCT_NAME:rfc1034identifier)"; 434 | PRODUCT_NAME = himbo; 435 | }; 436 | name = Debug; 437 | }; 438 | EC1AEC841A1C6B4A00D1FA48 /* Release */ = { 439 | isa = XCBuildConfiguration; 440 | buildSettings = { 441 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 442 | DEVELOPMENT_TEAM = 857XYUU5FE; 443 | INFOPLIST_FILE = himbo/Info.plist; 444 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 445 | PRODUCT_BUNDLE_IDENTIFIER = "io.kida.$(PRODUCT_NAME:rfc1034identifier)"; 446 | PRODUCT_NAME = himbo; 447 | }; 448 | name = Release; 449 | }; 450 | EC1AEC861A1C6B4A00D1FA48 /* Debug */ = { 451 | isa = XCBuildConfiguration; 452 | buildSettings = { 453 | FRAMEWORK_SEARCH_PATHS = ( 454 | "$(SDKROOT)/Developer/Library/Frameworks", 455 | "$(inherited)", 456 | ); 457 | GCC_PREPROCESSOR_DEFINITIONS = ( 458 | "DEBUG=1", 459 | "$(inherited)", 460 | ); 461 | INFOPLIST_FILE = himboTests/Info.plist; 462 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 463 | PRODUCT_BUNDLE_IDENTIFIER = "io.kida.$(PRODUCT_NAME:rfc1034identifier)"; 464 | PRODUCT_NAME = himboTests; 465 | }; 466 | name = Debug; 467 | }; 468 | EC1AEC871A1C6B4A00D1FA48 /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | FRAMEWORK_SEARCH_PATHS = ( 472 | "$(SDKROOT)/Developer/Library/Frameworks", 473 | "$(inherited)", 474 | ); 475 | INFOPLIST_FILE = himboTests/Info.plist; 476 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 477 | PRODUCT_BUNDLE_IDENTIFIER = "io.kida.$(PRODUCT_NAME:rfc1034identifier)"; 478 | PRODUCT_NAME = himboTests; 479 | }; 480 | name = Release; 481 | }; 482 | /* End XCBuildConfiguration section */ 483 | 484 | /* Begin XCConfigurationList section */ 485 | EC1AEC5E1A1C6B4A00D1FA48 /* Build configuration list for PBXProject "himbo" */ = { 486 | isa = XCConfigurationList; 487 | buildConfigurations = ( 488 | EC1AEC801A1C6B4A00D1FA48 /* Debug */, 489 | EC1AEC811A1C6B4A00D1FA48 /* Release */, 490 | ); 491 | defaultConfigurationIsVisible = 0; 492 | defaultConfigurationName = Release; 493 | }; 494 | EC1AEC821A1C6B4A00D1FA48 /* Build configuration list for PBXNativeTarget "himbo" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | EC1AEC831A1C6B4A00D1FA48 /* Debug */, 498 | EC1AEC841A1C6B4A00D1FA48 /* Release */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | EC1AEC851A1C6B4A00D1FA48 /* Build configuration list for PBXNativeTarget "himboTests" */ = { 504 | isa = XCConfigurationList; 505 | buildConfigurations = ( 506 | EC1AEC861A1C6B4A00D1FA48 /* Debug */, 507 | EC1AEC871A1C6B4A00D1FA48 /* Release */, 508 | ); 509 | defaultConfigurationIsVisible = 0; 510 | defaultConfigurationName = Release; 511 | }; 512 | /* End XCConfigurationList section */ 513 | }; 514 | rootObject = EC1AEC5B1A1C6B4A00D1FA48 /* Project object */; 515 | } 516 | --------------------------------------------------------------------------------