├── .codecov.yml ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Design ├── Logo.png └── Logo.sketch ├── Examples ├── PDColorPicker.framework │ ├── Headers │ │ ├── PDColorPicker-Swift.h │ │ └── PDColorPicker-umbrella.h │ ├── Info.plist │ ├── Modules │ │ ├── PDColorPicker.swiftmodule │ │ │ ├── x86_64.swiftdoc │ │ │ └── x86_64.swiftmodule │ │ └── module.modulemap │ ├── PDColorPicker │ └── _CodeSignature │ │ └── CodeResources ├── PDColorPicker.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── PDColorPickerExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── PDColorPickerExample.xcscheme ├── PDColorPickerExample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── Launch Screen.storyboard │ ├── Info.plist │ └── ViewController.swift ├── PDColorReceiverExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── PDColorReceiverExample.xcscheme ├── PDColorReceiverExample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ └── ViewController.swift ├── Podfile ├── Podfile.lock └── Tests │ ├── Info.plist │ ├── PDColorNamedColorsSpec.swift │ ├── PDColorPickerGesturesSpec.swift │ ├── PDColorPickerViewControllerSpec.swift │ └── PDColorSpec.swift ├── LICENSE.md ├── PDColorPicker.podspec ├── README.md ├── Resources ├── demo.gif └── drag-drop-demo.gif └── Source ├── Dimmable.swift ├── PDBouncyButton.swift ├── PDColor+NamedColors.swift ├── PDColor.swift ├── PDColorPickerAlphaSliderView.swift ├── PDColorPickerGridView.swift ├── PDColorPickerSliderView.swift ├── PDColorPickerViewController.swift ├── PDPanGestureRecognizer.swift ├── PDRoundedRectButton.swift ├── PDSelectedColorLabel.swift ├── PDTapGestureRecognizer.swift └── UIView+Layout.swift /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: 50..90 3 | round: down 4 | precision: 2 5 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | I have decided to adopt the [Contributor Convenant](https://contributor-covenant.org/) as the code of conduct to be followed when contributing to this project. It is used across [many open source communities](https://contributor-covenant.org/adopters/) and I think it articulates my values (and the values of open source software) well. 2 | 3 | The full text is copied below. 4 | 5 | ---- 6 | 7 | # Contributor Covenant Code of Conduct 8 | 9 | ## Our Pledge 10 | 11 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 12 | 13 | ## Our Standards 14 | 15 | Examples of behavior that contributes to creating a positive environment include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 26 | * Trolling, insulting/derogatory comments, and personal or political attacks 27 | * Public or private harassment 28 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 29 | * Other conduct which could reasonably be considered inappropriate in a professional setting 30 | 31 | ## Our Responsibilities 32 | 33 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 34 | 35 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 36 | 37 | ## Scope 38 | 39 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 40 | 41 | ## Enforcement 42 | 43 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at dilorenzo@hey.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 44 | 45 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 46 | 47 | ## Attribution 48 | 49 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 50 | 51 | [homepage]: http://contributor-covenant.org 52 | [version]: http://contributor-covenant.org/version/1/4/ 53 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # PDColorPicker Contribution Guidelines 2 | 3 | **PDColorPicker** welcomes contributions by anyone who is willing and abides by the [Code of Conduct](https://github.com/pdil/PDColorPicker/blob/master/CODE_OF_CONDUCT.md). The following guidelines provide a framework to make contribution seamless and effective. 4 | 5 | ### Pull Requests 6 | The main way to contribute to **PDColorPicker** is via pull requests. 7 | The steps to follow to submit a pull request are as follows: 8 | 9 | 1. Fork **PDColorPicker** 10 | 2. Clone your forked repository to your computer 11 | 3. Make changes and commits 12 | 4. Push your changes and commits to GitHub 13 | 5. Submit a pull request to this repository 14 | 15 | Your changes will be reviewed and discussed. Then the pull request will either be accepted, or sent back for changes. If it is determined that the change is not appropriate for the project, it may be rejected. 16 | 17 | #### Branch Structure 18 | All commits should be done on the `develop` branch. `master` is only to be used when a new release is being pushed. If the feature or bugfix requires significant work, create a separate branch to perform the work, then merge to `develop`. 19 | 20 | ### Issues 21 | Another way to contribute is filing issues. To file an issue go to the Issues tab and click "New issue". If possible, categorize your issue using one of the pre-defined labels. Issues offer a way to discuss bugs or proposed changes. If you are unable to submit a pull request with changes, an issue is a good way to bring that change proposal to the attention of the project maintainers and contributers. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Expected behavior 2 | 3 | 4 | 5 | ### Actual behavior 6 | 7 | 8 | 9 | ### Steps to reproduce behavior 10 | 11 | 12 | 13 | === 14 | 15 | * **Xcode version**: 16 | * **iOS version**: 17 | * **Device(s)**: 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | Fixes # 3 | 4 | ### Proposed changes 5 | * 6 | * 7 | * 8 | 9 | @pdil 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore media source files 2 | *.mov 3 | *.svg 4 | 5 | # =========== 6 | 7 | # OS X 8 | .DS_Store 9 | 10 | # Xcode 11 | build/ 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata/ 21 | *.xccheckout 22 | profile 23 | *.moved-aside 24 | DerivedData 25 | *.hmap 26 | *.ipa 27 | 28 | # Bundler 29 | .bundle 30 | 31 | # Cocoapods 32 | Pods/ 33 | Examples/Pods 34 | 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode10.2 3 | 4 | before_install: 5 | - npm install ios-sim -g 6 | - ios-sim start --devicetypeid "com.apple.CoreSimulator.SimDeviceType.iPhone-8, 12.2" 7 | 8 | script: 9 | - xcodebuild clean build build-for-testing -workspace Examples/PDColorPicker.xcworkspace -scheme PDColorPickerExample -sdk iphonesimulator12.2 -destination 'platform=iOS Simulator,name=iPhone 8,OS=12.2' -enableCodeCoverage YES ONLY_ACTIVE_ARCH=YES VALID_ARCHS=x86_64 10 | - xcodebuild test-without-building -workspace Examples/PDColorPicker.xcworkspace -scheme PDColorPickerExample -sdk iphonesimulator12.2 -destination 'platform=iOS Simulator,name=iPhone 8,OS=12.2' -enableCodeCoverage YES ONLY_ACTIVE_ARCH=YES VALID_ARCHS=x86_64 | xcpretty -f `xcpretty-travis-formatter` && exit ${PIPESTATUS[0]} 11 | - pod lib lint 12 | 13 | after_success: 14 | - bash <(curl -s https://codecov.io/bash) -J '^PDColorPicker$' || echo "Codecov did not collect coverage reports." 15 | 16 | notifications: 17 | pushover: 18 | api_key: 19 | secure: gyjYU6srgxtyY01aZ6Lvbxvb0nBxrKHMN1b9pySzGRHv1iPxObNjCtg7pWyH0FpHgtJ9c/kcemtfXq1Cug65dLPanTPqOk9BU306Rdrg7vBKp/7/CwsFGtcKZw6cKVthCFjQihiZfZMoeR4Jl/5DVXAKL5q36OvbKJ7FGJT2SL79IJxSo2/+YGvA+6mEPGPWigfJAtHhpkxH0xtWsTKHPeKEidRD0qrz55HxiYUcu1evBjXdQ24FolLd93cS/j+wBSsB+tA8bLaVQouAFYEaUJpSEn4sA56W4TLVHMl/r8123ZqWI6+VpAvUpkDxaWt/M/IGtlghAjMf1HK302fIqzf+PnKb+67W/jpB/Of/ktqCJFraMsqhFsNW2VfXPOBChhlTWLafxtJwiL75uh0Veump4az15pcJTJgc4AHwqy6v3LmHm8iew3VpqCExL71H7fsTqKAv2u0Dcq/MC9W2B6G4KE4SanOqbsDc4fKzSYHfeVv5C7fFX9W1q/Qd1l+jR4efOxniY2yZ3K2Ja/n+EZinolN5mXAUJnxeaAxi3RvXY3naEgiQTpEo722foBzOApM0mIJ/s6h08Ylxbvo6fmo9pH2XoHOmCm/VGOoiZpTtFPv/fYHJZe3YYyzrOyUBXIiT2jBNRdzjQa074Z3jrVVyIBz1k5/rbWJqtsD5XZE= 20 | users: 21 | secure: YCoTq3a1+qvJ2Cyy53Wu4V9wVTqw8kb27eeosscfJHBBGFohZkdHp3tpwm6De36ZtyKUN2J5NhbIS1b60WC4Ax6j6EZrhhNQeuhP9x+3jynsk8yVfH/+jJxIXp4fK6i3eO8dqFEBFqXBxVAejxDy7Xu1+rmmYjdhmabn/LyTTF01T7JT3fThgVcDPKyYQM6tsliCXhZ8vqFQU5C06c75wnI0WSBnMSX1Mq23m5aRTXmDYwxVFlMLAqIg7331bYotiNN2L2tLZFX8hOk+X5CT9cMZdu4fN4U1RSFr6worc9Rpgtq2GClqAwOODLia187p9pcTDZtOgRyLKSjHqGHPOySzp2PGllxmSDnWUZZokNREylyvGS/3qRUOhc3Gy2hvorkcIt59ePtMcRRnYpb4R2h/aTItTiHS0c9rqR0Iz8WPLSDrg7iYAuv49tPUiC6qoHA5vl7iiAobprlmqggUxwJGXQ3YEAoRuvB/R08sFBP09VQ5H43Oy/ogCqmCdm5R6UqnIvNFL7d343qtPsrWxAb2LiCgJE0gUw/gU8ZwT6db9g04kEQHTEx1l+9NvbunrRk6D/FYfucTA2DssWmw5fzlG/TNl1XnyYLgE3cYPUpCkO9V6Slt5ks+ZyW0VJfOiPqCkkKk/Rq64TZXMlnxTIaAEjNzZcNyB1gae4CDaJE= 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [PDColorPicker v0.8.5](https://github.com/pdil/PDColorPicker/releases/tag/0.8.5) 2 | Released Friday, October 20, 2023. 3 | 4 | * Update author email. 5 | 6 | # [PDColorPicker v0.8.4](https://github.com/pdil/PDColorPicker/releases/tag/0.8.4) 7 | Released Friday, August 25, 2023. 8 | 9 | * Set minimum deployment target to iOS 11. 10 | * Minor updates to ensure compatibility with modern iOS projects. 11 | 12 | # [PDColorPicker v0.8.3](https://github.com/pdil/PDColorPicker/releases/tag/0.8.3) 13 | Released Friday, June 14, 2019. 14 | 15 | * Updated to support Swift 5. 16 | * Made further fixes to appearance on devices of various orientations and screen sizes. 17 | 18 | # [PDColorPicker v0.8.2](https://github.com/pdil/PDColorPicker/releases/tag/0.8.2) 19 | Released on Wednesday, October 24, 2018. 20 | 21 | * Renamed `HexStringCase` cases to `upper` and `lower`. 22 | * `.uppercase` and `.lowercase` are now marked as deprecated and will be removed at a later date (probably version 1.0). 23 | * Fixed appearance of color picker on smaller devices and when device orientation changes. 24 | 25 | # [PDColorPicker v0.8.1](https://github.com/pdil/PDColorPicker/releases/tag/0.8.1) 26 | Released on Saturday, October 20, 2018. 27 | 28 | * Added ability to select case for hex string (`HexStringCase.uppercase` or `HexStringCase.lowercase`) via the `hexStringCase` property of `PDColorPickerViewController`. 29 | * Examples: `#02af93` vs `#02AF93`. 30 | * Updated to support Swift 4.2, iOS 12, and Xcode 10. 31 | * Ignore smart invert colors in dimming view to prevent white glow. 32 | 33 | # [PDColorPicker v0.8.0](https://github.com/pdil/PDColorPicker/releases/tag/0.8.0) 34 | Released on Tuesday, April 17, 2018. 35 | 36 | * Added ability to tap grid/slider to change color (without panning) ([PR #12](https://github.com/pdil/PDColorPicker/pull/12) by [@bennyjr33](https://github.com/bennyjr33)) 37 | * Added ability to toggle drag and drop functionality. 38 | * Set `allowsDragAndDrop` to `true` or `false` in `PDColorPicker`. 39 | * Updated to support Swift 4.1. 40 | 41 | 42 | # [PDColorPicker v0.7.0](https://github.com/pdil/PDColorPicker/releases/tag/0.7.0) 43 | Released on Tuesday, November 6, 2017. 44 | 45 | * Added support for Smart Invert Colors. 46 | * Set `supportsSmartInvertColors` to `true` or `false` in `PDColorPicker`. 47 | * Added [Pull Request](https://github.com/pdil/PDColorPicker/blob/master/.github/PULL_REQUEST_TEMPLATE.md) and [Issue](https://github.com/pdil/PDColorPicker/blob/master/.github/ISSUE_TEMPLATE.md) templates. 48 | 49 | ### Bug Fixes 50 | * Changed some property declarations for consistency. 51 | * Fixed `codecov.yml` template. 52 | * Fixed example code in [README](https://github.com/pdil/PDColorPicker/blob/master/README.md) 53 | 54 | # [PDColorPicker v0.6.0](https://github.com/pdil/PDColorPicker/releases/tag/0.6.0) 55 | Released on Tuesday, September 19, 2017. 56 | 57 | * Now supports Swift 4.0 58 | * For projects that don't support Swift 4.0, install from the `swift-3.2` branch. 59 | 60 | ### Minor improvements 61 | * Added Contributing guidelines to repository (will be updated over time) 62 | * Improved code coverage for tests 63 | 64 | # [PDColorPicker v0.5.0](https://github.com/pdil/PDColorPicker/releases/tag/0.5.0) 65 | Released on Sunday, September 3, 2017. 66 | 67 | ### Improvements 68 | * The status bar style no longer needs to be set by the presenting view controller (managed by `PDColorPickerViewController`) 69 | 70 | ### Bug Fixes 71 | * Fixed issue with slider circle offset not working in `PDColorPickerGridView` 72 | * This was caused by not checking to see if constraints had already been set in `PDColorPickerViewController` 73 | 74 | # [PDColorPicker v0.4.1](https://github.com/pdil/PDColorPicker/releases/tag/0.4.1) 75 | Released on Thursday, August 31, 2017. 76 | 77 | ### Improvements 78 | * Improved framework documentation 79 | 80 | ### Bug Fixes 81 | * Fixed rotation issue with dimming view ([issue #8](https://github.com/pdil/PDColorPicker/issues/8)) 82 | 83 | # [PDColorPicker v0.4.0](https://github.com/pdil/PDColorPicker/releases/tag/0.4.0) 84 | Released on Thursday, August 31, 2017. 85 | 86 | ### Improvements 87 | * Removed unnecessary layout anchor functions 88 | * Improved framework documentation 89 | 90 | # [PDColorPicker v0.3.0](https://github.com/pdil/PDColorPicker/releases/tag/0.3.0) 91 | Released Monday, August 28, 2017. 92 | 93 | ### Improvements 94 | * Fixed sizing of `PDColorPickerViewController` for different screen sizes (e.g. iPad in multiple split-view sizes) 95 | * Added the following named colors to `PDColor` for convenience: 96 | * `PDColor.red` 97 | * `PDColor.orange` 98 | * `PDColor.yellow` 99 | * `PDColor.yellowGreen` 100 | * `PDColor.green` 101 | * `PDColor.cyan` 102 | * `PDColor.azure` 103 | * `PDColor.blue` 104 | * `PDColor.purple` 105 | * `PDColor.magenta` 106 | * `PDColor.pink` 107 | * `PDColor.white` 108 | * `PDColor.black` 109 | * Improved framework documentation 110 | 111 | # [PDColorPicker v0.2.0](https://github.com/pdil/PDColorPicker/releases/tag/0.2.0) 112 | Released on Friday, August 18, 2017. 113 | 114 | ### New Features 115 | * Implemented drag-and-drop support for iOS 11 116 | * Created drag-and-drop example 117 | 118 | ### Other Improvements 119 | * Renamed `PDColor` initializer parameters 120 | - `PDColor(fromString:)` becomes `PDColor(string:)` 121 | - `PDColor(fromColor:)` becomes `PDColor(color:)` 122 | * Switched to MIT license 123 | * Added code of conduct 124 | * Improved documentation 125 | 126 | # [PDColorPicker v0.1.0](https://github.com/pdil/PDColorPicker/releases/tag/0.1.0) 127 | Released on Wednesday, August 16, 2017. 128 | 129 | First release. 130 | 131 | ### Main Features 132 | * Present a modal color picker view controller. 133 | * Allow user to select hue, saturation, and brightness values. 134 | * Displays hexadecimal value of color (can optionally be removed). 135 | * Customizable interface font and color. 136 | -------------------------------------------------------------------------------- /Design/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Design/Logo.png -------------------------------------------------------------------------------- /Design/Logo.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Design/Logo.sketch -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/Headers/PDColorPicker-Swift.h: -------------------------------------------------------------------------------- 1 | // Generated by Apple Swift version 4.0 effective-3.2 (swiftlang-900.0.43 clang-900.0.22.8) 2 | #pragma clang diagnostic push 3 | #pragma clang diagnostic ignored "-Wgcc-compat" 4 | 5 | #if !defined(__has_include) 6 | # define __has_include(x) 0 7 | #endif 8 | #if !defined(__has_attribute) 9 | # define __has_attribute(x) 0 10 | #endif 11 | #if !defined(__has_feature) 12 | # define __has_feature(x) 0 13 | #endif 14 | #if !defined(__has_warning) 15 | # define __has_warning(x) 0 16 | #endif 17 | 18 | #if __has_attribute(external_source_symbol) 19 | # define SWIFT_STRINGIFY(str) #str 20 | # define SWIFT_MODULE_NAMESPACE_PUSH(module_name) _Pragma(SWIFT_STRINGIFY(clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in=module_name, generated_declaration))), apply_to=any(function, enum, objc_interface, objc_category, objc_protocol)))) 21 | # define SWIFT_MODULE_NAMESPACE_POP _Pragma("clang attribute pop") 22 | #else 23 | # define SWIFT_MODULE_NAMESPACE_PUSH(module_name) 24 | # define SWIFT_MODULE_NAMESPACE_POP 25 | #endif 26 | 27 | #if __has_include() 28 | # include 29 | #endif 30 | 31 | #pragma clang diagnostic ignored "-Wauto-import" 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #if !defined(SWIFT_TYPEDEFS) 38 | # define SWIFT_TYPEDEFS 1 39 | # if __has_include() 40 | # include 41 | # elif !defined(__cplusplus) || __cplusplus < 201103L 42 | typedef uint_least16_t char16_t; 43 | typedef uint_least32_t char32_t; 44 | # endif 45 | typedef float swift_float2 __attribute__((__ext_vector_type__(2))); 46 | typedef float swift_float3 __attribute__((__ext_vector_type__(3))); 47 | typedef float swift_float4 __attribute__((__ext_vector_type__(4))); 48 | typedef double swift_double2 __attribute__((__ext_vector_type__(2))); 49 | typedef double swift_double3 __attribute__((__ext_vector_type__(3))); 50 | typedef double swift_double4 __attribute__((__ext_vector_type__(4))); 51 | typedef int swift_int2 __attribute__((__ext_vector_type__(2))); 52 | typedef int swift_int3 __attribute__((__ext_vector_type__(3))); 53 | typedef int swift_int4 __attribute__((__ext_vector_type__(4))); 54 | typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); 55 | typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); 56 | typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); 57 | #endif 58 | 59 | #if !defined(SWIFT_PASTE) 60 | # define SWIFT_PASTE_HELPER(x, y) x##y 61 | # define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) 62 | #endif 63 | #if !defined(SWIFT_METATYPE) 64 | # define SWIFT_METATYPE(X) Class 65 | #endif 66 | #if !defined(SWIFT_CLASS_PROPERTY) 67 | # if __has_feature(objc_class_property) 68 | # define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ 69 | # else 70 | # define SWIFT_CLASS_PROPERTY(...) 71 | # endif 72 | #endif 73 | 74 | #if __has_attribute(objc_runtime_name) 75 | # define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) 76 | #else 77 | # define SWIFT_RUNTIME_NAME(X) 78 | #endif 79 | #if __has_attribute(swift_name) 80 | # define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) 81 | #else 82 | # define SWIFT_COMPILE_NAME(X) 83 | #endif 84 | #if __has_attribute(objc_method_family) 85 | # define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) 86 | #else 87 | # define SWIFT_METHOD_FAMILY(X) 88 | #endif 89 | #if __has_attribute(noescape) 90 | # define SWIFT_NOESCAPE __attribute__((noescape)) 91 | #else 92 | # define SWIFT_NOESCAPE 93 | #endif 94 | #if __has_attribute(warn_unused_result) 95 | # define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 96 | #else 97 | # define SWIFT_WARN_UNUSED_RESULT 98 | #endif 99 | #if __has_attribute(noreturn) 100 | # define SWIFT_NORETURN __attribute__((noreturn)) 101 | #else 102 | # define SWIFT_NORETURN 103 | #endif 104 | #if !defined(SWIFT_CLASS_EXTRA) 105 | # define SWIFT_CLASS_EXTRA 106 | #endif 107 | #if !defined(SWIFT_PROTOCOL_EXTRA) 108 | # define SWIFT_PROTOCOL_EXTRA 109 | #endif 110 | #if !defined(SWIFT_ENUM_EXTRA) 111 | # define SWIFT_ENUM_EXTRA 112 | #endif 113 | #if !defined(SWIFT_CLASS) 114 | # if __has_attribute(objc_subclassing_restricted) 115 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA 116 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 117 | # else 118 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 119 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 120 | # endif 121 | #endif 122 | 123 | #if !defined(SWIFT_PROTOCOL) 124 | # define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 125 | # define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 126 | #endif 127 | 128 | #if !defined(SWIFT_EXTENSION) 129 | # define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) 130 | #endif 131 | 132 | #if !defined(OBJC_DESIGNATED_INITIALIZER) 133 | # if __has_attribute(objc_designated_initializer) 134 | # define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) 135 | # else 136 | # define OBJC_DESIGNATED_INITIALIZER 137 | # endif 138 | #endif 139 | #if !defined(SWIFT_ENUM_ATTR) 140 | # if defined(__has_attribute) && __has_attribute(enum_extensibility) 141 | # define SWIFT_ENUM_ATTR __attribute__((enum_extensibility(open))) 142 | # else 143 | # define SWIFT_ENUM_ATTR 144 | # endif 145 | #endif 146 | #if !defined(SWIFT_ENUM) 147 | # define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_ATTR SWIFT_ENUM_EXTRA _name : _type 148 | # if __has_feature(generalized_swift_name) 149 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR SWIFT_ENUM_EXTRA _name : _type 150 | # else 151 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) SWIFT_ENUM(_type, _name) 152 | # endif 153 | #endif 154 | #if !defined(SWIFT_UNAVAILABLE) 155 | # define SWIFT_UNAVAILABLE __attribute__((unavailable)) 156 | #endif 157 | #if !defined(SWIFT_UNAVAILABLE_MSG) 158 | # define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) 159 | #endif 160 | #if !defined(SWIFT_AVAILABILITY) 161 | # define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) 162 | #endif 163 | #if !defined(SWIFT_DEPRECATED) 164 | # define SWIFT_DEPRECATED __attribute__((deprecated)) 165 | #endif 166 | #if !defined(SWIFT_DEPRECATED_MSG) 167 | # define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) 168 | #endif 169 | #if __has_feature(attribute_diagnose_if_objc) 170 | # define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) 171 | #else 172 | # define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) 173 | #endif 174 | #if __has_feature(modules) 175 | @import UIKit; 176 | #endif 177 | 178 | #pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" 179 | #pragma clang diagnostic ignored "-Wduplicate-method-arg" 180 | #if __has_warning("-Wpragma-clang-attribute") 181 | # pragma clang diagnostic ignored "-Wpragma-clang-attribute" 182 | #endif 183 | #pragma clang diagnostic ignored "-Wunknown-pragmas" 184 | 185 | SWIFT_MODULE_NAMESPACE_PUSH("PDColorPicker") 186 | @class UIColor; 187 | @class UIFont; 188 | @class NSCoder; 189 | @class NSBundle; 190 | 191 | SWIFT_CLASS("_TtC13PDColorPicker27PDColorPickerViewController") 192 | @interface PDColorPickerViewController : UIViewController 193 | @property (nonatomic, strong) UIColor * _Nonnull tintColor; 194 | @property (nonatomic) BOOL showHexString; 195 | @property (nonatomic, strong) UIFont * _Nonnull font; 196 | @property (nonatomic, strong) UIFont * _Nonnull boldFont; 197 | @property (nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle; 198 | - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; 199 | - (void)viewDidLoad; 200 | - (void)viewDidLayoutSubviews; 201 | - (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil SWIFT_UNAVAILABLE; 202 | @end 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | SWIFT_MODULE_NAMESPACE_POP 213 | #pragma clang diagnostic pop 214 | -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/Headers/PDColorPicker-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double PDColorPickerVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char PDColorPickerVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Examples/PDColorPicker.framework/Info.plist -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/Modules/PDColorPicker.swiftmodule/x86_64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Examples/PDColorPicker.framework/Modules/PDColorPicker.swiftmodule/x86_64.swiftdoc -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/Modules/PDColorPicker.swiftmodule/x86_64.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Examples/PDColorPicker.framework/Modules/PDColorPicker.swiftmodule/x86_64.swiftmodule -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module PDColorPicker { 2 | umbrella header "PDColorPicker-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | 8 | module PDColorPicker.Swift { 9 | header "PDColorPicker-Swift.h" 10 | requires objc 11 | } 12 | -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/PDColorPicker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Examples/PDColorPicker.framework/PDColorPicker -------------------------------------------------------------------------------- /Examples/PDColorPicker.framework/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Headers/PDColorPicker-Swift.h 8 | 9 | lO3ik1N7/8V5llp4GQEoVyYmlIU= 10 | 11 | Headers/PDColorPicker-umbrella.h 12 | 13 | smhmBEU3fSea94A6YCFWHZXgzD4= 14 | 15 | Info.plist 16 | 17 | rVUDG6EJsgovyUYzUaEIgnssHEg= 18 | 19 | Modules/PDColorPicker.swiftmodule/x86_64.swiftdoc 20 | 21 | o1E/9778qCgc802omZoGlVWh9PE= 22 | 23 | Modules/PDColorPicker.swiftmodule/x86_64.swiftmodule 24 | 25 | q4VG3dtC1RE/qt4E0ovci9vZ2b8= 26 | 27 | Modules/module.modulemap 28 | 29 | QCjzQZHagItEqNeHV5yWPWAvuEg= 30 | 31 | 32 | files2 33 | 34 | Headers/PDColorPicker-Swift.h 35 | 36 | hash 37 | 38 | lO3ik1N7/8V5llp4GQEoVyYmlIU= 39 | 40 | hash2 41 | 42 | 9e2I8CbJQ7bsFBXen7RNRhstyQySBbpHwrzSqP9VtC0= 43 | 44 | 45 | Headers/PDColorPicker-umbrella.h 46 | 47 | hash 48 | 49 | smhmBEU3fSea94A6YCFWHZXgzD4= 50 | 51 | hash2 52 | 53 | /pDhioXW40jzPV1DdXhhDwlhrn57r7U79BqZ3Hoi+wQ= 54 | 55 | 56 | Modules/PDColorPicker.swiftmodule/x86_64.swiftdoc 57 | 58 | hash 59 | 60 | o1E/9778qCgc802omZoGlVWh9PE= 61 | 62 | hash2 63 | 64 | 13hvSLqcrXPbxBN2sSLwRIErEROFyVCoTgDfTQGsyso= 65 | 66 | 67 | Modules/PDColorPicker.swiftmodule/x86_64.swiftmodule 68 | 69 | hash 70 | 71 | q4VG3dtC1RE/qt4E0ovci9vZ2b8= 72 | 73 | hash2 74 | 75 | LbQVx8LjsUnMkPilynKVz7rFij7xdhHb0zvp5Bo/UvU= 76 | 77 | 78 | Modules/module.modulemap 79 | 80 | hash 81 | 82 | QCjzQZHagItEqNeHV5yWPWAvuEg= 83 | 84 | hash2 85 | 86 | FLkQ89UtE4ToZsmtT6eFJdReIM+/iHc2WW4OYBwaBog= 87 | 88 | 89 | 90 | rules 91 | 92 | ^ 93 | 94 | ^.*\.lproj/ 95 | 96 | optional 97 | 98 | weight 99 | 1000 100 | 101 | ^.*\.lproj/locversion.plist$ 102 | 103 | omit 104 | 105 | weight 106 | 1100 107 | 108 | ^Base\.lproj/ 109 | 110 | weight 111 | 1010 112 | 113 | ^version.plist$ 114 | 115 | 116 | rules2 117 | 118 | .*\.dSYM($|/) 119 | 120 | weight 121 | 11 122 | 123 | ^ 124 | 125 | weight 126 | 20 127 | 128 | ^(.*/)?\.DS_Store$ 129 | 130 | omit 131 | 132 | weight 133 | 2000 134 | 135 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ 136 | 137 | nested 138 | 139 | weight 140 | 10 141 | 142 | ^.* 143 | 144 | ^.*\.lproj/ 145 | 146 | optional 147 | 148 | weight 149 | 1000 150 | 151 | ^.*\.lproj/locversion.plist$ 152 | 153 | omit 154 | 155 | weight 156 | 1100 157 | 158 | ^Base\.lproj/ 159 | 160 | weight 161 | 1010 162 | 163 | ^Info\.plist$ 164 | 165 | omit 166 | 167 | weight 168 | 20 169 | 170 | ^PkgInfo$ 171 | 172 | omit 173 | 174 | weight 175 | 20 176 | 177 | ^[^/]+$ 178 | 179 | nested 180 | 181 | weight 182 | 10 183 | 184 | ^embedded\.provisionprofile$ 185 | 186 | weight 187 | 20 188 | 189 | ^version\.plist$ 190 | 191 | weight 192 | 20 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /Examples/PDColorPicker.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Examples/PDColorPicker.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/PDColorPicker.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 53; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 524213051F41269B00E3F961 /* PDColorPickerGesturesSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 524213031F41269B00E3F961 /* PDColorPickerGesturesSpec.swift */; }; 11 | 525924A21F56267400065C6F /* PDColorNamedColorsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525924A11F56267400065C6F /* PDColorNamedColorsSpec.swift */; }; 12 | 525ACFAD1F3EB6140027FAA9 /* PDColorSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5296BA091F3E91B200302C4B /* PDColorSpec.swift */; }; 13 | 527231DE1F46607A0042D583 /* PDColorPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 527231DC1F46607A0042D583 /* PDColorPicker.framework */; }; 14 | 527231DF1F46607A0042D583 /* Pods_PDColorPickerExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 527231DD1F46607A0042D583 /* Pods_PDColorPickerExample.framework */; }; 15 | 529F4AD51F401545001F986C /* PDColorPickerViewControllerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 529F4AD31F40152A001F986C /* PDColorPickerViewControllerSpec.swift */; }; 16 | 52AC53DF1F43E555002195AA /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52AC53DD1F43E555002195AA /* Launch Screen.storyboard */; }; 17 | 56220EA0D6B035E160877169 /* Pods_PDColorPickerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F728FE338C04D0141B2583F1 /* Pods_PDColorPickerTests.framework */; }; 18 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 19 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 20 | 607FACDD1AFB9204008FA782 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Assets.xcassets */; }; 21 | E019BD3105D01961B6192803 /* Pods_PDColorPickerExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF615EBCE1515922150D5460 /* Pods_PDColorPickerExample.framework */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 525ACFA71F3EB5D40027FAA9 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 30 | remoteInfo = PDColorPicker_Example; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 1D461239A96A3967AB382BB0 /* Pods-PDColorPickerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerTests/Pods-PDColorPickerTests.debug.xcconfig"; sourceTree = ""; }; 36 | 28AA86B70528828A961CA0E7 /* Pods-PDColorPickerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerTests/Pods-PDColorPickerTests.debug.xcconfig"; sourceTree = ""; }; 37 | 3430C7971B610DDC374B2E63 /* Pods-PDColorPickerExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerExample/Pods-PDColorPickerExample.release.xcconfig"; sourceTree = ""; }; 38 | 367F08CB0AB055783ED8BC6D /* LICENSE.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = LICENSE.md; path = ../LICENSE.md; sourceTree = ""; }; 39 | 40109194995B216C6675B342 /* PDColorPicker.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PDColorPicker.podspec; path = ../PDColorPicker.podspec; sourceTree = ""; }; 40 | 5231B1401F4507B900A5E3B1 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = ""; }; 41 | 524213031F41269B00E3F961 /* PDColorPickerGesturesSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDColorPickerGesturesSpec.swift; sourceTree = ""; }; 42 | 52468F451F453B7D0056ED5D /* PDColorPicker.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = PDColorPicker.xcconfig; path = "Pods/Target Support Files/PDColorPicker/PDColorPicker.xcconfig"; sourceTree = ""; }; 43 | 525924A11F56267400065C6F /* PDColorNamedColorsSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDColorNamedColorsSpec.swift; sourceTree = ""; }; 44 | 525ACFA21F3EB5D40027FAA9 /* PDColorPickerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PDColorPickerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 527231DC1F46607A0042D583 /* PDColorPicker.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PDColorPicker.framework; path = "../../../../Library/Developer/Xcode/DerivedData/PDColorPicker-eiygvurzacmyvvcytbbwmwzltsom/Build/Products/Debug-iphonesimulator/PDColorPicker/PDColorPicker.framework"; sourceTree = ""; }; 46 | 527231DD1F46607A0042D583 /* Pods_PDColorPickerExample.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pods_PDColorPickerExample.framework; path = "../../../../Library/Developer/Xcode/DerivedData/PDColorPicker-eiygvurzacmyvvcytbbwmwzltsom/Build/Products/Debug-iphonesimulator/Pods_PDColorPickerExample.framework"; sourceTree = ""; }; 47 | 5296BA091F3E91B200302C4B /* PDColorSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDColorSpec.swift; sourceTree = ""; usesTabs = 0; }; 48 | 529F4AD31F40152A001F986C /* PDColorPickerViewControllerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDColorPickerViewControllerSpec.swift; sourceTree = ""; }; 49 | 52AC53DE1F43E555002195AA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = "Base.lproj/Launch Screen.storyboard"; sourceTree = ""; }; 50 | 607FACD01AFB9204008FA782 /* PDColorPickerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PDColorPickerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 53 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 54 | 607FACDC1AFB9204008FA782 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 67DD86E83ABA3BF554DE3AF7 /* Pods-PDColorPickerExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerExample/Pods-PDColorPickerExample.debug.xcconfig"; sourceTree = ""; }; 57 | 8D3C231A4F4A801DBE4C6D48 /* Pods-PDColorPickerExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerExample/Pods-PDColorPickerExample.release.xcconfig"; sourceTree = ""; }; 58 | A701B1D85B8845F5060A6951 /* Pods-PDColorPickerExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerExample/Pods-PDColorPickerExample.debug.xcconfig"; sourceTree = ""; }; 59 | CCAC218A190BA1867A5E91AE /* Pods-PDColorPickerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerTests/Pods-PDColorPickerTests.release.xcconfig"; sourceTree = ""; }; 60 | DF615EBCE1515922150D5460 /* Pods_PDColorPickerExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PDColorPickerExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | E868133DF97BC15A784A90E6 /* Pods-PDColorPickerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorPickerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorPickerTests/Pods-PDColorPickerTests.release.xcconfig"; sourceTree = ""; }; 62 | F111FEE45CB0A2BC07676769 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 63 | F728FE338C04D0141B2583F1 /* Pods_PDColorPickerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PDColorPickerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | /* End PBXFileReference section */ 65 | 66 | /* Begin PBXFrameworksBuildPhase section */ 67 | 525ACF9F1F3EB5D40027FAA9 /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | 56220EA0D6B035E160877169 /* Pods_PDColorPickerTests.framework in Frameworks */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | 527231DE1F46607A0042D583 /* PDColorPicker.framework in Frameworks */, 80 | 527231DF1F46607A0042D583 /* Pods_PDColorPickerExample.framework in Frameworks */, 81 | E019BD3105D01961B6192803 /* Pods_PDColorPickerExample.framework in Frameworks */, 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXFrameworksBuildPhase section */ 86 | 87 | /* Begin PBXGroup section */ 88 | 1906D27A24F23BD34AD7A9F6 /* Frameworks */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 527231DD1F46607A0042D583 /* Pods_PDColorPickerExample.framework */, 92 | 527231DC1F46607A0042D583 /* PDColorPicker.framework */, 93 | DF615EBCE1515922150D5460 /* Pods_PDColorPickerExample.framework */, 94 | F728FE338C04D0141B2583F1 /* Pods_PDColorPickerTests.framework */, 95 | ); 96 | name = Frameworks; 97 | path = /Users/paolo/Desktop/iOS/PDColorPicker/Examples; 98 | sourceTree = ""; 99 | }; 100 | 607FACC71AFB9204008FA782 = { 101 | isa = PBXGroup; 102 | children = ( 103 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 104 | 607FACD21AFB9204008FA782 /* Example for PDColorPicker */, 105 | 607FACE81AFB9204008FA782 /* Tests */, 106 | 607FACD11AFB9204008FA782 /* Products */, 107 | C71A1B7414BC9BCD95F608C9 /* Pods */, 108 | 1906D27A24F23BD34AD7A9F6 /* Frameworks */, 109 | ); 110 | indentWidth = 2; 111 | sourceTree = ""; 112 | tabWidth = 2; 113 | usesTabs = 1; 114 | }; 115 | 607FACD11AFB9204008FA782 /* Products */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 607FACD01AFB9204008FA782 /* PDColorPickerExample.app */, 119 | 525ACFA21F3EB5D40027FAA9 /* PDColorPickerTests.xctest */, 120 | ); 121 | name = Products; 122 | sourceTree = ""; 123 | }; 124 | 607FACD21AFB9204008FA782 /* Example for PDColorPicker */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 607FACDC1AFB9204008FA782 /* Assets.xcassets */, 128 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 129 | 607FACD71AFB9204008FA782 /* ViewController.swift */, 130 | 607FACD31AFB9204008FA782 /* Supporting Files */, 131 | ); 132 | name = "Example for PDColorPicker"; 133 | path = PDColorPickerExample; 134 | sourceTree = ""; 135 | }; 136 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 607FACD41AFB9204008FA782 /* Info.plist */, 140 | 52AC53DD1F43E555002195AA /* Launch Screen.storyboard */, 141 | ); 142 | name = "Supporting Files"; 143 | sourceTree = ""; 144 | }; 145 | 607FACE81AFB9204008FA782 /* Tests */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 5296BA091F3E91B200302C4B /* PDColorSpec.swift */, 149 | 525924A11F56267400065C6F /* PDColorNamedColorsSpec.swift */, 150 | 524213031F41269B00E3F961 /* PDColorPickerGesturesSpec.swift */, 151 | 529F4AD31F40152A001F986C /* PDColorPickerViewControllerSpec.swift */, 152 | 607FACE91AFB9204008FA782 /* Supporting Files */, 153 | ); 154 | path = Tests; 155 | sourceTree = ""; 156 | }; 157 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 607FACEA1AFB9204008FA782 /* Info.plist */, 161 | ); 162 | name = "Supporting Files"; 163 | sourceTree = ""; 164 | }; 165 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 40109194995B216C6675B342 /* PDColorPicker.podspec */, 169 | F111FEE45CB0A2BC07676769 /* README.md */, 170 | 5231B1401F4507B900A5E3B1 /* CHANGELOG.md */, 171 | 367F08CB0AB055783ED8BC6D /* LICENSE.md */, 172 | ); 173 | name = "Podspec Metadata"; 174 | sourceTree = ""; 175 | }; 176 | C71A1B7414BC9BCD95F608C9 /* Pods */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | 52468F451F453B7D0056ED5D /* PDColorPicker.xcconfig */, 180 | A701B1D85B8845F5060A6951 /* Pods-PDColorPickerExample.debug.xcconfig */, 181 | 3430C7971B610DDC374B2E63 /* Pods-PDColorPickerExample.release.xcconfig */, 182 | 1D461239A96A3967AB382BB0 /* Pods-PDColorPickerTests.debug.xcconfig */, 183 | CCAC218A190BA1867A5E91AE /* Pods-PDColorPickerTests.release.xcconfig */, 184 | 67DD86E83ABA3BF554DE3AF7 /* Pods-PDColorPickerExample.debug.xcconfig */, 185 | 8D3C231A4F4A801DBE4C6D48 /* Pods-PDColorPickerExample.release.xcconfig */, 186 | 28AA86B70528828A961CA0E7 /* Pods-PDColorPickerTests.debug.xcconfig */, 187 | E868133DF97BC15A784A90E6 /* Pods-PDColorPickerTests.release.xcconfig */, 188 | ); 189 | name = Pods; 190 | sourceTree = ""; 191 | }; 192 | /* End PBXGroup section */ 193 | 194 | /* Begin PBXNativeTarget section */ 195 | 525ACFA11F3EB5D40027FAA9 /* PDColorPickerTests */ = { 196 | isa = PBXNativeTarget; 197 | buildConfigurationList = 525ACFAB1F3EB5D40027FAA9 /* Build configuration list for PBXNativeTarget "PDColorPickerTests" */; 198 | buildPhases = ( 199 | 498CD9AB2E87402C92A0AB0F /* [CP] Check Pods Manifest.lock */, 200 | 525ACF9E1F3EB5D40027FAA9 /* Sources */, 201 | 525ACF9F1F3EB5D40027FAA9 /* Frameworks */, 202 | 525ACFA01F3EB5D40027FAA9 /* Resources */, 203 | DB6621A48D4EB63FE5310AB9 /* [CP] Embed Pods Frameworks */, 204 | ); 205 | buildRules = ( 206 | ); 207 | dependencies = ( 208 | 525ACFA81F3EB5D40027FAA9 /* PBXTargetDependency */, 209 | ); 210 | name = PDColorPickerTests; 211 | productName = PDColorPicker_ExampleTests; 212 | productReference = 525ACFA21F3EB5D40027FAA9 /* PDColorPickerTests.xctest */; 213 | productType = "com.apple.product-type.bundle.unit-test"; 214 | }; 215 | 607FACCF1AFB9204008FA782 /* PDColorPickerExample */ = { 216 | isa = PBXNativeTarget; 217 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "PDColorPickerExample" */; 218 | buildPhases = ( 219 | DCCDF9E1FC81CC3C6DA1FDF5 /* [CP] Check Pods Manifest.lock */, 220 | 607FACCC1AFB9204008FA782 /* Sources */, 221 | 607FACCD1AFB9204008FA782 /* Frameworks */, 222 | 607FACCE1AFB9204008FA782 /* Resources */, 223 | E5A21BC6781D235E834A304E /* [CP] Embed Pods Frameworks */, 224 | ); 225 | buildRules = ( 226 | ); 227 | dependencies = ( 228 | ); 229 | name = PDColorPickerExample; 230 | productName = PDColorPicker; 231 | productReference = 607FACD01AFB9204008FA782 /* PDColorPickerExample.app */; 232 | productType = "com.apple.product-type.application"; 233 | }; 234 | /* End PBXNativeTarget section */ 235 | 236 | /* Begin PBXProject section */ 237 | 607FACC81AFB9204008FA782 /* Project object */ = { 238 | isa = PBXProject; 239 | attributes = { 240 | BuildIndependentTargetsInParallel = YES; 241 | LastSwiftUpdateCheck = 0900; 242 | LastUpgradeCheck = 1430; 243 | ORGANIZATIONNAME = CocoaPods; 244 | TargetAttributes = { 245 | 525ACFA11F3EB5D40027FAA9 = { 246 | CreatedOnToolsVersion = 9.0; 247 | LastSwiftMigration = 1020; 248 | ProvisioningStyle = Automatic; 249 | TestTargetID = 607FACCF1AFB9204008FA782; 250 | }; 251 | 607FACCF1AFB9204008FA782 = { 252 | CreatedOnToolsVersion = 6.3.1; 253 | DevelopmentTeam = UNCTHE43HQ; 254 | LastSwiftMigration = 1020; 255 | }; 256 | }; 257 | }; 258 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "PDColorPickerExample" */; 259 | compatibilityVersion = "Xcode 3.2"; 260 | developmentRegion = English; 261 | hasScannedForEncodings = 0; 262 | knownRegions = ( 263 | English, 264 | en, 265 | Base, 266 | ); 267 | mainGroup = 607FACC71AFB9204008FA782; 268 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 269 | projectDirPath = ""; 270 | projectRoot = ""; 271 | targets = ( 272 | 607FACCF1AFB9204008FA782 /* PDColorPickerExample */, 273 | 525ACFA11F3EB5D40027FAA9 /* PDColorPickerTests */, 274 | ); 275 | }; 276 | /* End PBXProject section */ 277 | 278 | /* Begin PBXResourcesBuildPhase section */ 279 | 525ACFA01F3EB5D40027FAA9 /* Resources */ = { 280 | isa = PBXResourcesBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | ); 284 | runOnlyForDeploymentPostprocessing = 0; 285 | }; 286 | 607FACCE1AFB9204008FA782 /* Resources */ = { 287 | isa = PBXResourcesBuildPhase; 288 | buildActionMask = 2147483647; 289 | files = ( 290 | 52AC53DF1F43E555002195AA /* Launch Screen.storyboard in Resources */, 291 | 607FACDD1AFB9204008FA782 /* Assets.xcassets in Resources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | /* End PBXResourcesBuildPhase section */ 296 | 297 | /* Begin PBXShellScriptBuildPhase section */ 298 | 498CD9AB2E87402C92A0AB0F /* [CP] Check Pods Manifest.lock */ = { 299 | isa = PBXShellScriptBuildPhase; 300 | buildActionMask = 2147483647; 301 | files = ( 302 | ); 303 | inputPaths = ( 304 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 305 | "${PODS_ROOT}/Manifest.lock", 306 | ); 307 | name = "[CP] Check Pods Manifest.lock"; 308 | outputPaths = ( 309 | "$(DERIVED_FILE_DIR)/Pods-PDColorPickerTests-checkManifestLockResult.txt", 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | shellPath = /bin/sh; 313 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 314 | showEnvVarsInLog = 0; 315 | }; 316 | DB6621A48D4EB63FE5310AB9 /* [CP] Embed Pods Frameworks */ = { 317 | isa = PBXShellScriptBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | ); 321 | inputPaths = ( 322 | "${PODS_ROOT}/Target Support Files/Pods-PDColorPickerTests/Pods-PDColorPickerTests-frameworks.sh", 323 | "${BUILT_PRODUCTS_DIR}/Nimble/Nimble.framework", 324 | "${BUILT_PRODUCTS_DIR}/Quick/Quick.framework", 325 | ); 326 | name = "[CP] Embed Pods Frameworks"; 327 | outputPaths = ( 328 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nimble.framework", 329 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Quick.framework", 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | shellPath = /bin/sh; 333 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PDColorPickerTests/Pods-PDColorPickerTests-frameworks.sh\"\n"; 334 | showEnvVarsInLog = 0; 335 | }; 336 | DCCDF9E1FC81CC3C6DA1FDF5 /* [CP] Check Pods Manifest.lock */ = { 337 | isa = PBXShellScriptBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | ); 341 | inputPaths = ( 342 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 343 | "${PODS_ROOT}/Manifest.lock", 344 | ); 345 | name = "[CP] Check Pods Manifest.lock"; 346 | outputPaths = ( 347 | "$(DERIVED_FILE_DIR)/Pods-PDColorPickerExample-checkManifestLockResult.txt", 348 | ); 349 | runOnlyForDeploymentPostprocessing = 0; 350 | shellPath = /bin/sh; 351 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 352 | showEnvVarsInLog = 0; 353 | }; 354 | E5A21BC6781D235E834A304E /* [CP] Embed Pods Frameworks */ = { 355 | isa = PBXShellScriptBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | ); 359 | inputPaths = ( 360 | "${PODS_ROOT}/Target Support Files/Pods-PDColorPickerExample/Pods-PDColorPickerExample-frameworks.sh", 361 | "${BUILT_PRODUCTS_DIR}/PDColorPicker/PDColorPicker.framework", 362 | ); 363 | name = "[CP] Embed Pods Frameworks"; 364 | outputPaths = ( 365 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PDColorPicker.framework", 366 | ); 367 | runOnlyForDeploymentPostprocessing = 0; 368 | shellPath = /bin/sh; 369 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PDColorPickerExample/Pods-PDColorPickerExample-frameworks.sh\"\n"; 370 | showEnvVarsInLog = 0; 371 | }; 372 | /* End PBXShellScriptBuildPhase section */ 373 | 374 | /* Begin PBXSourcesBuildPhase section */ 375 | 525ACF9E1F3EB5D40027FAA9 /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | 525924A21F56267400065C6F /* PDColorNamedColorsSpec.swift in Sources */, 380 | 525ACFAD1F3EB6140027FAA9 /* PDColorSpec.swift in Sources */, 381 | 529F4AD51F401545001F986C /* PDColorPickerViewControllerSpec.swift in Sources */, 382 | 524213051F41269B00E3F961 /* PDColorPickerGesturesSpec.swift in Sources */, 383 | ); 384 | runOnlyForDeploymentPostprocessing = 0; 385 | }; 386 | 607FACCC1AFB9204008FA782 /* Sources */ = { 387 | isa = PBXSourcesBuildPhase; 388 | buildActionMask = 2147483647; 389 | files = ( 390 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 391 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 392 | ); 393 | runOnlyForDeploymentPostprocessing = 0; 394 | }; 395 | /* End PBXSourcesBuildPhase section */ 396 | 397 | /* Begin PBXTargetDependency section */ 398 | 525ACFA81F3EB5D40027FAA9 /* PBXTargetDependency */ = { 399 | isa = PBXTargetDependency; 400 | target = 607FACCF1AFB9204008FA782 /* PDColorPickerExample */; 401 | targetProxy = 525ACFA71F3EB5D40027FAA9 /* PBXContainerItemProxy */; 402 | }; 403 | /* End PBXTargetDependency section */ 404 | 405 | /* Begin PBXVariantGroup section */ 406 | 52AC53DD1F43E555002195AA /* Launch Screen.storyboard */ = { 407 | isa = PBXVariantGroup; 408 | children = ( 409 | 52AC53DE1F43E555002195AA /* Base */, 410 | ); 411 | name = "Launch Screen.storyboard"; 412 | sourceTree = ""; 413 | }; 414 | /* End PBXVariantGroup section */ 415 | 416 | /* Begin XCBuildConfiguration section */ 417 | 525ACFA91F3EB5D40027FAA9 /* Debug */ = { 418 | isa = XCBuildConfiguration; 419 | baseConfigurationReference = 28AA86B70528828A961CA0E7 /* Pods-PDColorPickerTests.debug.xcconfig */; 420 | buildSettings = { 421 | BUNDLE_LOADER = "$(TEST_HOST)"; 422 | CLANG_ANALYZER_NONNULL = YES; 423 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 424 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 425 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 426 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 427 | CODE_SIGN_IDENTITY = "iPhone Developer"; 428 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 429 | CODE_SIGN_STYLE = Automatic; 430 | DEBUG_INFORMATION_FORMAT = dwarf; 431 | DEVELOPMENT_TEAM = ""; 432 | GCC_C_LANGUAGE_STANDARD = gnu11; 433 | INFOPLIST_FILE = Tests/Info.plist; 434 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 435 | LD_RUNPATH_SEARCH_PATHS = ( 436 | "$(inherited)", 437 | "@executable_path/Frameworks", 438 | "@loader_path/Frameworks", 439 | ); 440 | PRODUCT_BUNDLE_IDENTIFIER = "com.paolo.PDColorPicker-ExampleTests"; 441 | PRODUCT_NAME = "$(TARGET_NAME)"; 442 | PROVISIONING_PROFILE_SPECIFIER = ""; 443 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 444 | SWIFT_VERSION = 5.0; 445 | TARGETED_DEVICE_FAMILY = "1,2"; 446 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PDColorPickerExample.app/PDColorPickerExample"; 447 | }; 448 | name = Debug; 449 | }; 450 | 525ACFAA1F3EB5D40027FAA9 /* Release */ = { 451 | isa = XCBuildConfiguration; 452 | baseConfigurationReference = E868133DF97BC15A784A90E6 /* Pods-PDColorPickerTests.release.xcconfig */; 453 | buildSettings = { 454 | BUNDLE_LOADER = "$(TEST_HOST)"; 455 | CLANG_ANALYZER_NONNULL = YES; 456 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 457 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 458 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 459 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 460 | CODE_SIGN_IDENTITY = "iPhone Developer"; 461 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 462 | CODE_SIGN_STYLE = Automatic; 463 | DEVELOPMENT_TEAM = ""; 464 | GCC_C_LANGUAGE_STANDARD = gnu11; 465 | INFOPLIST_FILE = Tests/Info.plist; 466 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 467 | LD_RUNPATH_SEARCH_PATHS = ( 468 | "$(inherited)", 469 | "@executable_path/Frameworks", 470 | "@loader_path/Frameworks", 471 | ); 472 | PRODUCT_BUNDLE_IDENTIFIER = "com.paolo.PDColorPicker-ExampleTests"; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | PROVISIONING_PROFILE_SPECIFIER = ""; 475 | SWIFT_VERSION = 5.0; 476 | TARGETED_DEVICE_FAMILY = "1,2"; 477 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PDColorPickerExample.app/PDColorPickerExample"; 478 | }; 479 | name = Release; 480 | }; 481 | 607FACED1AFB9204008FA782 /* Debug */ = { 482 | isa = XCBuildConfiguration; 483 | buildSettings = { 484 | ALWAYS_SEARCH_USER_PATHS = NO; 485 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 486 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 487 | CLANG_CXX_LIBRARY = "libc++"; 488 | CLANG_ENABLE_MODULES = YES; 489 | CLANG_ENABLE_OBJC_ARC = YES; 490 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 491 | CLANG_WARN_BOOL_CONVERSION = YES; 492 | CLANG_WARN_COMMA = YES; 493 | CLANG_WARN_CONSTANT_CONVERSION = YES; 494 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 495 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 496 | CLANG_WARN_EMPTY_BODY = YES; 497 | CLANG_WARN_ENUM_CONVERSION = YES; 498 | CLANG_WARN_INFINITE_RECURSION = YES; 499 | CLANG_WARN_INT_CONVERSION = YES; 500 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 501 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 502 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 503 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 504 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 505 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 506 | CLANG_WARN_STRICT_PROTOTYPES = YES; 507 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 508 | CLANG_WARN_UNREACHABLE_CODE = YES; 509 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 510 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 511 | COPY_PHASE_STRIP = NO; 512 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 513 | ENABLE_STRICT_OBJC_MSGSEND = YES; 514 | ENABLE_TESTABILITY = YES; 515 | GCC_C_LANGUAGE_STANDARD = gnu99; 516 | GCC_DYNAMIC_NO_PIC = NO; 517 | GCC_NO_COMMON_BLOCKS = YES; 518 | GCC_OPTIMIZATION_LEVEL = 0; 519 | GCC_PREPROCESSOR_DEFINITIONS = ( 520 | "DEBUG=1", 521 | "$(inherited)", 522 | ); 523 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 524 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 525 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 526 | GCC_WARN_UNDECLARED_SELECTOR = YES; 527 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 528 | GCC_WARN_UNUSED_FUNCTION = YES; 529 | GCC_WARN_UNUSED_VARIABLE = YES; 530 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 531 | MTL_ENABLE_DEBUG_INFO = YES; 532 | ONLY_ACTIVE_ARCH = YES; 533 | SDKROOT = iphoneos; 534 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 535 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 536 | SWIFT_VERSION = 4.0; 537 | }; 538 | name = Debug; 539 | }; 540 | 607FACEE1AFB9204008FA782 /* Release */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | ALWAYS_SEARCH_USER_PATHS = NO; 544 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 545 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 546 | CLANG_CXX_LIBRARY = "libc++"; 547 | CLANG_ENABLE_MODULES = YES; 548 | CLANG_ENABLE_OBJC_ARC = YES; 549 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 550 | CLANG_WARN_BOOL_CONVERSION = YES; 551 | CLANG_WARN_COMMA = YES; 552 | CLANG_WARN_CONSTANT_CONVERSION = YES; 553 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 554 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 555 | CLANG_WARN_EMPTY_BODY = YES; 556 | CLANG_WARN_ENUM_CONVERSION = YES; 557 | CLANG_WARN_INFINITE_RECURSION = YES; 558 | CLANG_WARN_INT_CONVERSION = YES; 559 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 560 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 561 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 562 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 563 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 564 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 565 | CLANG_WARN_STRICT_PROTOTYPES = YES; 566 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 567 | CLANG_WARN_UNREACHABLE_CODE = YES; 568 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 569 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 570 | COPY_PHASE_STRIP = NO; 571 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 572 | ENABLE_NS_ASSERTIONS = NO; 573 | ENABLE_STRICT_OBJC_MSGSEND = YES; 574 | GCC_C_LANGUAGE_STANDARD = gnu99; 575 | GCC_NO_COMMON_BLOCKS = YES; 576 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 577 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 578 | GCC_WARN_UNDECLARED_SELECTOR = YES; 579 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 580 | GCC_WARN_UNUSED_FUNCTION = YES; 581 | GCC_WARN_UNUSED_VARIABLE = YES; 582 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 583 | MTL_ENABLE_DEBUG_INFO = NO; 584 | SDKROOT = iphoneos; 585 | SWIFT_COMPILATION_MODE = wholemodule; 586 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 587 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 588 | SWIFT_VERSION = 4.0; 589 | VALIDATE_PRODUCT = YES; 590 | }; 591 | name = Release; 592 | }; 593 | 607FACF01AFB9204008FA782 /* Debug */ = { 594 | isa = XCBuildConfiguration; 595 | baseConfigurationReference = 67DD86E83ABA3BF554DE3AF7 /* Pods-PDColorPickerExample.debug.xcconfig */; 596 | buildSettings = { 597 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 598 | DEVELOPMENT_TEAM = UNCTHE43HQ; 599 | INFOPLIST_FILE = "$(SRCROOT)/PDColorPickerExample/Info.plist"; 600 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 601 | LD_RUNPATH_SEARCH_PATHS = ( 602 | "$(inherited)", 603 | "@executable_path/Frameworks", 604 | ); 605 | MODULE_NAME = ExampleApp; 606 | PRODUCT_BUNDLE_IDENTIFIER = com.paolo.PDColorPickerExample; 607 | PRODUCT_NAME = "$(TARGET_NAME)"; 608 | SWIFT_VERSION = 5.0; 609 | TARGETED_DEVICE_FAMILY = "1,2"; 610 | }; 611 | name = Debug; 612 | }; 613 | 607FACF11AFB9204008FA782 /* Release */ = { 614 | isa = XCBuildConfiguration; 615 | baseConfigurationReference = 8D3C231A4F4A801DBE4C6D48 /* Pods-PDColorPickerExample.release.xcconfig */; 616 | buildSettings = { 617 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 618 | DEVELOPMENT_TEAM = UNCTHE43HQ; 619 | INFOPLIST_FILE = "$(SRCROOT)/PDColorPickerExample/Info.plist"; 620 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 621 | LD_RUNPATH_SEARCH_PATHS = ( 622 | "$(inherited)", 623 | "@executable_path/Frameworks", 624 | ); 625 | MODULE_NAME = ExampleApp; 626 | PRODUCT_BUNDLE_IDENTIFIER = com.paolo.PDColorPickerExample; 627 | PRODUCT_NAME = "$(TARGET_NAME)"; 628 | SWIFT_VERSION = 5.0; 629 | TARGETED_DEVICE_FAMILY = "1,2"; 630 | }; 631 | name = Release; 632 | }; 633 | /* End XCBuildConfiguration section */ 634 | 635 | /* Begin XCConfigurationList section */ 636 | 525ACFAB1F3EB5D40027FAA9 /* Build configuration list for PBXNativeTarget "PDColorPickerTests" */ = { 637 | isa = XCConfigurationList; 638 | buildConfigurations = ( 639 | 525ACFA91F3EB5D40027FAA9 /* Debug */, 640 | 525ACFAA1F3EB5D40027FAA9 /* Release */, 641 | ); 642 | defaultConfigurationIsVisible = 0; 643 | defaultConfigurationName = Release; 644 | }; 645 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "PDColorPickerExample" */ = { 646 | isa = XCConfigurationList; 647 | buildConfigurations = ( 648 | 607FACED1AFB9204008FA782 /* Debug */, 649 | 607FACEE1AFB9204008FA782 /* Release */, 650 | ); 651 | defaultConfigurationIsVisible = 0; 652 | defaultConfigurationName = Release; 653 | }; 654 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "PDColorPickerExample" */ = { 655 | isa = XCConfigurationList; 656 | buildConfigurations = ( 657 | 607FACF01AFB9204008FA782 /* Debug */, 658 | 607FACF11AFB9204008FA782 /* Release */, 659 | ); 660 | defaultConfigurationIsVisible = 0; 661 | defaultConfigurationName = Release; 662 | }; 663 | /* End XCConfigurationList section */ 664 | }; 665 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 666 | } 667 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample.xcodeproj/xcshareddata/xcschemes/PDColorPickerExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 45 | 46 | 52 | 53 | 54 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 77 | 79 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/2017. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | 18 | window = UIWindow(frame: UIScreen.main.bounds) 19 | 20 | window?.rootViewController = ViewController() 21 | window?.makeKeyAndVisible() 22 | 23 | return true 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample/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 | } -------------------------------------------------------------------------------- /Examples/PDColorPickerExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Examples/PDColorPickerExample/Base.lproj/Launch Screen.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 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | PDColorPickerExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Launch Screen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | UIInterfaceOrientationPortraitUpsideDown 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | UIViewControllerBasedStatusBarAppearance 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Examples/PDColorPickerExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/2017. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import PDColorPicker 11 | 12 | class ViewController: UIViewController, Dimmable { 13 | 14 | // Set the status bar style based on the currently selected color 15 | override var preferredStatusBarStyle: UIStatusBarStyle { 16 | return chooseColorButton.titleColor(for: .normal) == .black ? .default : .lightContent 17 | } 18 | 19 | // MARK: - Views 20 | 21 | lazy var chooseColorButton: UIButton = { 22 | let button = UIButton() 23 | 24 | button.setTitle("Tap to choose a color", for: .normal) 25 | button.addTarget(self, action: #selector(chooseColorPressed), for: .touchUpInside) 26 | 27 | return button 28 | }() 29 | 30 | // MARK: - Life Cycle 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | setupView() 35 | } 36 | 37 | // MARK: - Button Targets 38 | 39 | /// Displays example of presenting a PDColorPicker and how to handle result in 40 | /// the completion handler. 41 | @objc func chooseColorPressed() { 42 | let current = view.backgroundColor ?? .red 43 | 44 | /** 45 | Initializes a PDColorPickerViewController with the initial color, 46 | button foreground (tint color), and completion handler. 47 | 48 | The completion returns on the main thread so it is suitable for UI manipulation directly. 49 | 50 | The completion handler gives the new color as an optional PDColor object. 51 | If the user taps **Cancel**, the returned color is `nil`. The color is not `nil` if the 52 | user taps **Save**. 53 | */ 54 | let colorPicker = PDColorPickerViewController(initialColor: current, tintColor: .blue) { 55 | [weak self] newColor in 56 | 57 | // Un-dim the view once the color picker is dismissed 58 | self?.undim() 59 | 60 | // Check to see if the user selected a new color 61 | guard let color = newColor else { return } 62 | 63 | // Use the new color to update the view 64 | self?.view.backgroundColor = color.uiColor 65 | self?.chooseColorButton.setTitleColor(color.appropriateForegroundColor, for: .normal) 66 | 67 | self?.setNeedsStatusBarAppearanceUpdate() 68 | } 69 | 70 | // Dim the presenting view controller for a better appearance 71 | dim() 72 | 73 | // Present the color picker modally 74 | present(colorPicker, animated: true) 75 | } 76 | 77 | // MARK: - Convenience 78 | 79 | private func setupView() { 80 | view.backgroundColor = .red 81 | 82 | view.addSubview(chooseColorButton) 83 | chooseColorButton.translatesAutoresizingMaskIntoConstraints = false 84 | 85 | chooseColorButton.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true 86 | chooseColorButton.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true 87 | chooseColorButton.topAnchor.constraint(equalTo: view.topAnchor).isActive = true 88 | chooseColorButton.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 53; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5231B14F1F452B7200A5E3B1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5231B14E1F452B7200A5E3B1 /* AppDelegate.swift */; }; 11 | 5231B1511F452B7200A5E3B1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5231B1501F452B7200A5E3B1 /* ViewController.swift */; }; 12 | 5231B1561F452B7200A5E3B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5231B1551F452B7200A5E3B1 /* Assets.xcassets */; }; 13 | 52468F4A1F45456A0056ED5D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52468F481F45456A0056ED5D /* LaunchScreen.storyboard */; }; 14 | 935B146BC8241B78498814C7 /* Pods_PDColorReceiverExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9160414BB1A1284A21AC7696 /* Pods_PDColorReceiverExample.framework */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 49B248CCCA8884F3AA8D830D /* Pods-PDColorReceiverExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorReceiverExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorReceiverExample/Pods-PDColorReceiverExample.debug.xcconfig"; sourceTree = ""; }; 19 | 5231B14B1F452B7200A5E3B1 /* PDColorReceiverExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PDColorReceiverExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 5231B14E1F452B7200A5E3B1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 21 | 5231B1501F452B7200A5E3B1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 22 | 5231B1551F452B7200A5E3B1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 23 | 5231B15A1F452B7300A5E3B1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | 52468F491F45456A0056ED5D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = PDColorReceiverExample/Base.lproj/LaunchScreen.storyboard; sourceTree = SOURCE_ROOT; }; 25 | 9160414BB1A1284A21AC7696 /* Pods_PDColorReceiverExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PDColorReceiverExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | A36293F547877D2F71B12D0F /* Pods-PDColorReceiverExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PDColorReceiverExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-PDColorReceiverExample/Pods-PDColorReceiverExample.release.xcconfig"; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 5231B1481F452B7200A5E3B1 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | 935B146BC8241B78498814C7 /* Pods_PDColorReceiverExample.framework in Frameworks */, 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 0CC7BBAD57E7F21D88559129 /* Pods */ = { 42 | isa = PBXGroup; 43 | children = ( 44 | 49B248CCCA8884F3AA8D830D /* Pods-PDColorReceiverExample.debug.xcconfig */, 45 | A36293F547877D2F71B12D0F /* Pods-PDColorReceiverExample.release.xcconfig */, 46 | ); 47 | name = Pods; 48 | sourceTree = ""; 49 | }; 50 | 5231B1421F452B7200A5E3B1 = { 51 | isa = PBXGroup; 52 | children = ( 53 | 5231B14D1F452B7200A5E3B1 /* PDColorReceiverExample */, 54 | 5231B14C1F452B7200A5E3B1 /* Products */, 55 | 0CC7BBAD57E7F21D88559129 /* Pods */, 56 | F672F320188CB0C09C1D813D /* Frameworks */, 57 | ); 58 | indentWidth = 2; 59 | sourceTree = ""; 60 | tabWidth = 2; 61 | usesTabs = 1; 62 | }; 63 | 5231B14C1F452B7200A5E3B1 /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 5231B14B1F452B7200A5E3B1 /* PDColorReceiverExample.app */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 5231B14D1F452B7200A5E3B1 /* PDColorReceiverExample */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 5231B1551F452B7200A5E3B1 /* Assets.xcassets */, 75 | 5231B14E1F452B7200A5E3B1 /* AppDelegate.swift */, 76 | 5231B1501F452B7200A5E3B1 /* ViewController.swift */, 77 | 52468F461F453D8B0056ED5D /* Supporting Files */, 78 | ); 79 | path = PDColorReceiverExample; 80 | sourceTree = ""; 81 | }; 82 | 52468F461F453D8B0056ED5D /* Supporting Files */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 5231B15A1F452B7300A5E3B1 /* Info.plist */, 86 | 52468F481F45456A0056ED5D /* LaunchScreen.storyboard */, 87 | ); 88 | name = "Supporting Files"; 89 | sourceTree = ""; 90 | }; 91 | F672F320188CB0C09C1D813D /* Frameworks */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 9160414BB1A1284A21AC7696 /* Pods_PDColorReceiverExample.framework */, 95 | ); 96 | name = Frameworks; 97 | sourceTree = ""; 98 | }; 99 | /* End PBXGroup section */ 100 | 101 | /* Begin PBXNativeTarget section */ 102 | 5231B14A1F452B7200A5E3B1 /* PDColorReceiverExample */ = { 103 | isa = PBXNativeTarget; 104 | buildConfigurationList = 5231B15D1F452B7300A5E3B1 /* Build configuration list for PBXNativeTarget "PDColorReceiverExample" */; 105 | buildPhases = ( 106 | DC694C4B3E89C82B67309C36 /* [CP] Check Pods Manifest.lock */, 107 | 5231B1471F452B7200A5E3B1 /* Sources */, 108 | 5231B1481F452B7200A5E3B1 /* Frameworks */, 109 | 5231B1491F452B7200A5E3B1 /* Resources */, 110 | FC87C049B47BE8C63928682E /* [CP] Embed Pods Frameworks */, 111 | ); 112 | buildRules = ( 113 | ); 114 | dependencies = ( 115 | ); 116 | name = PDColorReceiverExample; 117 | productName = PDColorReceiverExample; 118 | productReference = 5231B14B1F452B7200A5E3B1 /* PDColorReceiverExample.app */; 119 | productType = "com.apple.product-type.application"; 120 | }; 121 | /* End PBXNativeTarget section */ 122 | 123 | /* Begin PBXProject section */ 124 | 5231B1431F452B7200A5E3B1 /* Project object */ = { 125 | isa = PBXProject; 126 | attributes = { 127 | BuildIndependentTargetsInParallel = YES; 128 | LastSwiftUpdateCheck = 0900; 129 | LastUpgradeCheck = 1430; 130 | ORGANIZATIONNAME = "Paolo Di Lorenzo"; 131 | TargetAttributes = { 132 | 5231B14A1F452B7200A5E3B1 = { 133 | CreatedOnToolsVersion = 9.0; 134 | LastSwiftMigration = 0900; 135 | }; 136 | }; 137 | }; 138 | buildConfigurationList = 5231B1461F452B7200A5E3B1 /* Build configuration list for PBXProject "PDColorReceiverExample" */; 139 | compatibilityVersion = "Xcode 8.0"; 140 | developmentRegion = en; 141 | hasScannedForEncodings = 0; 142 | knownRegions = ( 143 | en, 144 | Base, 145 | ); 146 | mainGroup = 5231B1421F452B7200A5E3B1; 147 | productRefGroup = 5231B14C1F452B7200A5E3B1 /* Products */; 148 | projectDirPath = ""; 149 | projectRoot = ""; 150 | targets = ( 151 | 5231B14A1F452B7200A5E3B1 /* PDColorReceiverExample */, 152 | ); 153 | }; 154 | /* End PBXProject section */ 155 | 156 | /* Begin PBXResourcesBuildPhase section */ 157 | 5231B1491F452B7200A5E3B1 /* Resources */ = { 158 | isa = PBXResourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | 5231B1561F452B7200A5E3B1 /* Assets.xcassets in Resources */, 162 | 52468F4A1F45456A0056ED5D /* LaunchScreen.storyboard in Resources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXResourcesBuildPhase section */ 167 | 168 | /* Begin PBXShellScriptBuildPhase section */ 169 | DC694C4B3E89C82B67309C36 /* [CP] Check Pods Manifest.lock */ = { 170 | isa = PBXShellScriptBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | ); 174 | inputPaths = ( 175 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 176 | "${PODS_ROOT}/Manifest.lock", 177 | ); 178 | name = "[CP] Check Pods Manifest.lock"; 179 | outputPaths = ( 180 | "$(DERIVED_FILE_DIR)/Pods-PDColorReceiverExample-checkManifestLockResult.txt", 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 185 | showEnvVarsInLog = 0; 186 | }; 187 | FC87C049B47BE8C63928682E /* [CP] Embed Pods Frameworks */ = { 188 | isa = PBXShellScriptBuildPhase; 189 | buildActionMask = 2147483647; 190 | files = ( 191 | ); 192 | inputPaths = ( 193 | "${PODS_ROOT}/Target Support Files/Pods-PDColorReceiverExample/Pods-PDColorReceiverExample-frameworks.sh", 194 | "${BUILT_PRODUCTS_DIR}/PDColorPicker/PDColorPicker.framework", 195 | ); 196 | name = "[CP] Embed Pods Frameworks"; 197 | outputPaths = ( 198 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PDColorPicker.framework", 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | shellPath = /bin/sh; 202 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PDColorReceiverExample/Pods-PDColorReceiverExample-frameworks.sh\"\n"; 203 | showEnvVarsInLog = 0; 204 | }; 205 | /* End PBXShellScriptBuildPhase section */ 206 | 207 | /* Begin PBXSourcesBuildPhase section */ 208 | 5231B1471F452B7200A5E3B1 /* Sources */ = { 209 | isa = PBXSourcesBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | 5231B1511F452B7200A5E3B1 /* ViewController.swift in Sources */, 213 | 5231B14F1F452B7200A5E3B1 /* AppDelegate.swift in Sources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXSourcesBuildPhase section */ 218 | 219 | /* Begin PBXVariantGroup section */ 220 | 52468F481F45456A0056ED5D /* LaunchScreen.storyboard */ = { 221 | isa = PBXVariantGroup; 222 | children = ( 223 | 52468F491F45456A0056ED5D /* Base */, 224 | ); 225 | name = LaunchScreen.storyboard; 226 | sourceTree = ""; 227 | }; 228 | /* End PBXVariantGroup section */ 229 | 230 | /* Begin XCBuildConfiguration section */ 231 | 5231B15B1F452B7300A5E3B1 /* Debug */ = { 232 | isa = XCBuildConfiguration; 233 | buildSettings = { 234 | ALWAYS_SEARCH_USER_PATHS = NO; 235 | CLANG_ANALYZER_NONNULL = YES; 236 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 238 | CLANG_CXX_LIBRARY = "libc++"; 239 | CLANG_ENABLE_MODULES = YES; 240 | CLANG_ENABLE_OBJC_ARC = YES; 241 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 242 | CLANG_WARN_BOOL_CONVERSION = YES; 243 | CLANG_WARN_COMMA = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 246 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 247 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 248 | CLANG_WARN_EMPTY_BODY = YES; 249 | CLANG_WARN_ENUM_CONVERSION = YES; 250 | CLANG_WARN_INFINITE_RECURSION = YES; 251 | CLANG_WARN_INT_CONVERSION = YES; 252 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 253 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 254 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 256 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 261 | CLANG_WARN_UNREACHABLE_CODE = YES; 262 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 263 | CODE_SIGN_IDENTITY = "iPhone Developer"; 264 | COPY_PHASE_STRIP = NO; 265 | DEBUG_INFORMATION_FORMAT = dwarf; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | ENABLE_TESTABILITY = YES; 268 | GCC_C_LANGUAGE_STANDARD = gnu11; 269 | GCC_DYNAMIC_NO_PIC = NO; 270 | GCC_NO_COMMON_BLOCKS = YES; 271 | GCC_OPTIMIZATION_LEVEL = 0; 272 | GCC_PREPROCESSOR_DEFINITIONS = ( 273 | "DEBUG=1", 274 | "$(inherited)", 275 | ); 276 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 277 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 278 | GCC_WARN_UNDECLARED_SELECTOR = YES; 279 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 280 | GCC_WARN_UNUSED_FUNCTION = YES; 281 | GCC_WARN_UNUSED_VARIABLE = YES; 282 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 283 | MTL_ENABLE_DEBUG_INFO = YES; 284 | ONLY_ACTIVE_ARCH = YES; 285 | SDKROOT = iphoneos; 286 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 287 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 288 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 289 | SWIFT_VERSION = 4.0; 290 | }; 291 | name = Debug; 292 | }; 293 | 5231B15C1F452B7300A5E3B1 /* Release */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | ALWAYS_SEARCH_USER_PATHS = NO; 297 | CLANG_ANALYZER_NONNULL = YES; 298 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 299 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 300 | CLANG_CXX_LIBRARY = "libc++"; 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 304 | CLANG_WARN_BOOL_CONVERSION = YES; 305 | CLANG_WARN_COMMA = YES; 306 | CLANG_WARN_CONSTANT_CONVERSION = YES; 307 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 308 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 309 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 310 | CLANG_WARN_EMPTY_BODY = YES; 311 | CLANG_WARN_ENUM_CONVERSION = YES; 312 | CLANG_WARN_INFINITE_RECURSION = YES; 313 | CLANG_WARN_INT_CONVERSION = YES; 314 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 315 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 316 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 317 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 318 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 319 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 320 | CLANG_WARN_STRICT_PROTOTYPES = YES; 321 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 322 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 323 | CLANG_WARN_UNREACHABLE_CODE = YES; 324 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 325 | CODE_SIGN_IDENTITY = "iPhone Developer"; 326 | COPY_PHASE_STRIP = NO; 327 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 328 | ENABLE_NS_ASSERTIONS = NO; 329 | ENABLE_STRICT_OBJC_MSGSEND = YES; 330 | GCC_C_LANGUAGE_STANDARD = gnu11; 331 | GCC_NO_COMMON_BLOCKS = YES; 332 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 333 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 334 | GCC_WARN_UNDECLARED_SELECTOR = YES; 335 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 336 | GCC_WARN_UNUSED_FUNCTION = YES; 337 | GCC_WARN_UNUSED_VARIABLE = YES; 338 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 339 | MTL_ENABLE_DEBUG_INFO = NO; 340 | SDKROOT = iphoneos; 341 | SWIFT_COMPILATION_MODE = wholemodule; 342 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 343 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 344 | SWIFT_VERSION = 4.0; 345 | VALIDATE_PRODUCT = YES; 346 | }; 347 | name = Release; 348 | }; 349 | 5231B15E1F452B7300A5E3B1 /* Debug */ = { 350 | isa = XCBuildConfiguration; 351 | baseConfigurationReference = 49B248CCCA8884F3AA8D830D /* Pods-PDColorReceiverExample.debug.xcconfig */; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | DEVELOPMENT_TEAM = UNCTHE43HQ; 355 | INFOPLIST_FILE = PDColorReceiverExample/Info.plist; 356 | LD_RUNPATH_SEARCH_PATHS = ( 357 | "$(inherited)", 358 | "@executable_path/Frameworks", 359 | ); 360 | PRODUCT_BUNDLE_IDENTIFIER = com.paolo.PDColorReceiverExample; 361 | PRODUCT_NAME = "$(TARGET_NAME)"; 362 | SWIFT_VERSION = 4.2; 363 | TARGETED_DEVICE_FAMILY = 2; 364 | }; 365 | name = Debug; 366 | }; 367 | 5231B15F1F452B7300A5E3B1 /* Release */ = { 368 | isa = XCBuildConfiguration; 369 | baseConfigurationReference = A36293F547877D2F71B12D0F /* Pods-PDColorReceiverExample.release.xcconfig */; 370 | buildSettings = { 371 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 372 | DEVELOPMENT_TEAM = UNCTHE43HQ; 373 | INFOPLIST_FILE = PDColorReceiverExample/Info.plist; 374 | LD_RUNPATH_SEARCH_PATHS = ( 375 | "$(inherited)", 376 | "@executable_path/Frameworks", 377 | ); 378 | PRODUCT_BUNDLE_IDENTIFIER = com.paolo.PDColorReceiverExample; 379 | PRODUCT_NAME = "$(TARGET_NAME)"; 380 | SWIFT_VERSION = 4.2; 381 | TARGETED_DEVICE_FAMILY = 2; 382 | }; 383 | name = Release; 384 | }; 385 | /* End XCBuildConfiguration section */ 386 | 387 | /* Begin XCConfigurationList section */ 388 | 5231B1461F452B7200A5E3B1 /* Build configuration list for PBXProject "PDColorReceiverExample" */ = { 389 | isa = XCConfigurationList; 390 | buildConfigurations = ( 391 | 5231B15B1F452B7300A5E3B1 /* Debug */, 392 | 5231B15C1F452B7300A5E3B1 /* Release */, 393 | ); 394 | defaultConfigurationIsVisible = 0; 395 | defaultConfigurationName = Release; 396 | }; 397 | 5231B15D1F452B7300A5E3B1 /* Build configuration list for PBXNativeTarget "PDColorReceiverExample" */ = { 398 | isa = XCConfigurationList; 399 | buildConfigurations = ( 400 | 5231B15E1F452B7300A5E3B1 /* Debug */, 401 | 5231B15F1F452B7300A5E3B1 /* Release */, 402 | ); 403 | defaultConfigurationIsVisible = 0; 404 | defaultConfigurationName = Release; 405 | }; 406 | /* End XCConfigurationList section */ 407 | }; 408 | rootObject = 5231B1431F452B7200A5E3B1 /* Project object */; 409 | } 410 | -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample.xcodeproj/xcshareddata/xcschemes/PDColorReceiverExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PDColorReceiverExample 4 | // 5 | // Created by Paolo Di Lorenzo on 8/16/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | 18 | window = UIWindow(frame: UIScreen.main.bounds) 19 | 20 | window?.rootViewController = ViewController() 21 | window?.makeKeyAndVisible() 22 | 23 | return true 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample/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" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample/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 | -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | UIInterfaceOrientationPortraitUpsideDown 35 | 36 | UISupportedInterfaceOrientations~ipad 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationPortraitUpsideDown 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Examples/PDColorReceiverExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // PDColorReceiverExample 4 | // 5 | // Created by Paolo Di Lorenzo on 8/16/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import PDColorPicker 11 | 12 | class ViewController: UIViewController { 13 | 14 | // MARK: - Subviews 15 | 16 | lazy var colorLabel: UILabel = { 17 | let label = UILabel() 18 | 19 | label.font = UIFont.systemFont(ofSize: 72, weight: .light) 20 | label.adjustsFontSizeToFitWidth = true 21 | label.minimumScaleFactor = 0.25 22 | label.text = "Drag a color here!" 23 | 24 | return label 25 | }() 26 | 27 | // MARK: - Life Cycle 28 | 29 | override func viewDidLoad() { 30 | super.viewDidLoad() 31 | 32 | view.backgroundColor = .white 33 | 34 | setupViews() 35 | 36 | if #available(iOS 11.0, *) { 37 | let dropInteraction = UIDropInteraction(delegate: self) 38 | view.addInteraction(dropInteraction) 39 | } 40 | } 41 | 42 | private func setupViews() { 43 | view.addSubview(colorLabel) 44 | colorLabel.translatesAutoresizingMaskIntoConstraints = false 45 | 46 | colorLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 47 | colorLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 48 | colorLabel.widthAnchor.constraint(lessThanOrEqualTo: view.widthAnchor, multiplier: 0.9, constant: 0).isActive = true 49 | } 50 | 51 | } 52 | 53 | // MARK: - UIDropInteraction 54 | @available(iOS 11.0, *) 55 | extension ViewController: UIDropInteractionDelegate { 56 | func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { 57 | return session.canLoadObjects(ofClass: UIColor.self) 58 | } 59 | 60 | func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal { 61 | return UIDropProposal(operation: .copy) 62 | } 63 | 64 | func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { 65 | session.loadObjects(ofClass: UIColor.self) { 66 | guard let color = $0.first as? UIColor else { return } 67 | let pdColor = PDColor(color: color) 68 | 69 | self.view.backgroundColor = color 70 | self.colorLabel.text = pdColor.hex 71 | self.colorLabel.textColor = pdColor.appropriateForegroundColor 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Examples/Podfile: -------------------------------------------------------------------------------- 1 | workspace 'PDColorPicker.xcworkspace' 2 | platform :ios, '11.0' 3 | 4 | use_frameworks! 5 | 6 | def shared_pods 7 | pod 'PDColorPicker', :path => '../' 8 | end 9 | 10 | project 'PDColorPickerExample.xcodeproj' 11 | project 'PDColorReceiverExample.xcodeproj' 12 | 13 | target 'PDColorPickerExample' do 14 | project 'PDColorPickerExample.xcodeproj' 15 | shared_pods 16 | 17 | target 'PDColorPickerTests' do 18 | inherit! :search_paths 19 | 20 | pod 'Quick' 21 | pod 'Nimble', :inhibit_warnings => true 22 | end 23 | end 24 | 25 | target 'PDColorReceiverExample' do 26 | project 'PDColorReceiverExample.xcodeproj' 27 | shared_pods 28 | end 29 | -------------------------------------------------------------------------------- /Examples/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Nimble (10.0.0) 3 | - PDColorPicker (0.8.3) 4 | - Quick (5.0.1) 5 | 6 | DEPENDENCIES: 7 | - Nimble 8 | - PDColorPicker (from `../`) 9 | - Quick 10 | 11 | SPEC REPOS: 12 | trunk: 13 | - Nimble 14 | - Quick 15 | 16 | EXTERNAL SOURCES: 17 | PDColorPicker: 18 | :path: "../" 19 | 20 | SPEC CHECKSUMS: 21 | Nimble: 5316ef81a170ce87baf72dd961f22f89a602ff84 22 | PDColorPicker: 3fe3ccb5103f82df05b15b618754151c8ed8f84c 23 | Quick: 749aa754fd1e7d984f2000fe051e18a3a9809179 24 | 25 | PODFILE CHECKSUM: 4cb3a810018214ba0ee635a1bbd1bbb183527100 26 | 27 | COCOAPODS: 1.12.1 28 | -------------------------------------------------------------------------------- /Examples/Tests/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 | -------------------------------------------------------------------------------- /Examples/Tests/PDColorNamedColorsSpec.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorNamedColorsSpec.swift 3 | // PDColorPickerTests 4 | // 5 | // Created by Paolo Di Lorenzo on 8/29/17. 6 | // Copyright © 2017 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Quick 10 | import Nimble 11 | import PDColorPicker 12 | 13 | class PDColorNamedColorsSpec: QuickSpec { 14 | 15 | override func spec() { 16 | describe("red") { 17 | it("produces correct RGB values") { 18 | let rgb = PDColor.red.rgba 19 | 20 | expect(rgb.r).to(equal(1)) 21 | expect(rgb.g).to(equal(0)) 22 | expect(rgb.b).to(equal(0)) 23 | } 24 | 25 | it("produces correct hex string") { 26 | expect(PDColor.red.hex).to(equal("#ff0000")) 27 | } 28 | } 29 | 30 | describe("orange") { 31 | it("produces correct RGB values") { 32 | let rgb = PDColor.orange.rgba 33 | 34 | expect(rgb.r).to(equal(1)) 35 | expect(rgb.g).to(equal(0.5)) 36 | expect(rgb.b).to(equal(0)) 37 | } 38 | 39 | it("produces correct hex string") { 40 | expect(PDColor.orange.hex).to(equal("#ff7f00")) 41 | } 42 | } 43 | 44 | describe("yellow") { 45 | it("produces correct RGB values") { 46 | let rgb = PDColor.yellow.rgba 47 | 48 | expect(rgb.r).to(equal(1)) 49 | expect(rgb.g).to(equal(1)) 50 | expect(rgb.b).to(equal(0)) 51 | } 52 | 53 | it("produces correct hex string") { 54 | expect(PDColor.yellow.hex).to(equal("#ffff00")) 55 | } 56 | } 57 | 58 | describe("yellowGreen") { 59 | it("produces correct RGB values") { 60 | let rgb = PDColor.yellowGreen.rgba 61 | 62 | expect(rgb.r).to(equal(0.5)) 63 | expect(rgb.g).to(equal(1)) 64 | expect(rgb.b).to(equal(0)) 65 | } 66 | 67 | it("produces correct hex string") { 68 | expect(PDColor.yellowGreen.hex).to(equal("#7fff00")) 69 | } 70 | } 71 | 72 | describe("green") { 73 | it("produces correct RGB values") { 74 | let rgb = PDColor.green.rgba 75 | 76 | expect(rgb.r).to(equal(0)) 77 | expect(rgb.g).to(equal(1)) 78 | expect(rgb.b).to(equal(0)) 79 | } 80 | 81 | it("produces correct hex string") { 82 | expect(PDColor.green.hex).to(equal("#00ff00")) 83 | } 84 | } 85 | 86 | describe("cyan") { 87 | it("produces correct RGB values") { 88 | let rgb = PDColor.cyan.rgba 89 | 90 | expect(rgb.r).to(equal(0)) 91 | expect(rgb.g).to(equal(1)) 92 | expect(rgb.b).to(equal(1)) 93 | } 94 | 95 | it("produces correct hex string") { 96 | expect(PDColor.cyan.hex).to(equal("#00ffff")) 97 | } 98 | } 99 | 100 | describe("azure") { 101 | it("produces correct RGB values") { 102 | let rgb = PDColor.azure.rgba 103 | 104 | expect(rgb.r).to(equal(0)) 105 | expect(rgb.g).to(equal(0.5)) 106 | expect(rgb.b).to(equal(1)) 107 | } 108 | 109 | it("produces correct hex string") { 110 | expect(PDColor.azure.hex).to(equal("#007fff")) 111 | } 112 | } 113 | 114 | describe("blue") { 115 | it("produces correct RGB values") { 116 | let rgb = PDColor.blue.rgba 117 | 118 | expect(rgb.r).to(equal(0)) 119 | expect(rgb.g).to(equal(0)) 120 | expect(rgb.b).to(equal(1)) 121 | } 122 | 123 | it("produces correct hex string") { 124 | expect(PDColor.blue.hex).to(equal("#0000ff")) 125 | } 126 | } 127 | 128 | describe("purple") { 129 | it("produces correct RGB values") { 130 | let rgb = PDColor.purple.rgba 131 | 132 | expect(rgb.r).to(equal(0.5)) 133 | expect(rgb.g).to(equal(0)) 134 | expect(rgb.b).to(equal(1)) 135 | } 136 | 137 | it("produces correct hex string") { 138 | expect(PDColor.purple.hex).to(equal("#7f00ff")) 139 | } 140 | } 141 | 142 | describe("magenta") { 143 | it("produces correct RGB values") { 144 | let rgb = PDColor.magenta.rgba 145 | 146 | expect(rgb.r).to(equal(1)) 147 | expect(rgb.g).to(equal(0)) 148 | expect(rgb.b).to(equal(1)) 149 | } 150 | 151 | it("produces correct hex string") { 152 | expect(PDColor.magenta.hex).to(equal("#ff00ff")) 153 | } 154 | } 155 | 156 | describe("pink") { 157 | it("produces correct RGB values") { 158 | let rgb = PDColor.pink.rgba 159 | 160 | expect(rgb.r).to(equal(1)) 161 | expect(rgb.g).to(equal(0)) 162 | expect(rgb.b).to(equal(0.5)) 163 | } 164 | 165 | it("produces correct hex string") { 166 | expect(PDColor.pink.hex).to(equal("#ff007f")) 167 | } 168 | } 169 | 170 | describe("white") { 171 | it("produces correct RGB values") { 172 | let rgb = PDColor.white.rgba 173 | 174 | expect(rgb.r).to(equal(1)) 175 | expect(rgb.g).to(equal(1)) 176 | expect(rgb.b).to(equal(1)) 177 | } 178 | 179 | it("produces correct hex string") { 180 | expect(PDColor.white.hex).to(equal("#ffffff")) 181 | } 182 | } 183 | 184 | describe("black") { 185 | it("produces correct RGB values") { 186 | let rgb = PDColor.black.rgba 187 | 188 | expect(rgb.r).to(equal(0)) 189 | expect(rgb.g).to(equal(0)) 190 | expect(rgb.b).to(equal(0)) 191 | } 192 | 193 | it("produces correct hex string") { 194 | expect(PDColor.black.hex).to(equal("#000000")) 195 | } 196 | } 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /Examples/Tests/PDColorPickerGesturesSpec.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorPickerGesturesSpec.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/13/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import Quick 10 | import Nimble 11 | @testable import PDColorPicker 12 | 13 | class PDColorPickerGesturesSpec: QuickSpec { 14 | 15 | override func spec() { 16 | var vc: UIViewController! 17 | var window: UIWindow! 18 | 19 | beforeEach { 20 | window = UIWindow(frame: UIScreen.main.bounds) 21 | vc = UIViewController() 22 | 23 | window.rootViewController = vc 24 | window.makeKeyAndVisible() 25 | } 26 | 27 | describe("PDColorPickerGridView gestures") { 28 | var colorPickerVC: PDColorPickerViewController! 29 | var colorPickerView: PDColorPickerGridView! 30 | var panRecognizer: PDPanGestureRecognizer! 31 | var tapRecognizer: PDTapGestureRecognizer! 32 | 33 | beforeEach { 34 | colorPickerVC = PDColorPickerViewController(initialColor: .red) 35 | colorPickerView = colorPickerVC.colorPickerView 36 | panRecognizer = colorPickerView.panRecognizer 37 | tapRecognizer = colorPickerView.tapRecognizer 38 | 39 | waitUntil { done in 40 | vc.present(colorPickerVC, animated: true, completion: done) 41 | } 42 | 43 | sleep(1) // make sure the view is fully loaded 44 | } 45 | 46 | afterEach { 47 | waitUntil { done in 48 | vc.dismiss(animated: true, completion: done) 49 | } 50 | 51 | sleep(1) // make sure the view is fully dismissed before starting next test 52 | } 53 | 54 | context("when the pan gesture begins") { 55 | it("sets the correct saturation and brightness values") { 56 | panRecognizer.performTouch(location: .zero, translation: nil, state: .began) 57 | panRecognizer.performTouch(location: colorPickerView.center, translation: nil, state: .changed) 58 | 59 | expect(colorPickerVC.currentColor.s).to(equal(0.5)) 60 | expect(colorPickerVC.currentColor.b).to(equal(0.5)) 61 | } 62 | } 63 | 64 | context("when the view is panned horizontally") { 65 | it("changes the saturation value") { 66 | // move 1/4 of the view width to the right 67 | let x = colorPickerView.bounds.width / 4 68 | let location = CGPoint(x: x, y: 0) 69 | 70 | panRecognizer.performTouch(location: .zero, translation: nil, state: .began) 71 | panRecognizer.performTouch(location: location, translation: nil, state: .changed) 72 | 73 | expect(colorPickerVC.currentColor.s).toEventually(equal(0.75)) 74 | expect(colorPickerView.sliderCircleX.constant).toEventually(equal(x)) 75 | } 76 | } 77 | 78 | context("when the view is panned vertically") { 79 | it("changes the brightness value") { 80 | // move 1/4 of the view height downward 81 | let y = colorPickerView.bounds.height / 4 82 | let offset = colorPickerView.visibilityOffset 83 | let location = CGPoint(x: 0, y: y) 84 | 85 | panRecognizer.performTouch(location: .zero, translation: nil, state: .began) 86 | panRecognizer.performTouch(location: location, translation: nil, state: .changed) 87 | 88 | expect(colorPickerVC.currentColor.b).to(equal(0.75)) 89 | expect(colorPickerView.sliderCircleY.constant).to(equal(y - offset)) 90 | } 91 | } 92 | 93 | context("when the pan gesture ends") { 94 | it("returns the slider circle to the original state") { 95 | panRecognizer.performTouch(location: colorPickerView.center, translation: nil, state: .began) 96 | panRecognizer.performTouch(location: nil, translation: nil, state: .ended) 97 | 98 | expect(colorPickerView.sliderCircle.transform).to(equal(CGAffineTransform.identity)) 99 | expect(colorPickerView.sliderCircle.backgroundColor).to(equal(UIColor.white.withAlphaComponent(0.6))) 100 | } 101 | } 102 | 103 | context("when the view is tapped") { 104 | it("changes the brightness and saturation values") { 105 | tapRecognizer.performTouch(location: colorPickerView.center, state: .began) 106 | 107 | expect(colorPickerVC.currentColor.s).to(equal(0.5)) 108 | expect(colorPickerVC.currentColor.b).to(equal(0.5)) 109 | } 110 | } 111 | } 112 | 113 | describe("PDColorPickerSliderView gestures") { 114 | var colorPickerVC: PDColorPickerViewController! 115 | var colorSliderView: PDColorPickerSliderView! 116 | var panRecognizer: PDPanGestureRecognizer! 117 | var tapRecognizer: PDTapGestureRecognizer! 118 | 119 | beforeEach { 120 | colorPickerVC = PDColorPickerViewController(initialColor: .red) 121 | colorSliderView = colorPickerVC.colorSliderView 122 | panRecognizer = colorSliderView.panRecognizer 123 | tapRecognizer = colorSliderView.tapRecognizer 124 | 125 | waitUntil { done in 126 | vc.present(colorPickerVC, animated: true, completion: done) 127 | } 128 | 129 | sleep(1) // make sure the view is fully loaded 130 | } 131 | 132 | afterEach { 133 | waitUntil { done in 134 | vc.dismiss(animated: true, completion: done) 135 | } 136 | 137 | sleep(1) // make sure the view is fully dismissed 138 | } 139 | 140 | context("when the view is panned horizontally") { 141 | it("changes the hue value") { 142 | // move 1/4 of the view width to the right 143 | let x = colorSliderView.bounds.width / 4 144 | let location = CGPoint(x: x, y: 0) 145 | 146 | panRecognizer.performTouch(location: .zero, translation: nil, state: .began) 147 | panRecognizer.performTouch(location: location, translation: nil, state: .changed) 148 | 149 | let expectedHue = x / (colorSliderView.bounds.width - 2 * colorSliderView.borderWidth) 150 | 151 | expect(colorPickerVC.currentColor.h).to(equal(expectedHue)) 152 | expect(colorSliderView.sliderX.constant).to(equal(x)) 153 | } 154 | } 155 | 156 | context("when the view is tapped") { 157 | it("changes the hue value") { 158 | // tap at 1/4 of the view width to the right 159 | let x = colorSliderView.bounds.width / 4 160 | let location = CGPoint(x: x, y: 0) 161 | 162 | tapRecognizer.performTouch(location: .zero, state: .began) 163 | tapRecognizer.performTouch(location: location, state: .changed) 164 | 165 | let expectedHue = x / (colorSliderView.bounds.width - 2 * colorSliderView.borderWidth) 166 | 167 | expect(colorPickerVC.currentColor.h).to(equal(expectedHue)) 168 | expect(colorSliderView.sliderX.constant).to(equal(x)) 169 | } 170 | } 171 | } 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /Examples/Tests/PDColorPickerViewControllerSpec.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorPickerViewControllerSpec.swift 3 | // PDColorPicker_Example 4 | // 5 | // Created by Paolo Di Lorenzo on 8/13/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import Quick 10 | import Nimble 11 | @testable import PDColorPicker 12 | 13 | class DimmableViewController: UIViewController, Dimmable { 14 | 15 | } 16 | 17 | class PDColorPickerViewControllerSpec: QuickSpec { 18 | 19 | override func spec() { 20 | var vc: DimmableViewController! 21 | var window: UIWindow! 22 | 23 | beforeEach { 24 | window = UIWindow(frame: UIScreen.main.bounds) 25 | vc = DimmableViewController() 26 | 27 | window.rootViewController = vc 28 | window.makeKeyAndVisible() 29 | 30 | vc.dim() 31 | } 32 | 33 | describe("a PDColorPickerViewController") { 34 | context("when cancel is tapped") { 35 | it("returns a nil color") { 36 | // set to non-nil value to ensure it is set to nil 37 | var selectedColor: PDColor? = .red 38 | 39 | let colorPickerVC = PDColorPickerViewController { 40 | vc.undim(speed: 0) 41 | selectedColor = $0 42 | } 43 | 44 | vc.present(colorPickerVC, animated: true) 45 | colorPickerVC.cancelButton.sendActions(for: .touchUpInside) 46 | 47 | expect(selectedColor).toEventually(beNil()) 48 | } 49 | } 50 | 51 | context("when save is tapped") { 52 | it("returns the correct color") { 53 | var selectedColor: PDColor? 54 | 55 | let startColor = UIColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1) 56 | let colorPickerVC = PDColorPickerViewController(initialColor: startColor) { 57 | vc.undim(speed: 0) 58 | selectedColor = $0 59 | } 60 | 61 | vc.present(colorPickerVC, animated: true) 62 | colorPickerVC.saveButton.sendActions(for: .touchUpInside) 63 | 64 | expect(selectedColor).toNotEventually(beNil()) 65 | expect(selectedColor?.uiColor).toEventually(equal(startColor)) 66 | } 67 | } 68 | 69 | context("when font is set") { 70 | it("appears on views correctly") { 71 | let font = UIFont.systemFont(ofSize: 5) 72 | let boldFont = UIFont.boldSystemFont(ofSize: 5) 73 | 74 | let colorPickerVC = PDColorPickerViewController() 75 | colorPickerVC.font = font 76 | colorPickerVC.boldFont = boldFont 77 | 78 | expect(colorPickerVC.cancelButton.titleLabel?.font).to(equal(font)) 79 | expect(colorPickerVC.selectedColorLabel.font).to(equal(font)) 80 | expect(colorPickerVC.saveButton.titleLabel?.font).to(equal(boldFont)) 81 | } 82 | } 83 | 84 | context("when tintColor is set") { 85 | it("appears on views correctly") { 86 | let tintColor = UIColor.yellow 87 | 88 | let colorPickerVC = PDColorPickerViewController() 89 | colorPickerVC.tintColor = tintColor 90 | 91 | expect(colorPickerVC.saveButton.titleLabel?.textColor).to(equal(tintColor)) 92 | } 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Examples/Tests/PDColorSpec.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorSpec.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/11/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import Quick 10 | import Nimble 11 | import PDColorPicker 12 | 13 | class PDColorSpec: QuickSpec { 14 | 15 | override func spec() { 16 | describe("a PDColor") { 17 | let original = UIColor(hue: 0.5, saturation: 0.5, brightness: 0.5, alpha: 1) 18 | let color = PDColor(color: original) 19 | 20 | context("when initialized with UIColor") { 21 | it("correctly assigns values") { 22 | expect(color.uiColor).to(equal(original)) 23 | } 24 | } 25 | 26 | context("when initialized with a 3 component string") { 27 | it("correctly assigns values") { 28 | let stringColor3 = PDColor(string: "0.5,0.5,0.5") // default alpha = 1.0 29 | 30 | expect(stringColor3).toNot(beNil()) 31 | expect(stringColor3!.uiColor).to(equal(original)) 32 | } 33 | 34 | it("fails for invalid values") { 35 | let invalidStringColor3 = PDColor(string: "car,0.5,0.5") 36 | expect(invalidStringColor3).to(beNil()) 37 | } 38 | } 39 | 40 | context("when initialized with a 4 component string") { 41 | it("correctly assigns values") { 42 | let stringColor4 = PDColor(string: "0.5,0.5,0.5,1.0") 43 | 44 | expect(stringColor4).toNot(beNil()) 45 | expect(stringColor4!.uiColor).to(equal(original)) 46 | } 47 | 48 | it("fails for invalid values") { 49 | let invalidStringColor4 = PDColor(string: "car,0.5,0.5,1.0") 50 | expect(invalidStringColor4).to(beNil()) 51 | } 52 | } 53 | 54 | context("when initialized with an invalid string") { 55 | let invalidColor = PDColor(string: "99999/*60") 56 | 57 | it("fails") { 58 | expect(invalidColor).to(beNil()) 59 | } 60 | } 61 | 62 | context("when initialized with HSB") { 63 | let hsbColor = PDColor(h: 0.5, s: 0.5, b: 0.5, a: 1) 64 | 65 | it("correctly assigns values") { 66 | expect(hsbColor.uiColor).to(equal(original)) 67 | } 68 | } 69 | 70 | it("produces correct description string") { 71 | expect(color.description).to(equal("0.5,0.5,0.5,1.0")) 72 | } 73 | 74 | it("produces correct hexadecimal string") { 75 | expect(color.hex).to(equal("#3f7f7f")) 76 | } 77 | 78 | it("produces correct RGBA values") { 79 | let rgba = color.rgba 80 | 81 | expect(rgba.r).to(equal(CGFloat(0.25))) 82 | expect(rgba.g).to(equal(CGFloat(0.50))) 83 | expect(rgba.b).to(equal(CGFloat(0.50))) 84 | expect(rgba.a).to(equal(CGFloat(1.00))) 85 | } 86 | 87 | describe("the foreground color") { 88 | context("when PDColor is dark") { 89 | let dark = UIColor(hue: 1, saturation: 1, brightness: 0.25, alpha: 1) 90 | let darkColor = PDColor(color: dark) 91 | 92 | it("is white") { 93 | expect(darkColor.appropriateForegroundColor).to(equal(UIColor.white)) 94 | } 95 | } 96 | 97 | context("when PDColor is light") { 98 | let light = UIColor(hue: 1, saturation: 0.25, brightness: 0.75, alpha: 1) 99 | let lightColor = PDColor(color: light) 100 | 101 | it("is black") { 102 | expect(lightColor.appropriateForegroundColor).to(equal(UIColor.black)) 103 | } 104 | } 105 | } 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Paolo Di Lorenzo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PDColorPicker.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint PDColorPicker.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'PDColorPicker' 11 | s.version = '0.8.5' 12 | s.summary = 'A simple, fast color picker for iOS apps.' 13 | 14 | s.description = <<-DESC 15 | PDColorPicker provides the ability to easily add a color selection interface to an iOS app. 16 | The provided view allows the user to select any 16-bit color by sliding across the different hue, 17 | saturation, and brightness values. The user interface\'s colors and fonts are easily customized 18 | to suit the appearance of any app in which PDColorPicker is used.' 19 | DESC 20 | 21 | s.screenshots = 'https://raw.githubusercontent.com/pdil/PDColorPicker/master/Resources/demo.gif', 'https://raw.githubusercontent.com/pdil/PDColorPicker/master/Resources/drag-drop-demo.gif' 22 | 23 | s.homepage = 'https://github.com/pdil/PDColorPicker' 24 | s.license = { :type => 'MIT', :file => 'LICENSE.md' } 25 | s.author = { 'Paolo Di Lorenzo' => 'dilorenzo@hey.com' } 26 | s.source = { :git => 'https://github.com/pdil/PDColorPicker.git', :tag => s.version.to_s } 27 | s.social_media_url = 'https://twitter.com/dilorenzopl' 28 | 29 | s.ios.deployment_target = '11.0' 30 | s.swift_version = '5.0' 31 | 32 | s.source_files = 'Source/**/*' 33 | 34 | s.frameworks = 'UIKit' 35 | end 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](https://raw.githubusercontent.com/pdil/PDColorPicker/master/Design/Logo.png) 2 | 3 | ---- 4 | 5 | [![Version](https://img.shields.io/github/release/pdil/PDColorPicker/all.svg)](https://github.com/pdil/PDColorPicker/releases) 6 | [![Platform](https://img.shields.io/cocoapods/p/PDColorPicker.svg)](http://cocoapods.org/pods/PDColorPicker) 7 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg)](https://github.com/Carthage/Carthage) 8 | [![CocoaPods compatible](https://img.shields.io/badge/CocoaPods-compatible-4BC51D.svg)](https://cocoapods.org/pods/PDColorPicker) 9 | [![Downloads](https://img.shields.io/cocoapods/dt/PDColorPicker.svg)](http://cocoapods.org/pods/PDColorPicker) 10 | 11 | 12 | | Branch | Status | Coverage | 13 | | ------ | ------ | -------- | 14 | | `master` (v0.8.5) | [![CI Status](http://img.shields.io/travis/pdil/PDColorPicker/master.svg?style=flat)](https://travis-ci.org/pdil/PDColorPicker) | [![codecov](https://codecov.io/gh/pdil/PDColorPicker/branch/master/graph/badge.svg)](https://codecov.io/gh/pdil/PDColorPicker/branch/master) | 15 | | `develop` | [![CI Status](http://img.shields.io/travis/pdil/PDColorPicker/develop.svg?style=flat)](https://travis-ci.org/pdil/PDColorPicker/branches) | [![codecov](https://codecov.io/gh/pdil/PDColorPicker/branch/develop/graph/badge.svg)](https://codecov.io/gh/pdil/PDColorPicker/branch/develop) | 16 | 17 | 18 | 🎨 **PDColorPicker** is an open source iOS library that lets developers include a color picker in their apps, allowing users to easily select colors in a variety of formats. This library is open for collaboration with the community so anyone is invited to submit issues or pull requests. 19 | 20 | | Demo | Table of Contents | 21 | | ----------------- | ----------------- | 22 | | [](https://giphy.com/gifs/10ofmG3LCZMImI/fullscreen) | [📄 Requirements](README.md#-requirements)

[💻 Installation](README.md#-installation)
  • [CocoaPods](README.md#cocoapods)
  • [Carthage](README.md#carthage)
  • [Manual](README.md#manual-not-recommended)
[📝 Usage](README.md#-usage)

[📲 Drag and Drop](README.md#-drag-and-drop)

[🎨 **PDColorPicker** in other apps](README.md#-pdcolorpicker-in-other-apps)

[🙋‍♂️ Author](README.md#%EF%B8%8F-author)

[⚖️ License](README.md#%EF%B8%8F-license) | 23 | 24 | ---- 25 | 26 | ## 📄 Requirements 27 | 28 | * iOS 9.0 or later (iOS 11.0+ for drag and drop) 29 | * Xcode 10.2 or later 30 | * Swift 5 or later 31 | 32 | ## 💻 Installation 33 | 34 | ### Cocoapods 35 | 36 | `PDColorPicker` is available through [CocoaPods](http://cocoapods.org). 37 | 38 | If you have not done so already, run `pod setup` from the root directory of your application. 39 | 40 | To install `PDColorPicker`, simply add the following line to the Podfile: 41 | 42 | ```ruby 43 | pod 'PDColorPicker' 44 | ``` 45 | 46 | This line should be added to the app's target so that it looks something like this: 47 | 48 | ```ruby 49 | use_frameworks! 50 | 51 | target 'TARGET_NAME' do 52 | pod 'PDColorPicker' 53 | 54 | # other pods... 55 | end 56 | ``` 57 | 58 | > **Older Swift Versions** 59 | > 60 | > If the project is not built for Swift 4.2, install from the `swift-3.2`, `swift-4.1` or the `swift-4.2` branches: 61 | > ```ruby 62 | > pod 'PDColorPicker', :git => 'https://github.com/pdil/PDColorPicker.git', :branch => 'swift-4.2' 63 | > ``` 64 | > Note that this build may not include all of the latest features of `PDColorPicker`. 65 | 66 | Build the CocoaPods frameworks by running the following command in the Terminal from the root project directory: 67 | 68 | ``` 69 | $ pod install 70 | ``` 71 | 72 | Open the newly created `.xcworkspace` file and build the project to make `PDColorPicker` available. 73 | 74 | **Note**: Be sure to always work inside the `.xcworkspace` file and **not** the `.xcodeproj` file, otherwise Xcode will not be able to locate the dependencies and `PDColorPicker` will not be accessible. 75 | 76 | ### Carthage 77 | 78 | `PDColorPicker` is available through [Carthage](https://github.com/carthage/carthage). 79 | 80 | If you haven't installed Carthage yet, use Homebrew to install it: 81 | 82 | ``` 83 | $ brew update 84 | $ brew install carthage 85 | ``` 86 | 87 | Create a Cartfile inside the root project directory with the following line (or add this line if you already have a Cartfile): 88 | 89 | ``` 90 | github "pdil/PDColorPicker" 91 | ``` 92 | 93 | > **Older Swift Versions** 94 | > 95 | > If the project is not built for Swift 4.2, install from the `swift-3.2`, `swift-4.1` or the `swift-4.2` branches: 96 | > ``` 97 | > github "pdil/PDColorPicker" "swift-4.2" 98 | > ``` 99 | > Note that this build may not include the latest features of `PDColorPicker`. 100 | 101 | Build the Carthage frameworks by running the following command in the Terminal from the root project directory: 102 | 103 | ``` 104 | $ carthage update 105 | ``` 106 | 107 | This will build the framework inside the `Carthage/build` folder. 108 | 109 | Lastly, add the framework to your project: 110 | 111 | * In Xcode, select the project in the Project Navigator in Xcode (blue icon). 112 | * Open the "General" tab on the top bar. 113 | * Drag `PDColorPicker.framework` from the `Carthage/build` folder into the "Embedded Binaries" section. 114 | 115 | ### Manual (not recommended) 116 | 117 | * Download the `.swift` files inside [PDColorPicker/Classes](https://github.com/pdil/PDColorPicker/tree/master/PDColorPicker/Classes) and add them to your project. 118 | * Add the files to the appropriate target(s) within the project. 119 | * Import `PDColorPicker` as you normally would. 120 | 121 | ## 📝 Usage 122 | 123 | ```swift 124 | import UIKit 125 | import PDColorPicker // 1. 126 | 127 | class MyViewController: UIViewController, Dimmable { 128 | // ... 129 | 130 | func presentColorPicker() { 131 | // 2. 132 | let colorPickerVC = PDColorPickerViewController(initialColor: .blue, tintColor: .black) 133 | 134 | // 3. 135 | colorPickerVC.completion = { 136 | [weak self] newColor in 137 | 138 | self?.undim() // 7. 139 | 140 | guard let color = newColor else { 141 | print("The user tapped cancel, no color was selected.") 142 | return 143 | } 144 | 145 | print("A new color was selected! HSBA: \(String(describing: color))") 146 | } 147 | 148 | // 4. 149 | dim() // see Dimmable documentation for extra options 150 | 151 | // 5. 152 | present(colorPickerVC, animated: true) 153 | } 154 | 155 | // ... 156 | } 157 | ``` 158 | 159 | 1. Import the `PDColorPicker` framework. 160 | 2. Instantiate a new `PDColorPickerViewController`. 161 | 3. Set the completion handler of the color picker, indicating what the presenting view controller should do with the color result. **Note**: this can also be set in the `PDColorPickerViewController` initializer. 162 | 4. Implement the `Dimmable` protocol and dim the presenting view controller (optional but highly recommended). 163 | 5. Present the color picker as a modal view controller. 164 | 6. Use the color picker to select a color. When **Save** or **Cancel** is tapped, the completion handler specified in the initializer will automatically provide the new color. If the user taps cancel, `nil` is returned. 165 | 7. Be sure to undim the view once the completion handler is called. 166 | 167 | ### Bonus 168 | 169 | To achieve the white status bar while the presenting view controller is dimmed, set `UIViewControllerBasedStatusBarAppearance` to `YES` in your `Info.plist`. 170 | 171 | You can also copy the code here into the plist file: 172 | ``` 173 | UIViewControllerBasedStatusBarAppearance 174 | 175 | ``` 176 | 177 | ## 📲 Drag and Drop 178 | 179 | Drag and drop is also supported in projects that target iOS 11.0 or later. 180 | 181 | [](https://giphy.com/gifs/6TNPgdZ3W4qMo/fullscreen) 182 | 183 | See `PDColorReceiverExample` for an example on how to consume a color that is dragged into your app. The drag and drop implementation of `PDColorPicker` exposes a basic `UIColor` so that it can be read by apps that don't necessarily import `PDColorPicker`. 184 | 185 | Of course, if the destination app imports `PDColorPicker`, it will have access to the convenient `PDColor` class which it could instantiate with the received `UIColor`: 186 | 187 | ```swift 188 | func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { 189 | session.loadObjects(ofClass: UIColor.self) { 190 | guard let color = $0.first as? UIColor else { return } 191 | 192 | let pdColor = PDColor(color: color) 193 | print(pdColor.hex) 194 | } 195 | } 196 | ``` 197 | 198 | ## 🎨 `PDColorPicker` in other apps 199 | Here is a list of apps that use **PDColorPicker** to let their users select colors: 200 | 201 | * 🌮 [FoodEase](https://foodease.xyz) 202 | * 🎨 [Paint Shapes](https://itunes.apple.com/us/app/paint-shapes/id1366164052) 203 | 204 | If your app is using **PDColorPicker**, [let me know](mailto:dilorenzo@hey.com?subject=PDColorPicker) and I'll add it to this list (include an emoji to represent your app in the list, the app name, and a web or download URL)! 205 | 206 | ## 🙋‍♂️ Author 207 | 208 | Paolo Di Lorenzo 209 | 210 | [![Email](https://img.shields.io/badge/email-dilorenzo@hey.com-red.svg)](mailto:dilorenzo@hey.com?subject=PDColorPicker) 211 | [![Website](https://img.shields.io/badge/web-dilorenzo.pl-red.svg)](https://dilorenzo.pl) 212 | [![Twitter](https://img.shields.io/badge/twitter-%40dilorenzopl-4099FF.svg)](https://twitter.com/dilorenzopl) 213 | [![Stackoverflow](https://img.shields.io/badge/stackoverflow-%40Paolo-FF9900.svg)](https://stackoverflow.com/users/7264964/paolo) 214 | 215 | ## ⚖️ License 216 | [![License](https://img.shields.io/cocoapods/l/PDColorPicker.svg?style=flat)](https://github.com/pdil/PDColorPicker/blob/master/LICENSE.md) 217 | 218 | PDColorPicker is available under the MIT license. See the [LICENSE](https://github.com/pdil/PDColorPicker/blob/master/LICENSE.md) file for more info. 219 | -------------------------------------------------------------------------------- /Resources/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Resources/demo.gif -------------------------------------------------------------------------------- /Resources/drag-drop-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdil/PDColorPicker/30d415ac59cfc2472b3ff18d0084ef54b0599cef/Resources/drag-drop-demo.gif -------------------------------------------------------------------------------- /Source/Dimmable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dimmable.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Provides a simple mechanism for dimming a view controller. 12 | /// 13 | /// The intended usage of this protocol is to allow dimming of a view controller 14 | /// so that another view controller (e.g. an alert) may be presented on top of it. 15 | /// 16 | /// - note: 17 | /// Be sure to carefully read the documentation for proper use of the `dim()` and 18 | /// `undim()` methods that are implemented by this protocol. Misuse may cause issues 19 | /// with the view hierarchy of the view controller. 20 | public protocol Dimmable { } 21 | 22 | public extension Dimmable where Self: UIViewController { 23 | 24 | /// Convenience method that creates a view in frame `rect`, 25 | /// with color `color` and transparency `alpha`. 26 | private func createDimView(in superview: UIView, color: UIColor, alpha: CGFloat) -> UIView? { 27 | let dimView = UIView() 28 | 29 | superview.addSubview(dimView) 30 | dimView.anchorFill(view: superview) 31 | 32 | dimView.backgroundColor = color 33 | dimView.alpha = 0 34 | 35 | if #available(iOS 11.0, *) { 36 | dimView.accessibilityIgnoresInvertColors = true 37 | } 38 | 39 | return dimView 40 | } 41 | 42 | /** 43 | Dims the view controller that it is called on. If the view controller is inside a `UINavigationController`, 44 | `UITabBarController`, or both, the entire view will be dimmed including the navigation bar and tab bar. 45 | 46 | - warning: 47 | Do not add any subviews to the view controller while it is dimmed. Instead, call `undim()` on the 48 | view controller before adding any subviews. 49 | 50 | - parameters: 51 | - color: The tint color to be used in dimming. The default is `UIColor.black`. 52 | - alpha: The transparency level of the dim. A value of 0.0 means a completely transparent dim (no effect) 53 | whereas 1.0 is a completely opaque dim. The default value is 0.5. 54 | - speed: The animation speed of the dimming (in seconds). The default value is 0.5. 55 | */ 56 | func dim(_ color: UIColor = .black, alpha: CGFloat = 0.5, speed: TimeInterval = 0.5) { 57 | let viewToDim: UIView 58 | 59 | if let navigationController = navigationController { 60 | viewToDim = navigationController.view 61 | } else { 62 | viewToDim = self.view 63 | } 64 | 65 | if let dimmingView = createDimView(in: viewToDim, color: color, alpha: alpha) { 66 | UIView.animate(withDuration: 0.25) { dimmingView.alpha = alpha } 67 | } 68 | 69 | if let tabBar = tabBarController?.tabBar { 70 | if let tabBarDimView = createDimView(in: tabBar, color: color, alpha: alpha) { 71 | UIView.animate(withDuration: 0.25) { tabBarDimView.alpha = alpha } 72 | } 73 | } 74 | } 75 | 76 | /** 77 | Undims the view controller that it is called on. This method has no effect if the view controller 78 | has not been dimmed with `dim()` yet. 79 | 80 | - warning: 81 | Do not call this method unless `dim()` has been called first and the view controller has not 82 | been undimmed already. Calling this method when the view controller is not dimmed may cause 83 | issues with the view hierarchy. 84 | 85 | - parameters: 86 | - speed: The animation speed of the undimming (in seconds). The default value is 0.5. 87 | - completion: The completion handler that is called after the undimming is complete. Use this 88 | parameter to execute any cleanup or setup code that should be executed immediately after the 89 | view controller becomes visible again. 90 | */ 91 | func undim(speed: TimeInterval = 0.5, completion: @escaping () -> () = {}) { 92 | UIView.animate(withDuration: speed, animations: { 93 | self.tabBarController?.tabBar.subviews.last?.alpha = 0 94 | 95 | if let navigationController = self.navigationController { 96 | navigationController.view.subviews.last?.alpha = 0 97 | } else { 98 | self.view.subviews.last?.alpha = 0 99 | } 100 | 101 | self.view.subviews.last?.alpha = 0 102 | 103 | }, completion: { _ in 104 | self.tabBarController?.tabBar.subviews.last?.removeFromSuperview() 105 | 106 | if let navigationController = self.navigationController { 107 | navigationController.view.subviews.last?.removeFromSuperview() 108 | } else { 109 | self.view.subviews.last?.removeFromSuperview() 110 | } 111 | 112 | completion() 113 | }) 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /Source/PDBouncyButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDBouncyButton.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PDBouncyButton: UIButton, Bounceable { 12 | 13 | let bounceScale: CGFloat = 0.9 14 | let bounceDuration: TimeInterval = 0.15 15 | 16 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 17 | super.touchesBegan(touches, with: event) 18 | bounceIn(at: bounceScale, with: bounceDuration) 19 | } 20 | 21 | override func touchesEnded(_ touches: Set, with event: UIEvent?) { 22 | super.touchesEnded(touches, with: event) 23 | bounceOut(with: bounceDuration) 24 | } 25 | 26 | override func touchesCancelled(_ touches: Set, with event: UIEvent?) { 27 | super.touchesCancelled(touches, with: event) 28 | bounceOut(with: bounceDuration) 29 | } 30 | 31 | } 32 | 33 | 34 | protocol Bounceable {} 35 | 36 | extension Bounceable where Self: UIView { 37 | func bounceIn(at scale: CGFloat, with duration: TimeInterval) { 38 | UIView.animate(withDuration: duration) { 39 | self.transform = CGAffineTransform(scaleX: scale, y: scale) 40 | } 41 | } 42 | 43 | func bounceOut(with duration: TimeInterval) { 44 | UIView.animate(withDuration: duration) { 45 | self.transform = .identity 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /Source/PDColor+NamedColors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColor+NamedColors.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/28/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | public extension PDColor { 10 | /// Convenient representation of the red `PDColor`. 11 | /// 12 | /// Its values are `(1.0, 1.0, 1.0, 1.0)` in the HSBA representation. 13 | static var red: PDColor { 14 | return PDColor(h: 1, s: 1, b: 1, a: 1) 15 | } 16 | 17 | /// Convenient representation of the orange `PDColor`. 18 | /// 19 | /// Its values are `(30/360, 1.0, 1.0, 1.0)` in the HSBA representation. 20 | static var orange: PDColor { 21 | return PDColor(h: 30/360, s: 1, b: 1, a: 1) 22 | } 23 | 24 | /// Convenient representation of the yellow `PDColor`. 25 | /// 26 | /// Its values are `(60/360, 1.0, 1.0, 1.0)` in the HSBA representation. 27 | static var yellow: PDColor { 28 | return PDColor(h: 60/360, s: 1, b: 1, a: 1) 29 | } 30 | 31 | /// Convenient representation of the yellow-green `PDColor`. 32 | /// 33 | /// Its values are `(90/360, 1.0, 1.0, 1.0)` in the HSBA representation. 34 | static var yellowGreen: PDColor { 35 | return PDColor(h: 90/360, s: 1, b: 1, a: 1) 36 | } 37 | 38 | /// Convenient representation of the green `PDColor`. 39 | /// 40 | /// Its values are `(120/360, 1.0, 1.0, 1.0)` in the HSBA representation. 41 | static var green: PDColor { 42 | return PDColor(h: 120/360, s: 1, b: 1, a: 1) 43 | } 44 | 45 | /// Convenient representation of the cyan `PDColor`. 46 | /// 47 | /// Its values are `(180/360, 1.0, 1.0, 1.0)` in the HSBA representation. 48 | static var cyan: PDColor { 49 | return PDColor(h: 180/360, s: 1, b: 1, a: 1) 50 | } 51 | 52 | /// Convenient representation of the azure `PDColor`. 53 | /// 54 | /// Its values are `(210/360, 1.0, 1.0, 1.0)` in the HSBA representation. 55 | static var azure: PDColor { 56 | return PDColor(h: 210/360, s: 1, b: 1, a: 1) 57 | } 58 | 59 | /// Convenient representation of the blue `PDColor`. 60 | /// 61 | /// Its values are `(240/360, 1.0, 1.0, 1.0)` in the HSBA representation. 62 | static var blue: PDColor { 63 | return PDColor(h: 240/360, s: 1, b: 1, a: 1) 64 | } 65 | 66 | /// Convenient representation of the purple `PDColor`. 67 | /// 68 | /// Its values are `(270/360, 1.0, 1.0, 1.0)` in the HSBA representation. 69 | static var purple: PDColor { 70 | return PDColor(h: 270/360, s: 1, b: 1, a: 1) 71 | } 72 | 73 | /// Convenient representation of the magenta `PDColor`. 74 | /// 75 | /// Its values are `(300/360, 1.0, 1.0, 1.0)` in the HSBA representation. 76 | static var magenta: PDColor { 77 | return PDColor(h: 300/360, s: 1, b: 1, a: 1) 78 | } 79 | 80 | /// Convenient representation of the pink `PDColor`. 81 | /// 82 | /// Its values are `(330/360, 1.0, 1.0, 1.0)` in the HSBA representation. 83 | static var pink: PDColor { 84 | return PDColor(h: 330/360, s: 1, b: 1, a: 1) 85 | } 86 | 87 | /// Convenient representation of the white `PDColor`. 88 | /// 89 | /// Its values are `(0.0, 0.0, 1.0, 1.0)` in the HSBA representation. 90 | static var white: PDColor { 91 | return PDColor(h: 0, s: 0, b: 1, a: 1) 92 | } 93 | 94 | /// Convenient representation of the black `PDColor`. 95 | /// 96 | /// Its values are `(0.0, 1.0, 1.0, 1.0)` in the HSBA representation. 97 | static var black: PDColor { 98 | return PDColor(h: 0, s: 0, b: 0, a: 1) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Source/PDColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColor.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Provides a convenient wrapper for colors to be represented as 12 | /// a set of hue, saturation, brightness, and alpha values. 13 | /// 14 | /// Convenience methods for accessing the `UIColor`, RGB, and hexadecimal 15 | /// representations are also provided. 16 | public struct PDColor { 17 | 18 | /// Hue -- values are constrained to be between 0.0 and 1.0. 19 | public var h: CGFloat 20 | /// Saturation -- values are constrained to be between 0.0 and 1.0. 21 | public var s: CGFloat 22 | /// Brightness -- values are constrained to be between 0.0 and 1.0. 23 | public var b: CGFloat 24 | /// Alpha -- values are constrained to be between 0.0 and 1.0. 25 | public var a: CGFloat 26 | 27 | /// The `UIColor` representation of the `PDColor`. 28 | public var uiColor: UIColor { 29 | return UIColor(hue: h, saturation: s, brightness: b, alpha: a) 30 | } 31 | 32 | /// The RGB representation of the `PDColor`. 33 | public var rgba: (r: CGFloat, b: CGFloat, g: CGFloat, a: CGFloat) { 34 | var r: CGFloat = 0.0 35 | var g: CGFloat = 0.0 36 | var b: CGFloat = 0.0 37 | var a: CGFloat = 0.0 38 | 39 | uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) 40 | 41 | return (r: r, b: b, g: g, a: a) 42 | } 43 | 44 | /** 45 | Initializes a `PDColor` from a `UIColor`. 46 | 47 | - parameter color: The `UIColor` to be used to initialize the `PDColor`. 48 | */ 49 | public init(color: UIColor) { 50 | var h: CGFloat = 0 51 | var s: CGFloat = 0 52 | var b: CGFloat = 0 53 | var a: CGFloat = 0 54 | 55 | color.getHue(&h, saturation: &s, brightness: &b, alpha: &a) 56 | 57 | self.h = h 58 | self.s = s 59 | self.b = b 60 | self.a = a 61 | } 62 | 63 | /** 64 | Initializes a `PDColor` from a `String`. 65 | 66 | - parameter string: The `String` to be used to initialize the `PDColor`. 67 | The string should be of the form `",,,"`, 68 | where the values are between 0.0 and 1.0 (and the `< >` are omitted). 69 | The `` value is optional and defaults to 1.0. 70 | 71 | Example: 72 | 73 | ``` 74 | let color = PDColor(string: "0.5,0.75,0.33,1.0") 75 | 76 | // alpha defaults to 1.0 77 | let color = PDColor(string: "0.5,0.75,0.33") 78 | ``` 79 | */ 80 | public init?(string: String) { 81 | let components = string.components(separatedBy: ",") 82 | 83 | if components.count >= 3 { 84 | if let h = Double(components[0]), let s = Double(components[1]), let b = Double(components[2]) { 85 | self.h = CGFloat(h) 86 | self.s = CGFloat(s) 87 | self.b = CGFloat(b) 88 | } else { 89 | return nil 90 | } 91 | 92 | if components.count == 4, let a = Double(components[3]) { 93 | self.a = CGFloat(a) 94 | } else { 95 | a = 1 96 | } 97 | } else { 98 | return nil 99 | } 100 | } 101 | 102 | /** 103 | Initializes a `PDColor` from hue, saturation, brightness, and alpha values directly. 104 | All four values are constrained to be between 0.0 and 1.0. 105 | 106 | - parameters: 107 | - h: Hue 108 | - s: Saturation 109 | - b: Brightness 110 | - a: Alpha -- the default value is 1.0 111 | */ 112 | public init(h: CGFloat, s: CGFloat, b: CGFloat, a: CGFloat = 1) { 113 | self.h = h 114 | self.s = s 115 | self.b = b 116 | self.a = a 117 | } 118 | 119 | // MARK: - Utilities 120 | 121 | /// The hexadecimal representation of the `PDColor`. 122 | /// 123 | /// Examples: 124 | /// - `#000000` : black 125 | /// - `#ff0000` : red 126 | /// - `#00ff00` : green 127 | /// - `#0000ff` : blue 128 | /// - `#ffffff` : white 129 | public var hex: String { 130 | let rgba = self.rgba 131 | 132 | let rr = (Int)(rgba.r * 255) << 16 133 | let gg = (Int)(rgba.g * 255) << 8 134 | let bb = (Int)(rgba.b * 255) << 0 135 | 136 | let rgb = rr | gg | bb 137 | 138 | return String(format: "#%06x", rgb) 139 | } 140 | 141 | /** 142 | A color that is appropriate to display as the foreground 143 | assuming that the `PDColor` is the background color. This convenience property 144 | returns a color that is visible when superimposed on the current value of the 145 | `PDColor`. 146 | 147 | The returned value is white if `PDColor` is dark, and black if `PDColor` is light. 148 | This property is computed based on the "luma" of the associated red, green, and blue values. 149 | 150 | See [https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness](https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness) 151 | for more information. 152 | */ 153 | public var appropriateForegroundColor: UIColor { 154 | let rgba = self.rgba 155 | let level = 1 - (0.299 * rgba.r + 0.587 * rgba.g + 0.114 * rgba.b) 156 | 157 | return (level < 0.5) ? .black : .white 158 | } 159 | 160 | } 161 | 162 | // MARK: - CustomStringConveritble 163 | extension PDColor: CustomStringConvertible { 164 | public var description: String { 165 | return "\(h),\(s),\(b),\(a)" 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Source/PDColorPickerAlphaSliderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorPickerAlphaSliderView.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 11/24/17. 6 | // 7 | 8 | import UIKit 9 | 10 | class PDColorPickerAlphaSliderView: UIView { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Source/PDColorPickerGridView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorPickerGridView.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol PDColorPickerGridDelegate: AnyObject { 12 | func colorChanged(to newColor: PDColor) 13 | } 14 | 15 | protocol PDColorPickerGridDataSource: AnyObject { 16 | func selectedHueForColorPicker() -> CGFloat? 17 | } 18 | 19 | class PDColorPickerGridView: UIView { 20 | 21 | // MARK: - Gesture Recognizer 22 | 23 | lazy var panRecognizer: PDPanGestureRecognizer = { 24 | return PDPanGestureRecognizer(target: self, action: #selector(colorDragged(_:))) 25 | }() 26 | 27 | lazy var tapRecognizer: PDTapGestureRecognizer = { 28 | return PDTapGestureRecognizer(target: self, action: #selector(colorTapped(_:))) 29 | }() 30 | 31 | // MARK: - Properties 32 | 33 | weak var delegate: PDColorPickerGridDelegate? 34 | weak var dataSource: PDColorPickerGridDataSource? 35 | 36 | var currentColor: PDColor? { 37 | didSet { setSliderCircle() } 38 | } 39 | 40 | var selectedHue: CGFloat? { 41 | didSet { 42 | guard let selectedHue = selectedHue else { return } 43 | backgroundColor = UIColor(hue: selectedHue, saturation: 1, brightness: 1, alpha: 1) 44 | } 45 | } 46 | 47 | // MARK: - Slider Properties 48 | 49 | lazy var sliderCircle: UIView = { 50 | let circle = UIView() 51 | circle.layer.borderColor = UIColor.black.cgColor 52 | circle.layer.borderWidth = 2.0 53 | circle.backgroundColor = UIColor.white.withAlphaComponent(0.6) 54 | circle.alpha = 0 55 | return circle 56 | }() 57 | 58 | lazy var sliderCircleX: NSLayoutConstraint = { 59 | let constraint = NSLayoutConstraint(item: self.sliderCircle, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 100) 60 | return constraint 61 | }() 62 | 63 | lazy var sliderCircleY: NSLayoutConstraint = { 64 | let constraint = NSLayoutConstraint(item: self.sliderCircle, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 100) 65 | return constraint 66 | }() 67 | 68 | let sliderSize: CGFloat = 25 69 | let visibilityOffset: CGFloat = 60 70 | let circleGrowthScale: CGFloat = 3 71 | 72 | // MARK: - Initializer 73 | 74 | init() { 75 | super.init(frame: .zero) 76 | 77 | if #available(iOS 11.0, *) { 78 | accessibilityIgnoresInvertColors = true 79 | } 80 | 81 | addGestureRecognizer(panRecognizer) 82 | addGestureRecognizer(tapRecognizer) 83 | } 84 | 85 | required init?(coder aDecoder: NSCoder) { 86 | fatalError("init(coder:) has not been implemented") 87 | } 88 | 89 | // MARK: - Life Cycle 90 | 91 | var initialViewLoad = true 92 | override func layoutSubviews() { 93 | super.layoutSubviews() 94 | 95 | setupGradient() 96 | 97 | if initialViewLoad { 98 | addSubview(sliderCircle) 99 | sliderCircle.anchor(height: sliderSize, width: sliderSize) 100 | addConstraints([sliderCircleX, sliderCircleY]) 101 | 102 | layoutIfNeeded() 103 | sliderCircle.layer.cornerRadius = sliderCircle.frame.width / 2 104 | setSliderCircle() 105 | 106 | initialViewLoad = false 107 | } 108 | } 109 | 110 | // MARK: - Setup 111 | 112 | var saturationGradient = CAGradientLayer() 113 | var brightnessGradient = CAGradientLayer() 114 | 115 | func setupGradient() { 116 | saturationGradient.removeFromSuperlayer() 117 | brightnessGradient.removeFromSuperlayer() 118 | 119 | saturationGradient = gradientLayerWithEndPoints(CGPoint(x: 0, y: 0.5), CGPoint(x: 1, y: 0.5), endColor: .white) 120 | brightnessGradient = gradientLayerWithEndPoints(CGPoint(x: 0.5, y: 0), CGPoint(x: 0.5, y: 1), endColor: .black) 121 | 122 | layer.addSublayer(saturationGradient) 123 | layer.addSublayer(brightnessGradient) 124 | 125 | bringSubviewToFront(sliderCircle) 126 | } 127 | 128 | private func gradientLayerWithEndPoints(_ start: CGPoint, _ end: CGPoint, endColor: UIColor) -> CAGradientLayer { 129 | let gradientLayer = CAGradientLayer() 130 | 131 | gradientLayer.frame = self.bounds 132 | gradientLayer.colors = [UIColor.clear.cgColor, endColor.cgColor] 133 | 134 | gradientLayer.startPoint = start 135 | gradientLayer.endPoint = end 136 | 137 | return gradientLayer 138 | } 139 | 140 | // MARK: - Gesture 141 | 142 | @objc func colorDragged(_ recognizer: PDPanGestureRecognizer) { 143 | let pos = recognizer.location(in: self) 144 | let comps = colorComponents(at: pos) 145 | let sliderCenter = constrainPosition(pos, toBounds: bounds) 146 | 147 | delegate?.colorChanged(to: comps) 148 | sliderCircle.backgroundColor = comps.uiColor 149 | 150 | switch recognizer.state { 151 | case .began: 152 | animateCircleSlider(.grow) 153 | case .changed: 154 | sliderCircleX.constant = sliderCenter.x 155 | sliderCircleY.constant = sliderCenter.y - visibilityOffset 156 | case .ended: 157 | sliderCircle.backgroundColor = UIColor.white.withAlphaComponent(0.6) 158 | animateCircleSlider(.shrink) 159 | default: 160 | break 161 | } 162 | } 163 | 164 | @objc func colorTapped(_ recognizer: PDTapGestureRecognizer) { 165 | let pos = recognizer.location(in: self) 166 | let comps = colorComponents(at: pos) 167 | let sliderCenter = constrainPosition(pos, toBounds: bounds) 168 | 169 | delegate?.colorChanged(to: comps) 170 | sliderCircle.backgroundColor = comps.uiColor 171 | 172 | animateCircleSlider(.grow) 173 | 174 | sliderCircleX.constant = sliderCenter.x 175 | sliderCircleY.constant = sliderCenter.y - visibilityOffset 176 | 177 | sliderCircle.backgroundColor = UIColor.white.withAlphaComponent(0.6) 178 | animateCircleSlider(.shrink) 179 | } 180 | 181 | // MARK: - Slider Management 182 | 183 | enum FadeMode { case `in`, out } 184 | 185 | func fadeSlider(_ mode: FadeMode) { 186 | UIView.animate(withDuration: 0.25) { 187 | self.sliderCircle.alpha = (mode == .in) ? 1 : 0 188 | } 189 | } 190 | 191 | func setSliderCircle() { 192 | guard let currentColor = currentColor else { return } 193 | 194 | sliderCircleX.constant = (1 - currentColor.s) * bounds.width 195 | sliderCircleY.constant = (1 - currentColor.b) * bounds.height 196 | 197 | sliderCircle.setNeedsLayout() 198 | } 199 | 200 | func constrainPosition(_ pos: CGPoint, toBounds rect: CGRect) -> CGPoint { 201 | let x = min(max(pos.x, 0), rect.width) 202 | let y = min(max(pos.y, 0), rect.height) 203 | 204 | return CGPoint(x: x, y: y) 205 | } 206 | 207 | enum CircleSliderAnimationType: Int { 208 | case grow = -1, shrink = 1 209 | } 210 | 211 | func animateCircleSlider(_ type: CircleSliderAnimationType) { 212 | let sliderOffsetDirection: CGFloat = CGFloat(type.rawValue) 213 | 214 | // if sliderOffsetDirection = 1, scale = circleGrowthScale, otherwise scale = circleGrowthScale ^ -1 215 | let scale = pow(circleGrowthScale, -sliderOffsetDirection) 216 | 217 | let transform = sliderCircle.transform.scaledBy(x: scale, y: scale) 218 | sliderCircleY.constant += visibilityOffset * sliderOffsetDirection 219 | 220 | UIView.animate(withDuration: 0.25, animations: { 221 | self.sliderCircle.transform = transform 222 | self.layoutIfNeeded() 223 | }) 224 | } 225 | 226 | func colorComponents(at point: CGPoint) -> PDColor { 227 | let s = min(max(bounds.width - point.x, 0) / bounds.width, 1) 228 | let b = min(max(bounds.height - point.y, 0) / bounds.height, 1) 229 | 230 | return PDColor(h: dataSource?.selectedHueForColorPicker() ?? 1, s: s, b: b, a: 1) 231 | } 232 | 233 | } 234 | -------------------------------------------------------------------------------- /Source/PDColorPickerSliderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorPickerSliderView.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol PDColorPickerSliderDelegate: AnyObject { 12 | func hueChanged(to newHue: CGFloat) 13 | } 14 | 15 | class PDColorPickerSliderView: UIView { 16 | 17 | // MARK: - Gesture Recognizer 18 | 19 | lazy var panRecognizer: PDPanGestureRecognizer = { 20 | return PDPanGestureRecognizer(target: self, action: #selector(colorDragged(_:))) 21 | }() 22 | 23 | lazy var tapRecognizer: PDTapGestureRecognizer = { 24 | return PDTapGestureRecognizer(target: self, action: #selector(colorTapped(_:))) 25 | }() 26 | 27 | // MARK - Properties 28 | 29 | weak var delegate: PDColorPickerSliderDelegate? 30 | 31 | var currentHue: CGFloat? { 32 | didSet { 33 | if let currentHue = currentHue { delegate?.hueChanged(to: currentHue) } 34 | setHueSlider() 35 | } 36 | } 37 | 38 | var borderWidth: CGFloat = 4 { 39 | didSet { setNeedsDisplay() } 40 | } 41 | 42 | // MARK: - Slider Properties 43 | 44 | var elementSize: CGFloat = 1 { 45 | didSet { setNeedsDisplay() } 46 | } 47 | 48 | let sliderOffset: CGFloat = 3 49 | 50 | lazy var hueSlider: UIView = { 51 | let slider = UIView() 52 | slider.layer.borderColor = UIColor.black.cgColor 53 | slider.layer.borderWidth = 1.0 54 | slider.backgroundColor = UIColor.white.withAlphaComponent(0.75) 55 | return slider 56 | }() 57 | 58 | lazy var sliderX: NSLayoutConstraint = { 59 | let constraint = NSLayoutConstraint(item: self.hueSlider, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 100) 60 | return constraint 61 | }() 62 | 63 | var sliderHalfWidth: CGFloat { 64 | return hueSlider.bounds.width / 2 65 | } 66 | 67 | // MARK: - Initializer 68 | 69 | init() { 70 | super.init(frame: .zero) 71 | backgroundColor = .clear 72 | 73 | if #available(iOS 11.0, *) { 74 | accessibilityIgnoresInvertColors = true 75 | } 76 | 77 | addGestureRecognizer(panRecognizer) 78 | addGestureRecognizer(tapRecognizer) 79 | 80 | layer.shadowColor = UIColor.black.cgColor 81 | layer.shadowOpacity = 0.4 82 | layer.shadowRadius = 10 83 | } 84 | 85 | required init?(coder aDecoder: NSCoder) { 86 | fatalError("init(coder:) has not been implemented") 87 | } 88 | 89 | // MARK: - Life Cycle 90 | 91 | var initialViewLoad = true 92 | override func layoutSubviews() { 93 | super.layoutSubviews() 94 | 95 | if initialViewLoad { 96 | addSubview(hueSlider) 97 | hueSlider.anchor(top: topAnchor, bottom: bottomAnchor, width: 8) 98 | addConstraint(sliderX) 99 | 100 | layoutIfNeeded() 101 | hueSlider.layer.cornerRadius = hueSlider.frame.width / 2 102 | setHueSlider() 103 | 104 | initialViewLoad = false 105 | } 106 | } 107 | 108 | override func draw(_ rect: CGRect) { 109 | let context = UIGraphicsGetCurrentContext() 110 | 111 | for x in stride(from: CGFloat(borderWidth), to: rect.width - borderWidth, by: elementSize) { 112 | let hue = hueAtPosition(x, containingRect: bounds) 113 | let color = UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1) 114 | 115 | context?.setFillColor(color.cgColor) 116 | context?.fill(CGRect(x: x, y: borderWidth, width: elementSize, height: bounds.height - 2 * borderWidth)) 117 | } 118 | } 119 | 120 | // MARK: - Gesture 121 | 122 | @objc func colorDragged(_ sender: UIPanGestureRecognizer) { 123 | let pos = sender.location(in: self) 124 | 125 | switch sender.state { 126 | case .changed: 127 | currentHue = hueAtPosition(pos.x, containingRect: bounds) 128 | sliderX.constant = constrainPosition(pos, toBounds: bounds) 129 | default: 130 | break 131 | } 132 | } 133 | 134 | @objc func colorTapped(_ sender: UITapGestureRecognizer) { 135 | let pos = sender.location(in: self) 136 | 137 | currentHue = hueAtPosition(pos.x, containingRect: bounds) 138 | sliderX.constant = constrainPosition(pos, toBounds: bounds) 139 | } 140 | 141 | // MARK: - Slider Management 142 | 143 | func setHueSlider() { 144 | guard let hue = currentHue else { return } 145 | sliderX.constant = borderWidth + hue * (bounds.width - 2 * borderWidth) 146 | } 147 | 148 | func constrainPosition(_ pos: CGPoint, toBounds rect: CGRect) -> CGFloat { 149 | let maximum = rect.width - borderWidth 150 | let minimum = borderWidth 151 | 152 | return max(min(pos.x, maximum), minimum) 153 | } 154 | 155 | func hueAtPosition(_ x: CGFloat, containingRect: CGRect) -> CGFloat { 156 | return min(max(x / (containingRect.width - 2 * borderWidth), 0), 1) 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /Source/PDColorPickerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDColorPickerViewController.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Creates a modal color picker view that allows the user 12 | /// to select hue, saturation, and brightness values in an 13 | /// easy to use, fast interface. 14 | /// 15 | /// To present the view controller, execute the following 16 | /// from the presenting view controller: 17 | /// 18 | /// let colorPickerVC = PDColorPickerViewController { _ in 19 | /// // handle completion 20 | /// } 21 | /// present(colorPickerVC, animated: true) 22 | /// 23 | /// **Note** Dimming the presenting view controller is recommended 24 | /// for a better appearance. 25 | /// See the `Dimmable` protocol. 26 | @available(iOS 9.0, *) 27 | open class PDColorPickerViewController: UIViewController { 28 | 29 | public enum HexStringCase { 30 | case upper, lower 31 | 32 | @available(*, deprecated, renamed: "upper") 33 | case uppercase 34 | @available(*, deprecated, renamed: "lower") 35 | case lowercase 36 | 37 | func applied(to string: String) -> String { 38 | switch self { 39 | case .uppercase: 40 | return string.uppercased() 41 | case .lowercase: 42 | return string.lowercased() 43 | case .upper: 44 | return string.uppercased() 45 | case .lower: 46 | return string.lowercased() 47 | } 48 | } 49 | } 50 | 51 | private struct LocalConstants { 52 | static let padding: CGFloat = 8 53 | } 54 | 55 | open override var preferredStatusBarStyle: UIStatusBarStyle { 56 | return .lightContent 57 | } 58 | 59 | // MARK: - Buttons 60 | 61 | lazy var saveButton: PDRoundedRectButton = { 62 | let button = PDRoundedRectButton(title: "Save", backColor: .white, foreColor: self.tintColor) 63 | 64 | button.addTarget(self, action: #selector(save), for: .touchUpInside) 65 | button.titleLabel?.font = boldFont 66 | 67 | return button 68 | }() 69 | 70 | lazy var cancelButton: PDRoundedRectButton = { 71 | let button = PDRoundedRectButton(title: "Cancel", backColor: .white, foreColor: .red) 72 | 73 | button.addTarget(self, action: #selector(cancel), for: .touchUpInside) 74 | button.titleLabel?.font = font 75 | 76 | return button 77 | }() 78 | 79 | // MARK: - Color Picking Views 80 | 81 | lazy var colorPickerView: PDColorPickerGridView = { 82 | let pickerView = PDColorPickerGridView() 83 | pickerView.delegate = self 84 | pickerView.dataSource = self 85 | return pickerView 86 | }() 87 | 88 | lazy var colorSliderView: PDColorPickerSliderView = { 89 | let sliderView = PDColorPickerSliderView() 90 | sliderView.delegate = self 91 | return sliderView 92 | }() 93 | 94 | var selectedColorLabel = PDSelectedColorLabel() 95 | 96 | // MARK: - Properties 97 | 98 | /// The tint color of the **Save** button. 99 | open var tintColor: UIColor { 100 | didSet { 101 | saveButton.foreColor = tintColor 102 | } 103 | } 104 | 105 | /// The background color of the view. 106 | /// The default value is `UIColor.lightGray` 107 | open var backgroundColor: UIColor = .lightGray { 108 | didSet { 109 | view.backgroundColor = backgroundColor 110 | } 111 | } 112 | 113 | /// The currently selected color of the color picker. 114 | open var currentColor: PDColor 115 | 116 | /// The completion handler that is called when the color picker is dismissed. 117 | open var completion: (PDColor?) -> () 118 | 119 | /// Whether or not to display the hexadecimal code in the selected color preview. 120 | /// The default value is `true`. 121 | open var showHexString = true 122 | 123 | /// Whether to display the hexadecimal code in `uppercase` or `lowercase`. 124 | /// This property has no effect if `showHexString` is set to `false`. 125 | /// The default is `uppercase`. 126 | open var hexStringCase: HexStringCase = .upper 127 | 128 | /// Whether or not to support Smart Invert Colors on iOS 11.0+. 129 | /// It is highly recommended to leave this value set to the default of true as 130 | /// inverted colors may cause unexpected behavior. 131 | open var supportSmartInvertColors = true { 132 | didSet { 133 | if #available(iOS 11.0, *) { 134 | selectedColorLabel.accessibilityIgnoresInvertColors = supportSmartInvertColors 135 | colorSliderView.accessibilityIgnoresInvertColors = supportSmartInvertColors 136 | colorPickerView.accessibilityIgnoresInvertColors = supportSmartInvertColors 137 | } else { 138 | print("\n\n[PDColorPicker] Warning: supportSmartInvertColors is only available on iOS 11.0 or later, be sure to check availability using #available(iOS 11.0, *).\n\n") 139 | } 140 | } 141 | } 142 | 143 | /// The font to be used on the **Cancel** button and color preview. 144 | /// 145 | /// The default value is the system font at size 18. 146 | open var font: UIFont = .systemFont(ofSize: 18) { 147 | didSet { 148 | cancelButton.titleLabel?.font = font 149 | selectedColorLabel.font = font 150 | } 151 | } 152 | 153 | /// The font to be used on the **Save** button. 154 | /// 155 | /// The default value is the bold system font at size 18. 156 | open var boldFont: UIFont = .boldSystemFont(ofSize: 18) { 157 | didSet { 158 | saveButton.titleLabel?.font = boldFont 159 | } 160 | } 161 | 162 | /// Whether or not to allow drag and drop of the color preview. 163 | /// 164 | /// The default value is `true`. 165 | open var allowsDragAndDrop: Bool = true { 166 | didSet { 167 | guard #available(iOS 11.0, *) else { 168 | print("\n\n[PDColorPicker] Warning: allowsDragAndDrop is only available on iOS 11.0 or later, be sure to check availability using #available(iOS 11.0, *).\n\n") 169 | return 170 | } 171 | 172 | if allowsDragAndDrop { 173 | selectedColorLabel.addInteraction(colorDragInteraction) 174 | } else { 175 | selectedColorLabel.removeInteraction(colorDragInteraction) 176 | } 177 | } 178 | } 179 | 180 | private lazy var colorDragInteraction: UIDragInteraction = { 181 | return UIDragInteraction(delegate: self) 182 | }() 183 | 184 | // MARK: - Initializer 185 | 186 | /** 187 | Creates a `PDColorPickerViewController` with an initial color, a tint color for the *Save* button, and a completion callback to handle the user response. 188 | 189 | - parameter initialColor: The starting color that the color picker should be set to. This parameter can be any `UIColor`. 190 | The hue, saturation, and brightness values will be parsed from the given color and used to provide the starting positions of the sliders. 191 | The default value is `UIColor.red` which places the hue slider to the left and the saturation/brightness slider in the top left. 192 | - parameter tintColor: Currently this property only affects the text color of the *Save* button. The default value is `UIColor.blue`. 193 | - parameter completion: The completion callback that is called when the user taps *Save* or *Cancel*. The callback returns a single `PDColor?` 194 | parameter that contains the selected color as a `PDColor` if the user taps *Save*, or `nil` if the user taps *Cancel*. 195 | The default completion is a blank closure (this allows implementation after initialization if necessary). 196 | - parameter selectedColor: The color selected by the user when `PDColorPickerViewController` is displayed. If the user cancels, the value is `nil`. 197 | */ 198 | public init(initialColor: UIColor = .red, tintColor: UIColor = .blue, completion: @escaping (_ selectedColor: PDColor?) -> () = { _ in }) { 199 | self.currentColor = PDColor(color: initialColor) 200 | self.tintColor = tintColor 201 | self.completion = completion 202 | 203 | super.init(nibName: nil, bundle: nil) 204 | 205 | modalPresentationStyle = .overCurrentContext 206 | modalPresentationCapturesStatusBarAppearance = true 207 | } 208 | 209 | required public init?(coder aDecoder: NSCoder) { 210 | fatalError("init(coder:) has not been implemented") 211 | } 212 | 213 | // MARK: - Life Cycle 214 | 215 | open override func viewDidLoad() { 216 | super.viewDidLoad() 217 | 218 | view.layer.shadowColor = UIColor.black.cgColor 219 | view.layer.shadowOpacity = 0.6 220 | view.layer.shadowRadius = 15 221 | view.layer.shadowOffset = CGSize(width: 0, height: 5) 222 | view.backgroundColor = backgroundColor 223 | 224 | setupViews() 225 | } 226 | 227 | private func setupViews() { 228 | view.addSubview(colorPickerView) 229 | colorPickerView.anchor(left: view.leftAnchor, right: view.rightAnchor, top: view.topAnchor) 230 | 231 | view.addSubview(colorSliderView) 232 | colorSliderView.anchor(left: view.leftAnchor, right: view.rightAnchor, top: colorPickerView.bottomAnchor, leftConstant: LocalConstants.padding, rightConstant: LocalConstants.padding, topConstant: LocalConstants.padding, height: 44) 233 | 234 | let stackView = UIStackView(arrangedSubviews: [cancelButton, saveButton, selectedColorLabel]) 235 | 236 | stackView.alignment = .center 237 | stackView.axis = .horizontal 238 | stackView.distribution = .fillEqually 239 | stackView.spacing = LocalConstants.padding 240 | 241 | view.addSubview(stackView) 242 | stackView.anchor(left: view.leftAnchor, right: view.rightAnchor, top: colorSliderView.bottomAnchor, bottom: view.bottomAnchor, leftConstant: LocalConstants.padding, rightConstant: LocalConstants.padding, topConstant: LocalConstants.padding, bottomConstant: LocalConstants.padding, height: 44) 243 | 244 | view.addConstraint( 245 | NSLayoutConstraint(item: selectedColorLabel, attribute: .height, relatedBy: .equal, toItem: saveButton, attribute: .height, multiplier: 1, constant: 0) 246 | ) 247 | 248 | if #available(iOS 11.0, *), allowsDragAndDrop { 249 | let colorDragInteraction = UIDragInteraction(delegate: self) 250 | selectedColorLabel.addInteraction(colorDragInteraction) 251 | } 252 | } 253 | 254 | var constraintsHaveBeenSet = false 255 | open override func viewDidLayoutSubviews() { 256 | super.viewDidLayoutSubviews() 257 | 258 | if !constraintsHaveBeenSet { 259 | updateViewFrame() 260 | 261 | selectedColorLabel.layer.cornerRadius = selectedColorLabel.frame.height / 2 262 | 263 | colorPickerView.currentColor = currentColor 264 | colorSliderView.currentHue = currentColor.h 265 | colorPickerView.fadeSlider(.in) 266 | 267 | colorChanged(to: currentColor) 268 | constraintsHaveBeenSet = true 269 | } 270 | } 271 | 272 | open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 273 | updateViewFrame() 274 | } 275 | 276 | open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 277 | updateViewFrame() 278 | } 279 | 280 | // MARK: - Button Targets 281 | 282 | @objc func save(_ sender: UIButton) { 283 | colorPickerView.fadeSlider(.out) 284 | 285 | completion(currentColor) 286 | dismiss(animated: true, completion: nil) 287 | } 288 | 289 | @objc func cancel(_ sender: UIButton) { 290 | colorPickerView.fadeSlider(.out) 291 | 292 | completion(nil) 293 | dismiss(animated: true, completion: nil) 294 | } 295 | 296 | // MARK: - Convenience 297 | 298 | private func updateViewFrame() { 299 | guard let pvc = presentingViewController else { return } 300 | let targetWidth = pvc.view.frame.width 301 | let targetHeight = pvc.view.frame.height 302 | let goldenRatio: CGFloat = 1.618 303 | 304 | if targetWidth > targetHeight { 305 | view.frame.size.height = targetHeight * 0.9 306 | view.frame.size.width = min(targetHeight * 0.9 * goldenRatio, targetWidth * 0.9) 307 | } else { 308 | view.frame.size.width = targetWidth * 0.9 309 | view.frame.size.height = min(targetWidth * 0.9 * goldenRatio, targetHeight * 0.9) 310 | } 311 | 312 | view.frame.origin.x = targetWidth / 2 - view.frame.width / 2 313 | view.frame.origin.y = targetHeight / 2 - view.frame.height / 2 314 | 315 | view.layoutIfNeeded() 316 | } 317 | 318 | } 319 | 320 | // MARK: - PDColorPickerDataSource 321 | @available(iOS 9.0, *) 322 | extension PDColorPickerViewController: PDColorPickerGridDataSource { 323 | func selectedHueForColorPicker() -> CGFloat? { 324 | return currentColor.h 325 | } 326 | } 327 | 328 | // MARK: - PDColorPickerDelegate 329 | @available(iOS 9.0, *) 330 | extension PDColorPickerViewController: PDColorPickerGridDelegate { 331 | func colorChanged(to newColor: PDColor) { 332 | currentColor = newColor 333 | selectedColorLabel.backgroundColor = currentColor.uiColor 334 | selectedColorLabel.textColor = newColor.appropriateForegroundColor 335 | selectedColorLabel.text = showHexString ? hexStringCase.applied(to: newColor.hex) : "" 336 | } 337 | } 338 | 339 | // MARK: - ColorSliderDelegate 340 | @available(iOS 9.0, *) 341 | extension PDColorPickerViewController: PDColorPickerSliderDelegate { 342 | func hueChanged(to newHue: CGFloat) { 343 | currentColor.h = newHue 344 | colorPickerView.selectedHue = newHue 345 | 346 | colorChanged(to: currentColor) 347 | } 348 | } 349 | 350 | // MARK: - UIDragInteractionDelegate 351 | @available(iOS 11.0, *) 352 | extension PDColorPickerViewController: UIDragInteractionDelegate { 353 | @available(iOS 11.0, *) 354 | public func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] { 355 | let colorItemProvider = NSItemProvider(object: currentColor.uiColor) 356 | return [UIDragItem(itemProvider: colorItemProvider)] 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /Source/PDPanGestureRecognizer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDPanGestureRecognizer.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/13/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// A testable subclass of `UIPanGestureRecognizer`. 12 | class PDPanGestureRecognizer: UIPanGestureRecognizer { 13 | 14 | let testTarget: Any? 15 | let testAction: Selector? 16 | 17 | var testState: UIGestureRecognizer.State? 18 | var testLocation: CGPoint? 19 | var testTranslation: CGPoint? 20 | 21 | // MARK: - Overrides 22 | 23 | override init(target: Any?, action: Selector?) { 24 | testTarget = target 25 | testAction = action 26 | super.init(target: target, action: action) 27 | } 28 | 29 | override var state: UIGestureRecognizer.State { 30 | get { 31 | if let testState = testState { 32 | return testState 33 | } 34 | 35 | return super.state 36 | } 37 | set { 38 | super.state = newValue 39 | } 40 | } 41 | 42 | override func location(in view: UIView?) -> CGPoint { 43 | if let testLocation = testLocation { 44 | return testLocation 45 | } 46 | 47 | return super.location(in: view) 48 | } 49 | 50 | override func translation(in view: UIView?) -> CGPoint { 51 | if let testTranslation = testTranslation { 52 | return testTranslation 53 | } 54 | 55 | return super.translation(in: view) 56 | } 57 | 58 | // MARK: - Test Touches 59 | 60 | func performTouch(location: CGPoint?, translation: CGPoint?, state: UIGestureRecognizer.State) { 61 | testLocation = location 62 | testTranslation = translation 63 | testState = state 64 | 65 | if let action = testAction { 66 | (testTarget as AnyObject).perform(action, on: .current, with: self, waitUntilDone: true) 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /Source/PDRoundedRectButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDRoundedRectButton.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PDRoundedRectButton: PDBouncyButton { 12 | 13 | var title: String { 14 | didSet { 15 | setTitle(title, for: .normal) 16 | titleLabel?.sizeToFit() 17 | } 18 | } 19 | 20 | var backColor: UIColor { 21 | didSet { backgroundColor = backColor } 22 | } 23 | 24 | var foreColor: UIColor { 25 | didSet { setTitleColor(foreColor, for: .normal) } 26 | } 27 | 28 | override var intrinsicContentSize: CGSize { 29 | guard let labelSize = titleLabel?.intrinsicContentSize else { return .zero } 30 | 31 | return CGSize(width: labelSize.width + contentEdgeInsets.left + contentEdgeInsets.right, height: super.intrinsicContentSize.height + contentEdgeInsets.top + contentEdgeInsets.bottom) 32 | } 33 | 34 | // MARK: - Initializer 35 | 36 | init(title: String, backColor: UIColor, foreColor: UIColor) { 37 | self.title = "" 38 | self.backColor = .black 39 | self.foreColor = .black 40 | 41 | super.init(frame: .zero) 42 | 43 | defer { 44 | self.title = title 45 | self.backColor = backColor 46 | self.foreColor = foreColor 47 | 48 | layer.shadowColor = UIColor.black.cgColor 49 | layer.shadowOffset = CGSize(width: 0, height: 0) 50 | layer.shadowOpacity = 0.6 51 | layer.shadowRadius = 4 52 | } 53 | } 54 | 55 | required init?(coder aDecoder: NSCoder) { 56 | fatalError("init(coder:) has not been implemented") 57 | } 58 | 59 | // MARK: - Life Cycle 60 | 61 | override func layoutSubviews() { 62 | super.layoutSubviews() 63 | 64 | layer.cornerRadius = bounds.height / 2 65 | contentEdgeInsets = UIEdgeInsets(top: 2, left: 6, bottom: 2, right: 6) 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Source/PDSelectedColorLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDSelectedColorLabel.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/31/18. 6 | // 7 | 8 | import UIKit 9 | 10 | class PDSelectedColorLabel: UILabel { 11 | 12 | init() { 13 | super.init(frame: .zero) 14 | 15 | clipsToBounds = true 16 | textAlignment = .center 17 | 18 | layer.borderWidth = 1.0 19 | layer.borderColor = UIColor.black.cgColor 20 | 21 | isUserInteractionEnabled = true 22 | 23 | if #available(iOS 11.0, *) { 24 | accessibilityIgnoresInvertColors = true 25 | } 26 | } 27 | 28 | required init?(coder aDecoder: NSCoder) { 29 | fatalError("init(coder:) has not been implemented") 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Source/PDTapGestureRecognizer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDTapGestureRecognizer.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 4/17/18. 6 | // Copyright © 2018 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// A testable subclass of `UITapGestureRecognizer`. 12 | class PDTapGestureRecognizer: UITapGestureRecognizer { 13 | 14 | let testTarget: Any? 15 | let testAction: Selector? 16 | 17 | var testState: UIGestureRecognizer.State? 18 | var testLocation: CGPoint? 19 | 20 | // MARK: - Overrides 21 | 22 | override init(target: Any?, action: Selector?) { 23 | testTarget = target 24 | testAction = action 25 | super.init(target: target, action: action) 26 | } 27 | 28 | override var state: UIGestureRecognizer.State { 29 | get { 30 | if let testState = testState { 31 | return testState 32 | } 33 | 34 | return super.state 35 | } 36 | set { 37 | super.state = newValue 38 | } 39 | } 40 | 41 | override func location(in view: UIView?) -> CGPoint { 42 | if let testLocation = testLocation { 43 | return testLocation 44 | } 45 | 46 | return super.location(in: view) 47 | } 48 | 49 | // MARK: - Test Touches 50 | 51 | func performTouch(location: CGPoint?, state: UIGestureRecognizer.State) { 52 | testLocation = location 53 | testState = state 54 | 55 | if let action = testAction { 56 | (testTarget as AnyObject).perform(action, on: .current, with: self, waitUntilDone: true) 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Source/UIView+Layout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Layout.swift 3 | // PDColorPicker 4 | // 5 | // Created by Paolo Di Lorenzo on 8/8/17. 6 | // Copyright © 2017 Paolo Di Lorenzo. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @available(iOS 9.0, *) 12 | extension UIView { 13 | 14 | /** 15 | Provides a convenient method for anchoring the receiver to other 16 | anchors within its view hierarchy. All parameters have default values of 17 | `nil` or `0` so only the desired constraints need be provided. 18 | 19 | This method should only be called *after* the receiver has been added to its superview, 20 | otherwise an exception may be thrown. 21 | 22 | This method automatically sets `translatesAutoresizingMaskIntoConstraints` to `false` on 23 | the receiver. 24 | 25 | All parameters are optional and are set to sensible defaults if ignored (e.g. `nil` or `0`). 26 | 27 | Example: 28 | 29 | ``` 30 | // in a UIView subclass: 31 | let aView = UIView() 32 | addSubview(aView) 33 | // sets aView to be positioned 10 points from the 34 | // containing view's left anchor 35 | aView.anchor(left: self.leftAnchor, leftConstant: 10) 36 | ``` 37 | 38 | - parameter left: The anchor to pin the left side of the receiver to. 39 | - parameter right: The anchor to pin the right side of the receiver to. 40 | - parameter top: The anchor to pin the top side of the receiver to. 41 | - parameter bottom: The anchor to pin the bottom side of the receiver to. 42 | - parameter leftConstant: The number of points of spacing given to the left side (increases to the right). 43 | - parameter rightConstant: The number of points of spacing given to the right side (increases to the left). 44 | - parameter topConstant: The number of points of spacing given to the top side (increases down). 45 | - parameter bottomConstant: The number of points of spacing given to the bottom side (increases up). 46 | - parameter height: The fixed height in points. 47 | - parameter width: The fixed width in points. 48 | */ 49 | func anchor(left: NSLayoutXAxisAnchor? = nil, 50 | right: NSLayoutXAxisAnchor? = nil, 51 | top: NSLayoutYAxisAnchor? = nil, 52 | bottom: NSLayoutYAxisAnchor? = nil, 53 | leftConstant: CGFloat = 0, 54 | rightConstant: CGFloat = 0, 55 | topConstant: CGFloat = 0, 56 | bottomConstant: CGFloat = 0, 57 | height: CGFloat = 0, 58 | width: CGFloat = 0) { 59 | 60 | translatesAutoresizingMaskIntoConstraints = false 61 | 62 | if let left = left { 63 | leftAnchor.constraint(equalTo: left, constant: leftConstant).isActive = true 64 | } 65 | 66 | if let right = right { 67 | rightAnchor.constraint(equalTo: right, constant: -rightConstant).isActive = true 68 | } 69 | 70 | if let top = top { 71 | topAnchor.constraint(equalTo: top, constant: topConstant).isActive = true 72 | } 73 | 74 | if let bottom = bottom { 75 | bottomAnchor.constraint(equalTo: bottom, constant: -bottomConstant).isActive = true 76 | } 77 | 78 | if width > 0 { 79 | widthAnchor.constraint(equalToConstant: width).isActive = true 80 | } 81 | 82 | if height > 0 { 83 | heightAnchor.constraint(equalToConstant: height).isActive = true 84 | } 85 | } 86 | 87 | func anchorFill(view: UIView? = nil) { 88 | guard let view = view ?? superview else { 89 | fatalError("No view provided, and a superview doesn't exist. Be sure to add the view as a subview before calling anchorFill().\n\n") 90 | } 91 | 92 | anchor(left: view.leftAnchor, right: view.rightAnchor, top: view.topAnchor, bottom: view.bottomAnchor) 93 | } 94 | 95 | } 96 | --------------------------------------------------------------------------------