├── .gitignore ├── Resources └── EliminationMenu.gif ├── EliminationMenu ├── Assets.xcassets │ ├── Contents.json │ ├── disk.imageset │ │ ├── disk.pdf │ │ └── Contents.json │ ├── check.imageset │ │ ├── check.pdf │ │ └── Contents.json │ ├── heart.imageset │ │ ├── heart.pdf │ │ └── Contents.json │ ├── fabric.imageset │ │ ├── fabric.pdf │ │ └── Contents.json │ ├── safari.imageset │ │ ├── safari.pdf │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── MyCostomType.swift ├── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── AppDelegate.swift └── ViewController.swift ├── EliminationMenu.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ ├── EliminationMenu.xcscheme │ │ └── Example App.xcscheme └── project.pbxproj ├── .travis.yml ├── EliminationMenu.podspec ├── EliminationMenuTests ├── Info.plist └── EliminationMenuTests.swift ├── Package.swift ├── LICENSE ├── README.md └── Sources ├── EliminationMenuItem.swift └── EliminationMenu.swift /.gitignore: -------------------------------------------------------------------------------- 1 | EliminationMenu.xcodeproj/xcuserdata 2 | *xcuserdatad* 3 | .DS_Store -------------------------------------------------------------------------------- /Resources/EliminationMenu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-dent/EliminationMenu/HEAD/Resources/EliminationMenu.gif -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/disk.imageset/disk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-dent/EliminationMenu/HEAD/EliminationMenu/Assets.xcassets/disk.imageset/disk.pdf -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/check.imageset/check.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-dent/EliminationMenu/HEAD/EliminationMenu/Assets.xcassets/check.imageset/check.pdf -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/heart.imageset/heart.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-dent/EliminationMenu/HEAD/EliminationMenu/Assets.xcassets/heart.imageset/heart.pdf -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/fabric.imageset/fabric.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-dent/EliminationMenu/HEAD/EliminationMenu/Assets.xcassets/fabric.imageset/fabric.pdf -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/safari.imageset/safari.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r-dent/EliminationMenu/HEAD/EliminationMenu/Assets.xcassets/safari.imageset/safari.pdf -------------------------------------------------------------------------------- /EliminationMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/disk.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "disk.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/check.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "check.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/fabric.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "fabric.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/heart.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "heart.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /EliminationMenu/Assets.xcassets/safari.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "safari.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /EliminationMenu.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | osx_image: xcode10 4 | xcode_workspace: EliminationMenu.xcodeproj 5 | xcode_scheme: "Example App" 6 | xcode_sdk: iphonesimulator11.0 7 | 8 | script: xcodebuild build test -project EliminationMenu.xcodeproj -scheme "Example App" -destination "platform=iOS Simulator,name=iPhone 7" -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO 9 | -------------------------------------------------------------------------------- /EliminationMenu/MyCostomType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyCustomType.swift 3 | // Example App 4 | // 5 | // Created by Roman Gille on 28.09.18. 6 | // Copyright © 2018 Roman Gille. All rights reserved. 7 | // 8 | 9 | import EliminationMenu 10 | 11 | struct MyCustomType: EliminationMenuItem { 12 | 13 | var title: String { 14 | return String(describing: someOtherProperty) 15 | } 16 | 17 | var value: Any? { 18 | return customProperty 19 | } 20 | 21 | let customProperty: Bool 22 | let someOtherProperty: Int 23 | 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /EliminationMenu.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'EliminationMenu' 3 | s.version = '1.0.2' 4 | s.swift_version = '4.2' 5 | 6 | s.summary = 'A menu that eliminates all values which were not selected.' 7 | s.author = { 'Roman Gille' => 'developer@romangille.com' } 8 | s.homepage = 'https://github.com/r-dent/EliminationMenu' 9 | s.license = { :type => 'MIT', :file => 'LICENSE' } 10 | 11 | s.source = { :git => 'https://github.com/r-dent/EliminationMenu.git', :tag => "#{s.version}" } 12 | s.source_files = 'Sources/*.swift' 13 | 14 | s.requires_arc = true 15 | s.frameworks = 'UIKit' 16 | 17 | s.platform = :ios, '8.0' 18 | s.ios.deployment_target = '8' 19 | end -------------------------------------------------------------------------------- /EliminationMenuTests/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 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.2 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "EliminationMenu", 8 | products: [ 9 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 10 | .library( 11 | name: "EliminationMenu", 12 | targets: ["EliminationMenu"]), 13 | ], 14 | dependencies: [ 15 | // Dependencies declare other packages that this package depends on. 16 | // .package(url: /* package url */, from: "1.0.0"), 17 | ], 18 | targets: [ 19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 21 | .target( 22 | name: "EliminationMenu", 23 | path: "./Sources" 24 | ) 25 | ] 26 | ) 27 | -------------------------------------------------------------------------------- /EliminationMenu/Assets.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 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Roman Gille, http://romangille.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /EliminationMenu/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.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /EliminationMenu/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /EliminationMenuTests/EliminationMenuTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EliminationMenuTests.swift 3 | // EliminationMenuTests 4 | // 5 | // Created by Roman Gille on 02.09.16. 6 | // Copyright © 2016 Roman Gille. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import EliminationMenu 11 | 12 | class EliminationMenuTests: 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 testLayoutMargins() { 25 | let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() 26 | 27 | guard let view = viewController?.view else { 28 | XCTFail("Could not get view") 29 | return 30 | } 31 | 32 | 33 | let menuItems = [ 34 | EliminationMenu.Item(value: UIColor(red: 57/255, green: 61/255, blue: 66/255, alpha: 1) , title: "Gray"), 35 | EliminationMenu.Item(value: UIColor.blue, title: "Blue"), 36 | EliminationMenu.Item(value: UIColor.red, title: "Red"), 37 | EliminationMenu.Item(value: UIColor.green, title: "Green") 38 | ] 39 | 40 | let margin = CGPoint(x: 12, y: 24) 41 | 42 | let menu = EliminationMenu.createMenu( 43 | withItems: menuItems, 44 | inView: view, 45 | aligned: .topLeft, 46 | margin: margin, 47 | selection: nil 48 | ) 49 | 50 | view.layoutSubviews() 51 | 52 | XCTAssertEqual(menu.frame.origin.x, margin.x, "Margin x does not match") 53 | XCTAssertEqual(menu.frame.origin.y, margin.y, "Margin y does not match") 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /EliminationMenu/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // RGEliminationMenu 4 | // 5 | // Created by Roman Gille on 14.04.16. 6 | // Copyright © 2016 Roman Gille. 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: [UIApplication.LaunchOptionsKey: Any]?) -> 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 | -------------------------------------------------------------------------------- /EliminationMenu.xcodeproj/xcshareddata/xcschemes/EliminationMenu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EliminationMenu 2 | [![Travis](https://img.shields.io/travis/r-dent/EliminationMenu.svg)](https://travis-ci.org/r-dent/EliminationMenu) 3 | [![CocoaPods](https://img.shields.io/cocoapods/v/EliminationMenu.svg)](http://cocoadocs.org/docsets/EliminationMenu) 4 | [![CocoaPods](https://img.shields.io/cocoapods/l/EliminationMenu.svg)](LICENSE) 5 | [![Platform](https://img.shields.io/cocoapods/p/EliminationMenu.svg)](http://cocoadocs.org/docsets/EliminationMenu) 6 | 7 | Some kind of menu that eliminates all values which were not selected. 8 | 9 |

10 | 11 |

12 | 13 | ## Installation 14 | 15 | Just drag the Folder `Sources` into your project. 16 | 17 | ### Cocoapods 18 | 19 | If you´re using [CocoaPods](https://cocoapods.org), add this to your Podfile: 20 | 21 | pod EliminationMenu 22 | 23 | ### Swift Package Manager 24 | 25 | To add EliminationMenu to a [Swift Package Manager](https://swift.org/package-manager/) based project, add the following: 26 | 27 | ```swift 28 | .package(url: "https://github.com/r-dent/EliminationMenu", from: "1.0.2") 29 | ``` 30 | 31 | to the `dependencies` value of your `Package.swift`. 32 | 33 | 34 | ## Usage 35 | 36 | You can create an EliminationMenu view in Interface Builder or in code. 37 | 38 | ### Create entries 39 | 40 | To set up the entries, create an array of instances conforming to `EliminationMenuItem` and set it to the `items` property of the menu object. 41 | 42 | ```swift 43 | let menuEntries = [ 44 | EliminationMenu.Item(value: "SomeValue", title: "First"), 45 | EliminationMenu.Item(value: "SomeOtherValue", title: "Second"), 46 | EliminationMenu.Item(value: UIImage(named: "filename"), title: "Third"), // You can use values of any kind. 47 | EliminationMenu.Item(value: "...or a view", title: "Fourth"), 48 | "Just a String", 49 | MyCustomType(customProperty: true, someOtherProperty: 5) 50 | ] 51 | menu.items = menuEntries 52 | ``` 53 | 54 | *Hint*: The default type `EliminationMenu.Item` can be used to populate the menu. But you can also make your own types conform to `EliminationMenuItem` and use them directly. 55 | `String` already conforms to it. So you can use Strings as menu items. See the example project for an overview. 56 | 57 | ### Create Menu 58 | 59 | Use the convenience method to create a menu and add it as a subview to your view controllers view. 60 | 61 | ```swift 62 | let menu = EliminationMenu.createMenu(withItems: menuEntries, inView: view, aligned: .topRight, margin: CGPoint(x: 0, y: 20)) { (item) in 63 | print("Selected value: \(item.value)") 64 | } 65 | ``` 66 | 67 | If you want to use Interface Builder, just add a `UIView` and pin 2 of its edges (vertical and horizontal). Set `EliminationMenu` as the views class. Also add a width and a height constraint to supress warnings. Enable "_Remove at build time_" on the size constraints. The menu will get an intrinsic size at runtime. 68 | 69 | You can also create an instance of `EliminationMenu` and constrain it yourself in a superview. Be shure to call `menu.setup()` after all. 70 | 71 | See the [example code](EliminationMenu/ViewController.swift) for a better insight. 72 | 73 | ### Customize 74 | 75 | You can customize the properties of your menu like this: 76 | 77 | ```swift 78 | menu.font = UIFont.boldSystemFont(ofSize: 24) 79 | menu.color = UIColor.white 80 | 81 | menu.setup() 82 | ``` 83 | 84 | Be shure to call `menu.setup()` to apply your changes. See the [documentation](http://cocoadocs.org/docsets/EliminationMenu) for more ways to customize. 85 | 86 | ## License 87 | 88 | `EliminationMenu` is available under the MIT license. See the [LICENSE](LICENSE) file for more info. -------------------------------------------------------------------------------- /Sources/EliminationMenuItem.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Roman Gille, http://romangille.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining 4 | // a copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to 8 | // permit persons to whom the Software is furnished to do so, subject to 9 | // the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be 12 | // included in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | import UIKit 23 | 24 | /// Conforming objects can be used as menu items in an `EliminationMenu`. 25 | public protocol EliminationMenuItem { 26 | /// The title that will be shown in the menu. 27 | var title: String { get } 28 | /// The icon that will be shown in the menu. 29 | var icon: UIImage? { get } 30 | /// These insets will also set titleInsets and contentInsets of the items entry button. 31 | var iconInsets: UIEdgeInsets { get } 32 | /// The object that you will receive in the selectionHandler. 33 | var value: Any? { get } 34 | } 35 | 36 | /// This adds default implementations for optional methods of `EliminationMenuItem`. 37 | public extension EliminationMenuItem { 38 | /// Default implementation of icon to make it optional. 39 | var icon: UIImage? { return nil } 40 | /// Default implementation of iconInsets to make it optional. 41 | var iconInsets: UIEdgeInsets { 42 | return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 43 | } 44 | } 45 | 46 | /// Adds a default `Item` to use in `EleminationMenu`. 47 | public extension EliminationMenu { 48 | 49 | // MARK: - Class: Item 50 | 51 | // An item representing a menu entry in EliminationMenu. 52 | public class Item: EliminationMenuItem { 53 | /// The title that will be shown in the menu. 54 | open var title: String = "" 55 | /// The icon that will be shown in the menu. 56 | open var icon: UIImage? 57 | /// The object that you will receive in the selectionHandler. 58 | open var value: Any? 59 | /// These insets will also set titleInsets and contentInsets of the items entry button. 60 | open var iconInsets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 61 | 62 | /** 63 | - parameter value: The value that will be passed to the selection handler. 64 | - parameter title: An optional text that is shown as menu entry. 65 | - parameter icon: An optional image. Shown before the title in the menu entry. 66 | */ 67 | public init(value:Any, title: String = "", icon: UIImage? = nil) { 68 | self.title = title 69 | self.value = value 70 | self.icon = icon 71 | } 72 | } 73 | 74 | } 75 | 76 | /// Add capability to use `String` as item in `EleminationMenu`. 77 | extension String: EliminationMenuItem { 78 | public var title: String { 79 | return self 80 | } 81 | 82 | public var value: Any? { 83 | return self 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /EliminationMenu.xcodeproj/xcshareddata/xcschemes/Example App.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /EliminationMenu/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 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /EliminationMenu/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // EliminationMenu 4 | // 5 | // Created by Roman Gille on 14.04.16. 6 | // Copyright © 2016 Roman Gille. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import EliminationMenu 11 | 12 | class ViewController: UIViewController { 13 | 14 | @IBOutlet weak var eliminationMenu: EliminationMenu! 15 | @IBOutlet weak var infoLabel: UILabel! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | /** 21 | Set up the menu created in interface builder. 22 | */ 23 | 24 | eliminationMenu.font = .boldSystemFont(ofSize: 24) 25 | eliminationMenu.color = .white 26 | 27 | eliminationMenu.selectionHandler = { item in 28 | self.infoLabel.text = "Selected item:\n\"\(item.title)\"" 29 | if let value = item.value { 30 | self.infoLabel.text?.append( "\n\nThe value is:\n\"\(value)\"" ) 31 | } 32 | } 33 | 34 | eliminationMenu.items = [ 35 | EliminationMenu.Item(value: "SomeValue", title: "First"), 36 | // String already conforms to EliminationMenuItem an can be used out of the box. 37 | "Just a String", 38 | EliminationMenu.Item(value: "This could also be an Image", title: "Third"), 39 | EliminationMenu.Item(value: "...or a view", title: "Fourth"), 40 | // Add an Element of MyCustomType which conforms to EliminationMenuItem. 41 | MyCustomType(customProperty: true, someOtherProperty: 5) 42 | ] 43 | 44 | /** 45 | Create menu in code. 46 | Using the convenience function. 47 | */ 48 | 49 | let topRightMenuItems = [ 50 | EliminationMenu.Item(value: UIColor(red: 57/255, green: 61/255, blue: 66/255, alpha: 1) , title: "Gray"), 51 | EliminationMenu.Item(value: UIColor.blue, title: "Blue"), 52 | EliminationMenu.Item(value: UIColor.red, title: "Red"), 53 | EliminationMenu.Item(value: UIColor.green, title: "Green") 54 | ] 55 | 56 | let topRightMenu = EliminationMenu.createMenu( 57 | withItems: topRightMenuItems, 58 | inView: view, 59 | aligned: .topRight, 60 | margin: CGPoint(x: 20, y: 20) 61 | ) { (item) in 62 | // Animate the backgroundColor of the view. 63 | if let color = item.value as? UIColor { 64 | UIView.animate(withDuration: 0.5, animations: { 65 | self.view.backgroundColor = color 66 | }) 67 | } 68 | } 69 | 70 | // A little customization. 71 | topRightMenu.font = .boldSystemFont(ofSize: 24) 72 | topRightMenu.color = .white 73 | // Call this after changing layout properties of an already added menu to apply the changes. 74 | topRightMenu.setup() 75 | 76 | /** 77 | Create menu in code. 78 | Manually adding it to the view and setting constraints. 79 | */ 80 | 81 | let rightMenu = EliminationMenu() 82 | 83 | rightMenu.selectionHandler = {item in 84 | self.infoLabel.text = "Selected item:\n\"\(item.title)\"" 85 | if let value = item.value { 86 | self.infoLabel.text?.append( "\n\nThe value is:\n\"\(value)\"" ) 87 | } 88 | } 89 | 90 | rightMenu.items = [ 91 | EliminationMenu.Item(value: "Layer over layer.", icon: UIImage(named: "fabric")), 92 | EliminationMenu.Item(value: "There was this browser...", icon: UIImage(named: "safari")), 93 | EliminationMenu.Item(value: "Save to disk.", icon: UIImage(named: "disk")), 94 | EliminationMenu.Item(value: "Mic check. One, two...", icon: UIImage(named: "check")), 95 | EliminationMenu.Item(value: "To the heart!", icon: UIImage(named: "heart")) 96 | ] 97 | 98 | rightMenu.align = .bottomRight 99 | 100 | // Add menu to layout. 101 | 102 | rightMenu.translatesAutoresizingMaskIntoConstraints = false 103 | view.addSubview(rightMenu) 104 | 105 | view.addConstraints([ 106 | NSLayoutConstraint(item: view, attribute: .right, relatedBy: .equal, toItem: rightMenu, attribute: .right, multiplier: 1, constant: 20), 107 | NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: rightMenu, attribute: .bottom, multiplier: 1, constant: 20) 108 | ]) 109 | } 110 | 111 | override func didReceiveMemoryWarning() { 112 | super.didReceiveMemoryWarning() 113 | // Dispose of any resources that can be recreated. 114 | } 115 | 116 | 117 | } 118 | 119 | -------------------------------------------------------------------------------- /Sources/EliminationMenu.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Roman Gille, http://romangille.com 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining 4 | // a copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to 8 | // permit persons to whom the Software is furnished to do so, subject to 9 | // the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be 12 | // included in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | import UIKit 23 | 24 | /// A menu that eliminates all values which were not selected. 25 | open class EliminationMenu: UIView { 26 | 27 | /// The alignment to a corner of the parent view. 28 | public enum Alignment { 29 | case topLeft, topRight, bottomLeft, bottomRight 30 | } 31 | 32 | /// A closure that provides information about the selected menu item. 33 | public typealias SelectionHandler = (_ selectedIdtem: EliminationMenuItem) -> Void 34 | /// A closure that provides information about an animation that will or did happen. 35 | public typealias AnimationHandler = (_ opening: Bool, _ animated: Bool) -> Void 36 | 37 | /// The alignment of the menu. It defines from which direction the entries will fly in. Defaults to .BottomLeft 38 | open var align: Alignment = .bottomLeft 39 | /// The font used in the menu entry buttons. Defaults to systemFontSize(). 40 | open var font: UIFont = .systemFont(ofSize: UIFont.systemFontSize) 41 | /// The color of the text in menu entries. Defaults to darkTextColor(). 42 | open var color: UIColor = .darkText 43 | /// The amount of points, the menu entries are offset from the screen before fading tehm in. Defaults to 50. 44 | open var buttonAnimationOffset: CGFloat = 50 45 | /// The duration in seconds, that the show animation will take. Defaults to 0.4. 46 | open var showAnimationDuration: TimeInterval = 0.4 47 | /// The duration in seconds, that the selection animation will take. Defaults to 0.25. 48 | open var selectAnimationDuration: TimeInterval = 0.25 49 | /// Margin between the entry buttons. Defaults to 0. 50 | open var margin: CGFloat = 0 51 | /// The height of the menu entry buttons. Defaults to 44. 52 | open var buttonHeight: CGFloat = 44 53 | 54 | /// A closure to react on the selection of a menu entry. This will not fire when the selected value has not changed. 55 | open var selectionHandler: SelectionHandler? 56 | /// A closure to react on menu opening/closing. This will be called before the animation runs. 57 | open var willAnimateHandler: AnimationHandler? 58 | /// A closure to react on menu opening/closing. This will be called after the animation has finished. 59 | open var didAnimateHandler: AnimationHandler? 60 | 61 | var buttons: [UIButton] = [] 62 | 63 | fileprivate var _selectedIndex = 0 64 | fileprivate let _tagOffset = 10 65 | 66 | fileprivate var isLeftAligned: Bool { 67 | return (align == .bottomLeft) || (align == .topLeft) 68 | } 69 | 70 | fileprivate var isBottomAligned: Bool { 71 | return (align == .bottomLeft) || (align == .bottomRight) 72 | } 73 | 74 | /// The entries of the menu. Setting this will reinitialize the menu. 75 | open var items: [EliminationMenuItem] = [] { 76 | didSet { 77 | setup() 78 | } 79 | } 80 | 81 | /// The button for the selected item. This is the one that you see when the menu is closed. 82 | var mainButton: UIButton { 83 | return getButton(atIndex: _selectedIndex)! 84 | } 85 | 86 | /** 87 | Convenience method to create a new menu in a given view and constrain it to some edges. 88 | - parameter items: A collection of EleminationMenu.Item objects. 89 | - parameter view: The view where the menu is added as subview. 90 | - parameter aligned: The corner in which the menu is placed. 91 | - parameter margin: The distance the menu will have to the edges of its superview. 92 | - parameter selection: The closure that will be called upon selection of a menu item. 93 | */ 94 | open class func createMenu(withItems items: [EliminationMenuItem], inView view: UIView, aligned: Alignment, margin: CGPoint = CGPoint(x: 0, y: 0), selection: SelectionHandler? = nil) -> EliminationMenu { 95 | let menu = EliminationMenu() 96 | menu.selectionHandler = selection 97 | menu.align = aligned 98 | 99 | menu.translatesAutoresizingMaskIntoConstraints = false 100 | view.addSubview(menu) 101 | 102 | if menu.isLeftAligned { 103 | view.addConstraint(NSLayoutConstraint( 104 | item: menu, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: margin.x) 105 | ) 106 | } 107 | else { 108 | view.addConstraint(NSLayoutConstraint( 109 | item: view, attribute: .right, relatedBy: .equal, toItem: menu, attribute: .right, multiplier: 1, constant: margin.x) 110 | ) 111 | } 112 | 113 | if menu.isBottomAligned { 114 | view.addConstraint(NSLayoutConstraint( 115 | item: view, attribute: .bottom, relatedBy: .equal, toItem: menu, attribute: .bottom, multiplier: 1, constant: margin.y) 116 | ) 117 | } 118 | else { 119 | view.addConstraint(NSLayoutConstraint( 120 | item: view, attribute: .top, relatedBy: .equal, toItem: menu, attribute: .top, multiplier: 1, constant: -margin.y) 121 | ) 122 | } 123 | 124 | menu.items = items 125 | 126 | return menu 127 | } 128 | 129 | /** 130 | Initializes the menu interface. Call this when you changed layout properties, to apply them. 131 | - parameter index: An optional index of a menu item to show selected after setup 132 | */ 133 | open func setup(withSelectedIndex index: Int = 0) { 134 | // Clear existing buttons. 135 | if items.count > 0 { 136 | for subview in self.subviews { 137 | subview.removeFromSuperview() 138 | } 139 | buttons = [] 140 | } 141 | 142 | guard items.count > 0 else {return} 143 | 144 | let safeIndex = (index < items.count) ? index : 0 145 | 146 | // Create first button. 147 | if buttons.count == 0 { 148 | let menuItem = items[safeIndex] 149 | let button = self.createButton(menuItem, tag: _tagOffset) 150 | 151 | button.frame = CGRect(x: 0, y: 0, width: max(button.intrinsicContentSize.width, self.bounds.size.width), height: self.buttonHeight) 152 | 153 | buttons.append(button) 154 | self.addSubview(button) 155 | 156 | self.invalidateIntrinsicContentSize() 157 | } 158 | 159 | _selectedIndex = safeIndex 160 | } 161 | 162 | @objc func buttonPressed(_ sender: UIView) { 163 | let index = sender.tag - _tagOffset 164 | 165 | if (index == _selectedIndex) { 166 | show((buttons.count < 2), animated: true) 167 | } 168 | else { 169 | select(sender.tag - _tagOffset, animated: true) 170 | } 171 | } 172 | 173 | func getButton(atIndex index: Int) -> UIButton? { 174 | return self.viewWithTag(_tagOffset + index) as? UIButton 175 | } 176 | 177 | func createButton(_ item:EliminationMenuItem, tag:Int) -> UIButton { 178 | let button = UIButton() 179 | 180 | button.setTitle(item.title, for: .normal) 181 | button.setImage(item.icon, for: .normal) 182 | button.contentHorizontalAlignment = (isLeftAligned) ? .left : .right 183 | button.tag = tag 184 | button.titleLabel?.font = self.font 185 | button.setTitleColor(color, for: .normal) 186 | button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) 187 | 188 | setIconInsets(item.iconInsets, button: button) 189 | 190 | return button 191 | } 192 | 193 | func setIconInsets(_ iconInsets:UIEdgeInsets, button:UIButton) { 194 | button.imageEdgeInsets = UIEdgeInsets(top: iconInsets.top, left: iconInsets.left, bottom: iconInsets.bottom, right: 0) 195 | button.titleEdgeInsets = UIEdgeInsets(top: 0, left: iconInsets.right, bottom: 0, right: -iconInsets.right) 196 | button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: iconInsets.right) 197 | } 198 | 199 | func show(_ show: Bool, animated: Bool) { 200 | if show { 201 | var buttonIndex = 0 202 | let buttonVerticalSpace = CGFloat(buttonHeight + margin) 203 | 204 | willAnimateHandler?(true, animated) 205 | 206 | // Add buttons for unselected items. 207 | for titleIndex in 0.. Void in 255 | for button in self.buttons { 256 | button.transform = CGAffineTransform.identity 257 | } 258 | }, completion:{(success) -> Void in 259 | self.didAnimateHandler?(true, animated) 260 | }) 261 | } 262 | else { 263 | self.select(_selectedIndex, animated: animated) 264 | } 265 | } 266 | 267 | func select(_ index: Int?, animated: Bool) { 268 | let selectedIndex: Int = index ?? 0 269 | let menuItem = items[selectedIndex] 270 | 271 | if buttons.count > 1 { 272 | let selectionDidChange = _selectedIndex != selectedIndex 273 | 274 | if selectionDidChange { 275 | selectionHandler?(menuItem) 276 | } 277 | willAnimateHandler?(false, animated) 278 | 279 | 280 | let selectedButton = getButton(atIndex: selectedIndex) 281 | let selectionTargetFrame = CGRect(origin: self.mainButton.frame.origin, size: selectedButton!.frame.size) 282 | let nonSelectedAnimationY: CGFloat 283 | 284 | if isBottomAligned { 285 | nonSelectedAnimationY = frame.size.height - selectedButton!.frame.origin.y - selectedButton!.frame.size.height 286 | } 287 | else { 288 | nonSelectedAnimationY = -(selectedButton!.frame.origin.y) 289 | } 290 | 291 | let nonSelectedTransfromation = CGAffineTransform(translationX: 0, y: nonSelectedAnimationY) 292 | 293 | UIView.animate(withDuration: (animated ? selectAnimationDuration : 0), animations: { () -> Void in 294 | for button in self.buttons { 295 | if button != selectedButton { 296 | button.transform = nonSelectedTransfromation 297 | button.alpha = 0 298 | } 299 | } 300 | 301 | selectedButton?.frame = selectionTargetFrame 302 | 303 | }, completion: { (success) -> Void in 304 | // Remove hidden buttons. 305 | for button in self.buttons { 306 | if button != selectedButton { 307 | button.removeFromSuperview() 308 | 309 | if let index = self.buttons.index(of: button) { 310 | self.buttons.remove(at: index) 311 | } 312 | } 313 | } 314 | // Correct main button position. 315 | selectedButton?.frame = CGRect( 316 | origin: CGPoint(x: 0, y: 0), 317 | size: CGSize(width: selectedButton!.intrinsicContentSize.width, height: self.buttonHeight) 318 | ) 319 | 320 | self._selectedIndex = selectedIndex 321 | self.invalidateIntrinsicContentSize() 322 | 323 | self.didAnimateHandler?(true, animated) 324 | }) 325 | } 326 | else { 327 | selectionHandler?(menuItem) 328 | willAnimateHandler?(false, animated) 329 | 330 | mainButton.setTitle(menuItem.title, for: .normal) 331 | mainButton.setImage(menuItem.icon, for: .normal) 332 | 333 | setIconInsets(menuItem.iconInsets, button: mainButton) 334 | 335 | mainButton.frame = CGRect( 336 | origin: mainButton.frame.origin, 337 | size: CGSize(width: mainButton.intrinsicContentSize.width, height: self.buttonHeight) 338 | ) 339 | mainButton.tag = selectedIndex + _tagOffset 340 | _selectedIndex = selectedIndex 341 | 342 | didAnimateHandler?(true, animated) 343 | } 344 | } 345 | 346 | func selectEntryWithValue(_ value: AnyObject!, animated: Bool) { 347 | for i in 0.. 0 { 357 | var width: CGFloat = 0 358 | var height: CGFloat = -margin 359 | 360 | for button in buttons { 361 | let contentSize = button.intrinsicContentSize 362 | height += self.buttonHeight + margin 363 | if contentSize.width > width { 364 | width = contentSize.width 365 | } 366 | } 367 | return CGSize(width: width, height: height) 368 | } 369 | 370 | return CGSize(width: 0, height: 0) 371 | } 372 | 373 | } 374 | -------------------------------------------------------------------------------- /EliminationMenu.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3071A644215E17440058DF42 /* EliminationMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3071A643215E17440058DF42 /* EliminationMenu.swift */; }; 11 | 3071A646215E21310058DF42 /* MyCostomType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3071A645215E21310058DF42 /* MyCostomType.swift */; }; 12 | 30865F7F215E13A800801C80 /* EliminationMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E77F631DCDA34E00A2A230 /* EliminationMenuItem.swift */; }; 13 | 30865F81215E144300801C80 /* libEliminationMenu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 30865F77215E139D00801C80 /* libEliminationMenu.a */; }; 14 | 30B2D6C21D79E74F00C54A61 /* EliminationMenuTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2D6C11D79E74F00C54A61 /* EliminationMenuTests.swift */; }; 15 | 30C53CF41CC2849B00121273 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C53CEC1CC2849B00121273 /* AppDelegate.swift */; }; 16 | 30C53CF51CC2849B00121273 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 30C53CED1CC2849B00121273 /* Assets.xcassets */; }; 17 | 30C53CF61CC2849B00121273 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 30C53CEE1CC2849B00121273 /* LaunchScreen.storyboard */; }; 18 | 30C53CF71CC2849B00121273 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 30C53CF01CC2849B00121273 /* Main.storyboard */; }; 19 | 30C53CF91CC2849B00121273 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C53CF31CC2849B00121273 /* ViewController.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 30B2D6C41D79E74F00C54A61 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 302488C91CBF811D002343AE /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 302488D01CBF811D002343AE; 28 | remoteInfo = EliminationMenu; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXCopyFilesBuildPhase section */ 33 | 30865F75215E139D00801C80 /* CopyFiles */ = { 34 | isa = PBXCopyFilesBuildPhase; 35 | buildActionMask = 2147483647; 36 | dstPath = "include/$(PRODUCT_NAME)"; 37 | dstSubfolderSpec = 16; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXCopyFilesBuildPhase section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | 302488D11CBF811D002343AE /* Example App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 3071A643215E17440058DF42 /* EliminationMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EliminationMenu.swift; sourceTree = ""; }; 47 | 3071A645215E21310058DF42 /* MyCostomType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyCostomType.swift; sourceTree = ""; }; 48 | 30865F77215E139D00801C80 /* libEliminationMenu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libEliminationMenu.a; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 30B2D6BF1D79E74F00C54A61 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 30B2D6C11D79E74F00C54A61 /* EliminationMenuTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EliminationMenuTests.swift; sourceTree = ""; }; 51 | 30B2D6C31D79E74F00C54A61 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 30C53CEC1CC2849B00121273 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 53 | 30C53CED1CC2849B00121273 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 30C53CEF1CC2849B00121273 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | 30C53CF11CC2849B00121273 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 56 | 30C53CF21CC2849B00121273 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 30C53CF31CC2849B00121273 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 58 | 30E77F631DCDA34E00A2A230 /* EliminationMenuItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EliminationMenuItem.swift; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 302488CE1CBF811D002343AE /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | 30865F81215E144300801C80 /* libEliminationMenu.a in Frameworks */, 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | 30865F74215E139D00801C80 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | 30B2D6BC1D79E74F00C54A61 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | 302488C81CBF811D002343AE = { 88 | isa = PBXGroup; 89 | children = ( 90 | 30C53CEB1CC2849B00121273 /* EliminationMenu */, 91 | 308D72EE1CC2851C0031AFCD /* Sources */, 92 | 30B2D6C01D79E74F00C54A61 /* EliminationMenuTests */, 93 | 302488D21CBF811D002343AE /* Products */, 94 | 30865F80215E144300801C80 /* Frameworks */, 95 | ); 96 | sourceTree = ""; 97 | }; 98 | 302488D21CBF811D002343AE /* Products */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 302488D11CBF811D002343AE /* Example App.app */, 102 | 30B2D6BF1D79E74F00C54A61 /* Tests.xctest */, 103 | 30865F77215E139D00801C80 /* libEliminationMenu.a */, 104 | ); 105 | name = Products; 106 | sourceTree = ""; 107 | }; 108 | 30865F80215E144300801C80 /* Frameworks */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | ); 112 | name = Frameworks; 113 | sourceTree = ""; 114 | }; 115 | 308D72EE1CC2851C0031AFCD /* Sources */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 3071A643215E17440058DF42 /* EliminationMenu.swift */, 119 | 30E77F631DCDA34E00A2A230 /* EliminationMenuItem.swift */, 120 | ); 121 | path = Sources; 122 | sourceTree = ""; 123 | }; 124 | 30B2D6C01D79E74F00C54A61 /* EliminationMenuTests */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 30B2D6C11D79E74F00C54A61 /* EliminationMenuTests.swift */, 128 | 30B2D6C31D79E74F00C54A61 /* Info.plist */, 129 | ); 130 | path = EliminationMenuTests; 131 | sourceTree = ""; 132 | }; 133 | 30C53CEB1CC2849B00121273 /* EliminationMenu */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 30C53CEC1CC2849B00121273 /* AppDelegate.swift */, 137 | 30C53CF31CC2849B00121273 /* ViewController.swift */, 138 | 3071A645215E21310058DF42 /* MyCostomType.swift */, 139 | 30C53CF01CC2849B00121273 /* Main.storyboard */, 140 | 30C53CED1CC2849B00121273 /* Assets.xcassets */, 141 | 30C53CEE1CC2849B00121273 /* LaunchScreen.storyboard */, 142 | 30C53CF21CC2849B00121273 /* Info.plist */, 143 | ); 144 | path = EliminationMenu; 145 | sourceTree = ""; 146 | }; 147 | /* End PBXGroup section */ 148 | 149 | /* Begin PBXNativeTarget section */ 150 | 302488D01CBF811D002343AE /* Example App */ = { 151 | isa = PBXNativeTarget; 152 | buildConfigurationList = 302488E31CBF811D002343AE /* Build configuration list for PBXNativeTarget "Example App" */; 153 | buildPhases = ( 154 | 302488CD1CBF811D002343AE /* Sources */, 155 | 302488CE1CBF811D002343AE /* Frameworks */, 156 | 302488CF1CBF811D002343AE /* Resources */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | ); 162 | name = "Example App"; 163 | productName = RGEliminationMenu; 164 | productReference = 302488D11CBF811D002343AE /* Example App.app */; 165 | productType = "com.apple.product-type.application"; 166 | }; 167 | 30865F76215E139D00801C80 /* EliminationMenu */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = 30865F7B215E139D00801C80 /* Build configuration list for PBXNativeTarget "EliminationMenu" */; 170 | buildPhases = ( 171 | 30865F73215E139D00801C80 /* Sources */, 172 | 30865F74215E139D00801C80 /* Frameworks */, 173 | 30865F75215E139D00801C80 /* CopyFiles */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = EliminationMenu; 180 | productName = EliminationMenu; 181 | productReference = 30865F77215E139D00801C80 /* libEliminationMenu.a */; 182 | productType = "com.apple.product-type.library.static"; 183 | }; 184 | 30B2D6BE1D79E74F00C54A61 /* Tests */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 30B2D6C81D79E74F00C54A61 /* Build configuration list for PBXNativeTarget "Tests" */; 187 | buildPhases = ( 188 | 30B2D6BB1D79E74F00C54A61 /* Sources */, 189 | 30B2D6BC1D79E74F00C54A61 /* Frameworks */, 190 | 30B2D6BD1D79E74F00C54A61 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | 30B2D6C51D79E74F00C54A61 /* PBXTargetDependency */, 196 | ); 197 | name = Tests; 198 | productName = EliminationMenuTests; 199 | productReference = 30B2D6BF1D79E74F00C54A61 /* Tests.xctest */; 200 | productType = "com.apple.product-type.bundle.unit-test"; 201 | }; 202 | /* End PBXNativeTarget section */ 203 | 204 | /* Begin PBXProject section */ 205 | 302488C91CBF811D002343AE /* Project object */ = { 206 | isa = PBXProject; 207 | attributes = { 208 | LastSwiftUpdateCheck = 1000; 209 | LastUpgradeCheck = 1000; 210 | ORGANIZATIONNAME = "Roman Gille"; 211 | TargetAttributes = { 212 | 302488D01CBF811D002343AE = { 213 | CreatedOnToolsVersion = 7.3; 214 | DevelopmentTeam = SBPV56G7LG; 215 | LastSwiftMigration = 0800; 216 | }; 217 | 30865F76215E139D00801C80 = { 218 | CreatedOnToolsVersion = 10.0; 219 | DevelopmentTeam = SBPV56G7LG; 220 | ProvisioningStyle = Automatic; 221 | }; 222 | 30B2D6BE1D79E74F00C54A61 = { 223 | CreatedOnToolsVersion = 7.3.1; 224 | DevelopmentTeam = SBPV56G7LG; 225 | LastSwiftMigration = 0800; 226 | TestTargetID = 302488D01CBF811D002343AE; 227 | }; 228 | }; 229 | }; 230 | buildConfigurationList = 302488CC1CBF811D002343AE /* Build configuration list for PBXProject "EliminationMenu" */; 231 | compatibilityVersion = "Xcode 3.2"; 232 | developmentRegion = English; 233 | hasScannedForEncodings = 0; 234 | knownRegions = ( 235 | en, 236 | Base, 237 | ); 238 | mainGroup = 302488C81CBF811D002343AE; 239 | productRefGroup = 302488D21CBF811D002343AE /* Products */; 240 | projectDirPath = ""; 241 | projectRoot = ""; 242 | targets = ( 243 | 302488D01CBF811D002343AE /* Example App */, 244 | 30B2D6BE1D79E74F00C54A61 /* Tests */, 245 | 30865F76215E139D00801C80 /* EliminationMenu */, 246 | ); 247 | }; 248 | /* End PBXProject section */ 249 | 250 | /* Begin PBXResourcesBuildPhase section */ 251 | 302488CF1CBF811D002343AE /* Resources */ = { 252 | isa = PBXResourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | 30C53CF71CC2849B00121273 /* Main.storyboard in Resources */, 256 | 30C53CF51CC2849B00121273 /* Assets.xcassets in Resources */, 257 | 30C53CF61CC2849B00121273 /* LaunchScreen.storyboard in Resources */, 258 | ); 259 | runOnlyForDeploymentPostprocessing = 0; 260 | }; 261 | 30B2D6BD1D79E74F00C54A61 /* Resources */ = { 262 | isa = PBXResourcesBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | /* End PBXResourcesBuildPhase section */ 269 | 270 | /* Begin PBXSourcesBuildPhase section */ 271 | 302488CD1CBF811D002343AE /* Sources */ = { 272 | isa = PBXSourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | 30C53CF91CC2849B00121273 /* ViewController.swift in Sources */, 276 | 3071A646215E21310058DF42 /* MyCostomType.swift in Sources */, 277 | 30C53CF41CC2849B00121273 /* AppDelegate.swift in Sources */, 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | 30865F73215E139D00801C80 /* Sources */ = { 282 | isa = PBXSourcesBuildPhase; 283 | buildActionMask = 2147483647; 284 | files = ( 285 | 30865F7F215E13A800801C80 /* EliminationMenuItem.swift in Sources */, 286 | 3071A644215E17440058DF42 /* EliminationMenu.swift in Sources */, 287 | ); 288 | runOnlyForDeploymentPostprocessing = 0; 289 | }; 290 | 30B2D6BB1D79E74F00C54A61 /* Sources */ = { 291 | isa = PBXSourcesBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | 30B2D6C21D79E74F00C54A61 /* EliminationMenuTests.swift in Sources */, 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | /* End PBXSourcesBuildPhase section */ 299 | 300 | /* Begin PBXTargetDependency section */ 301 | 30B2D6C51D79E74F00C54A61 /* PBXTargetDependency */ = { 302 | isa = PBXTargetDependency; 303 | target = 302488D01CBF811D002343AE /* Example App */; 304 | targetProxy = 30B2D6C41D79E74F00C54A61 /* PBXContainerItemProxy */; 305 | }; 306 | /* End PBXTargetDependency section */ 307 | 308 | /* Begin PBXVariantGroup section */ 309 | 30C53CEE1CC2849B00121273 /* LaunchScreen.storyboard */ = { 310 | isa = PBXVariantGroup; 311 | children = ( 312 | 30C53CEF1CC2849B00121273 /* Base */, 313 | ); 314 | name = LaunchScreen.storyboard; 315 | sourceTree = ""; 316 | }; 317 | 30C53CF01CC2849B00121273 /* Main.storyboard */ = { 318 | isa = PBXVariantGroup; 319 | children = ( 320 | 30C53CF11CC2849B00121273 /* Base */, 321 | ); 322 | name = Main.storyboard; 323 | sourceTree = ""; 324 | }; 325 | /* End PBXVariantGroup section */ 326 | 327 | /* Begin XCBuildConfiguration section */ 328 | 302488E11CBF811D002343AE /* Debug */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ALWAYS_SEARCH_USER_PATHS = NO; 332 | CLANG_ANALYZER_NONNULL = YES; 333 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 334 | CLANG_CXX_LIBRARY = "libc++"; 335 | CLANG_ENABLE_MODULES = YES; 336 | CLANG_ENABLE_OBJC_ARC = YES; 337 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 338 | CLANG_WARN_BOOL_CONVERSION = YES; 339 | CLANG_WARN_COMMA = YES; 340 | CLANG_WARN_CONSTANT_CONVERSION = YES; 341 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 342 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 343 | CLANG_WARN_EMPTY_BODY = YES; 344 | CLANG_WARN_ENUM_CONVERSION = YES; 345 | CLANG_WARN_INFINITE_RECURSION = YES; 346 | CLANG_WARN_INT_CONVERSION = YES; 347 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 348 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 349 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 350 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 352 | CLANG_WARN_STRICT_PROTOTYPES = YES; 353 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 354 | CLANG_WARN_UNREACHABLE_CODE = YES; 355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 357 | COPY_PHASE_STRIP = NO; 358 | DEBUG_INFORMATION_FORMAT = dwarf; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | ENABLE_TESTABILITY = YES; 361 | GCC_C_LANGUAGE_STANDARD = gnu99; 362 | GCC_DYNAMIC_NO_PIC = NO; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_OPTIMIZATION_LEVEL = 0; 365 | GCC_PREPROCESSOR_DEFINITIONS = ( 366 | "DEBUG=1", 367 | "$(inherited)", 368 | ); 369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 371 | GCC_WARN_UNDECLARED_SELECTOR = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 373 | GCC_WARN_UNUSED_FUNCTION = YES; 374 | GCC_WARN_UNUSED_VARIABLE = YES; 375 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 376 | MTL_ENABLE_DEBUG_INFO = YES; 377 | ONLY_ACTIVE_ARCH = YES; 378 | SDKROOT = iphoneos; 379 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 380 | }; 381 | name = Debug; 382 | }; 383 | 302488E21CBF811D002343AE /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_SEARCH_USER_PATHS = NO; 387 | CLANG_ANALYZER_NONNULL = YES; 388 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 389 | CLANG_CXX_LIBRARY = "libc++"; 390 | CLANG_ENABLE_MODULES = YES; 391 | CLANG_ENABLE_OBJC_ARC = YES; 392 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 393 | CLANG_WARN_BOOL_CONVERSION = YES; 394 | CLANG_WARN_COMMA = YES; 395 | CLANG_WARN_CONSTANT_CONVERSION = YES; 396 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 397 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 398 | CLANG_WARN_EMPTY_BODY = YES; 399 | CLANG_WARN_ENUM_CONVERSION = YES; 400 | CLANG_WARN_INFINITE_RECURSION = YES; 401 | CLANG_WARN_INT_CONVERSION = YES; 402 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 403 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 404 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 405 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 406 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 407 | CLANG_WARN_STRICT_PROTOTYPES = YES; 408 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 409 | CLANG_WARN_UNREACHABLE_CODE = YES; 410 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 411 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 412 | COPY_PHASE_STRIP = NO; 413 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 414 | ENABLE_NS_ASSERTIONS = NO; 415 | ENABLE_STRICT_OBJC_MSGSEND = YES; 416 | GCC_C_LANGUAGE_STANDARD = gnu99; 417 | GCC_NO_COMMON_BLOCKS = YES; 418 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 419 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 420 | GCC_WARN_UNDECLARED_SELECTOR = YES; 421 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 422 | GCC_WARN_UNUSED_FUNCTION = YES; 423 | GCC_WARN_UNUSED_VARIABLE = YES; 424 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 425 | MTL_ENABLE_DEBUG_INFO = NO; 426 | SDKROOT = iphoneos; 427 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 428 | VALIDATE_PRODUCT = YES; 429 | }; 430 | name = Release; 431 | }; 432 | 302488E41CBF811D002343AE /* Debug */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 436 | DEVELOPMENT_TEAM = SBPV56G7LG; 437 | INFOPLIST_FILE = EliminationMenu/Info.plist; 438 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 439 | PRODUCT_BUNDLE_IDENTIFIER = rg.test.EliminationMenu; 440 | PRODUCT_NAME = "$(TARGET_NAME)"; 441 | SWIFT_VERSION = 4.2; 442 | }; 443 | name = Debug; 444 | }; 445 | 302488E51CBF811D002343AE /* Release */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 449 | DEVELOPMENT_TEAM = SBPV56G7LG; 450 | INFOPLIST_FILE = EliminationMenu/Info.plist; 451 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 452 | PRODUCT_BUNDLE_IDENTIFIER = rg.test.EliminationMenu; 453 | PRODUCT_NAME = "$(TARGET_NAME)"; 454 | SWIFT_VERSION = 4.2; 455 | }; 456 | name = Release; 457 | }; 458 | 30865F7C215E139D00801C80 /* Debug */ = { 459 | isa = XCBuildConfiguration; 460 | buildSettings = { 461 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 462 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 463 | CLANG_ENABLE_OBJC_WEAK = YES; 464 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 465 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 466 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 467 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 468 | CODE_SIGN_IDENTITY = "iPhone Developer"; 469 | CODE_SIGN_STYLE = Automatic; 470 | DEVELOPMENT_TEAM = SBPV56G7LG; 471 | GCC_C_LANGUAGE_STANDARD = gnu11; 472 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 473 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 474 | MTL_FAST_MATH = YES; 475 | OTHER_LDFLAGS = "-ObjC"; 476 | PRODUCT_NAME = "$(TARGET_NAME)"; 477 | SKIP_INSTALL = YES; 478 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 479 | SWIFT_VERSION = 4.2; 480 | TARGETED_DEVICE_FAMILY = "1,2"; 481 | }; 482 | name = Debug; 483 | }; 484 | 30865F7D215E139D00801C80 /* Release */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 488 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 489 | CLANG_ENABLE_OBJC_WEAK = YES; 490 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 491 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 492 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 493 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 494 | CODE_SIGN_IDENTITY = "iPhone Developer"; 495 | CODE_SIGN_STYLE = Automatic; 496 | DEVELOPMENT_TEAM = SBPV56G7LG; 497 | GCC_C_LANGUAGE_STANDARD = gnu11; 498 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 499 | MTL_FAST_MATH = YES; 500 | OTHER_LDFLAGS = "-ObjC"; 501 | PRODUCT_NAME = "$(TARGET_NAME)"; 502 | SKIP_INSTALL = YES; 503 | SWIFT_VERSION = 4.2; 504 | TARGETED_DEVICE_FAMILY = "1,2"; 505 | }; 506 | name = Release; 507 | }; 508 | 30B2D6C61D79E74F00C54A61 /* Debug */ = { 509 | isa = XCBuildConfiguration; 510 | buildSettings = { 511 | BUNDLE_LOADER = "$(TEST_HOST)"; 512 | DEVELOPMENT_TEAM = SBPV56G7LG; 513 | INFOPLIST_FILE = EliminationMenuTests/Info.plist; 514 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 515 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 516 | PRODUCT_BUNDLE_IDENTIFIER = rg.EliminationMenuTests; 517 | PRODUCT_NAME = "$(TARGET_NAME)"; 518 | SWIFT_VERSION = 4.2; 519 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example App.app/Example App"; 520 | }; 521 | name = Debug; 522 | }; 523 | 30B2D6C71D79E74F00C54A61 /* Release */ = { 524 | isa = XCBuildConfiguration; 525 | buildSettings = { 526 | BUNDLE_LOADER = "$(TEST_HOST)"; 527 | DEVELOPMENT_TEAM = SBPV56G7LG; 528 | INFOPLIST_FILE = EliminationMenuTests/Info.plist; 529 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 530 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 531 | PRODUCT_BUNDLE_IDENTIFIER = rg.EliminationMenuTests; 532 | PRODUCT_NAME = "$(TARGET_NAME)"; 533 | SWIFT_VERSION = 4.2; 534 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example App.app/Example App"; 535 | }; 536 | name = Release; 537 | }; 538 | /* End XCBuildConfiguration section */ 539 | 540 | /* Begin XCConfigurationList section */ 541 | 302488CC1CBF811D002343AE /* Build configuration list for PBXProject "EliminationMenu" */ = { 542 | isa = XCConfigurationList; 543 | buildConfigurations = ( 544 | 302488E11CBF811D002343AE /* Debug */, 545 | 302488E21CBF811D002343AE /* Release */, 546 | ); 547 | defaultConfigurationIsVisible = 0; 548 | defaultConfigurationName = Release; 549 | }; 550 | 302488E31CBF811D002343AE /* Build configuration list for PBXNativeTarget "Example App" */ = { 551 | isa = XCConfigurationList; 552 | buildConfigurations = ( 553 | 302488E41CBF811D002343AE /* Debug */, 554 | 302488E51CBF811D002343AE /* Release */, 555 | ); 556 | defaultConfigurationIsVisible = 0; 557 | defaultConfigurationName = Release; 558 | }; 559 | 30865F7B215E139D00801C80 /* Build configuration list for PBXNativeTarget "EliminationMenu" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | 30865F7C215E139D00801C80 /* Debug */, 563 | 30865F7D215E139D00801C80 /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | 30B2D6C81D79E74F00C54A61 /* Build configuration list for PBXNativeTarget "Tests" */ = { 569 | isa = XCConfigurationList; 570 | buildConfigurations = ( 571 | 30B2D6C61D79E74F00C54A61 /* Debug */, 572 | 30B2D6C71D79E74F00C54A61 /* Release */, 573 | ); 574 | defaultConfigurationIsVisible = 0; 575 | defaultConfigurationName = Release; 576 | }; 577 | /* End XCConfigurationList section */ 578 | }; 579 | rootObject = 302488C91CBF811D002343AE /* Project object */; 580 | } 581 | --------------------------------------------------------------------------------