├── .codebeatsettings ├── .codeclimate.yml ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE.md ├── .gitignore ├── .jazzy.yaml ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Example ├── HGCircularSlider.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── HGCircularSlider-Example.xcscheme ├── HGCircularSlider.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── HGCircularSlider │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── CircularSliderViewController.swift │ ├── ClockViewController.swift │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Bedtime.imageset │ │ │ ├── Bedtime.pdf │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Hours.imageset │ │ │ ├── Contents.json │ │ │ └── Hours.pdf │ │ ├── Wake.imageset │ │ │ ├── Contents.json │ │ │ └── Wake.pdf │ │ ├── first.imageset │ │ │ ├── Contents.json │ │ │ └── first.pdf │ │ ├── ic_bedtime.imageset │ │ │ ├── Contents.json │ │ │ └── ic_bedtime.pdf │ │ ├── ic_wake.imageset │ │ │ ├── Contents.json │ │ │ └── ic_wake.pdf │ │ ├── second.imageset │ │ │ ├── Contents.json │ │ │ └── second.pdf │ │ └── time_indicators.imageset │ │ │ ├── Contents.json │ │ │ └── time_indicators.pdf │ ├── Info.plist │ ├── OClockViewController.swift │ ├── OtherExampleViewController.swift │ ├── PlayerViewController.swift │ └── StrangeZero.mp3 ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── HGCircularSlider.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── HGCircularSlider │ │ ├── HGCircularSlider-Info.plist │ │ ├── HGCircularSlider-dummy.m │ │ ├── HGCircularSlider-prefix.pch │ │ ├── HGCircularSlider-umbrella.h │ │ ├── HGCircularSlider.modulemap │ │ ├── HGCircularSlider.xcconfig │ │ └── Info.plist │ │ ├── Pods-HGCircularSlider_Example │ │ ├── Info.plist │ │ ├── Pods-HGCircularSlider_Example-Info.plist │ │ ├── Pods-HGCircularSlider_Example-acknowledgements.markdown │ │ ├── Pods-HGCircularSlider_Example-acknowledgements.plist │ │ ├── Pods-HGCircularSlider_Example-dummy.m │ │ ├── Pods-HGCircularSlider_Example-frameworks.sh │ │ ├── Pods-HGCircularSlider_Example-resources.sh │ │ ├── Pods-HGCircularSlider_Example-umbrella.h │ │ ├── Pods-HGCircularSlider_Example.debug.xcconfig │ │ ├── Pods-HGCircularSlider_Example.modulemap │ │ └── Pods-HGCircularSlider_Example.release.xcconfig │ │ └── Pods-HGCircularSlider_Tests │ │ ├── Info.plist │ │ ├── Pods-HGCircularSlider_Tests-Info.plist │ │ ├── Pods-HGCircularSlider_Tests-acknowledgements.markdown │ │ ├── Pods-HGCircularSlider_Tests-acknowledgements.plist │ │ ├── Pods-HGCircularSlider_Tests-dummy.m │ │ ├── Pods-HGCircularSlider_Tests-frameworks.sh │ │ ├── Pods-HGCircularSlider_Tests-resources.sh │ │ ├── Pods-HGCircularSlider_Tests-umbrella.h │ │ ├── Pods-HGCircularSlider_Tests.debug.xcconfig │ │ ├── Pods-HGCircularSlider_Tests.modulemap │ │ └── Pods-HGCircularSlider_Tests.release.xcconfig └── Tests │ ├── CircularSliderHelperTests.swift │ ├── CircularSliderTests.swift │ ├── Info.plist │ └── Tests.swift ├── HGCircularSlider.podspec ├── HGCircularSlider.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── HGCircularSlider.xcscheme ├── HGCircularSlider ├── Assets │ └── .gitkeep ├── Classes │ ├── CircularSlider+Draw.swift │ ├── CircularSlider.swift │ ├── CircularSliderHelper.swift │ ├── MidPointCircularSlider.swift │ └── RangeCircularSlider.swift ├── HGCircularSlider.h └── Info.plist ├── HGCircularSliderTests ├── HGCircularSliderTests.swift └── Info.plist ├── LICENSE ├── Package.swift ├── README.md └── Screenshots ├── Bedtime.gif ├── Circular.gif ├── OClock.gif ├── Other.gif └── Player.gif /.codebeatsettings: -------------------------------------------------------------------------------- 1 | { 2 | "SWIFT": { 3 | "TOO_MANY_IVARS": [8, 12, 16, 20] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | exclude_patterns: 2 | - "Example/" -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: HamzaGhazouani 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | .DS_Store 67 | -------------------------------------------------------------------------------- /.jazzy.yaml: -------------------------------------------------------------------------------- 1 | jazzy --podspec HGCircularSlider.podspec 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | os: osx 3 | osx_image: 4 | - xcode10.2 5 | 6 | env: 7 | global: 8 | - IOS_SCHEME="HGCircularSlider" 9 | 10 | matrix: 11 | - DESTINATION="OS=12.0,name=iPhone X" 12 | SCHEME="$IOS_SCHEME" RUN_TESTS="YES" 13 | - DESTINATION="OS=10.3.1,name=iPhone 7 Plus" 14 | SCHEME="$IOS_SCHEME" RUN_TESTS="YES" 15 | - DESTINATION="OS=9.3,name=iPhone 5" 16 | SCHEME="$IOS_SCHEME" RUN_TESTS="YES" 17 | 18 | script: 19 | - set -o pipefail 20 | - xcodebuild -version 21 | - xcodebuild -showsdks 22 | 23 | - xcodebuild build -scheme "$SCHEME" -destination "$DESTINATION" -configuration Debug | xcpretty; 24 | - xcodebuild build -scheme "$SCHEME" -destination "$DESTINATION" -configuration Release | xcpretty; 25 | 26 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [2.2.0](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/2.2.0) 5 | * Support Swift 5 6 | * Fix the tracking when the value is equal to the max 7 | * Add option to stop thumb looping over the min/max value 8 | * Add offset thumb option, to draw the thumb inside or outside the circle 9 | 10 | ## [2.1.0](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/2.1.0) 11 | * Support Swift 4.2 version 12 | 13 | ## [2.0.0](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/2.0.0) 14 | * Added Carthage support 15 | * Added number of rounds, allowing to create slider same as Apple bedtime slider (12h clock with two rounds) 16 | * Added backtrack inspectable properties, allowing to modify its properties 17 | * Added shadow track color and offset inspectable attributes 18 | * Removed distance from default slider definition 19 | 20 | 21 | ## [1.1.0](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/1.1.0) 22 | 23 | * Fix Swift 3.1 warnings 24 | 25 | ## [1.0.3](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/1.0.3) 26 | 27 | * Change midPointValue from private to open 28 | * Imporve the documentation 29 | 30 | ## [1.0.2](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/1.0.2) 31 | 32 | * Update the documentation 33 | 34 | ## [1.0.1](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/1.0.1) 35 | 36 | * remove warnings 37 | 38 | ## [1.0.0](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/1.0.0) 39 | 40 | * Support for Swift 3.0. 41 | 42 | ## [0.1.2](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/0.1.2) 43 | 44 | * Add documentation 45 | * Last version that support Xcode 7.3.1 46 | 47 | ## [0.1.1](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/0.1.1) 48 | 49 | * Add new examples 50 | 51 | ## [0.1.0](https://github.com/HamzaGhazouani/HGCircularSlider/releases/tag/0.1.0) 52 | 53 | * Initial release. 54 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute 2 | 3 | ## Introduction 4 | 5 | First, thank you for considering contributing to HGCircularSlider! It's people like you that make the open source community such a great community! 😊 6 | 7 | We welcome any type of contribution, not only code. You can help with 8 | - **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open) 9 | - **Marketing**: writing blog posts, howto's, printing stickers, ... 10 | - **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ... 11 | - **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them. 12 | 13 | ## Your First Contribution 14 | 15 | Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github). 16 | 17 | ## Submitting code 18 | 19 | Any code change should be submitted as a pull request. The description should explain what the code does and give steps to execute it. The pull request should also contain tests. 20 | 21 | ## Code review process 22 | 23 | The bigger the pull request, the longer it will take to review and merge. Try to break down large pull requests in smaller chunks that are easier to review and merge. 24 | It is also always helpful to have some context for your pull request. What was the purpose? Why does it matter to you? 25 | -------------------------------------------------------------------------------- /Example/HGCircularSlider.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2DF970E3D7BE7173DEC1D05C /* Pods_HGCircularSlider_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C7918EC49141F7F4652E8F1 /* Pods_HGCircularSlider_Tests.framework */; }; 11 | 3EC27E521EA546F700631582 /* CircularSliderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EC27E511EA546F700631582 /* CircularSliderViewController.swift */; }; 12 | 551FF6F21DD3BFE300BD5B76 /* OtherExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551FF6F11DD3BFE300BD5B76 /* OtherExampleViewController.swift */; }; 13 | 5539B1B91DD275250038D49D /* PlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5539B1B81DD275250038D49D /* PlayerViewController.swift */; }; 14 | 5539B1BB1DD276C00038D49D /* StrangeZero.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 5539B1BA1DD276C00038D49D /* StrangeZero.mp3 */; }; 15 | 55CE65391DD3D32100B0C2B2 /* OClockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55CE65381DD3D32100B0C2B2 /* OClockViewController.swift */; }; 16 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 17 | 607FACD81AFB9204008FA782 /* ClockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ClockViewController.swift */; }; 18 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 19 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 20 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 21 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; 22 | BB409EA9235C82CE006DC844 /* CircularSliderHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB409EA7235C82CA006DC844 /* CircularSliderHelperTests.swift */; }; 23 | BB409EAB235C8ACE006DC844 /* CircularSliderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB409EAA235C8ACE006DC844 /* CircularSliderTests.swift */; }; 24 | BDF84380A076F46A79D0C634 /* Pods_HGCircularSlider_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 41A4019E034E0265198683A8 /* Pods_HGCircularSlider_Example.framework */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 33 | remoteInfo = HGCircularSlider; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 04EAC630898381E6412A72E4 /* Pods-HGCircularSlider_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HGCircularSlider_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example.debug.xcconfig"; sourceTree = ""; }; 39 | 2A9608AFE40174911E5079C3 /* Pods-HGCircularSlider_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HGCircularSlider_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests.debug.xcconfig"; sourceTree = ""; }; 40 | 3EC27E511EA546F700631582 /* CircularSliderViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircularSliderViewController.swift; sourceTree = ""; }; 41 | 41A4019E034E0265198683A8 /* Pods_HGCircularSlider_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HGCircularSlider_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 47EC1122B43F882A3D3679B7 /* HGCircularSlider.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = HGCircularSlider.podspec; path = ../HGCircularSlider.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 43 | 551FF6F11DD3BFE300BD5B76 /* OtherExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OtherExampleViewController.swift; sourceTree = ""; }; 44 | 5539B1B81DD275250038D49D /* PlayerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = ""; }; 45 | 5539B1BA1DD276C00038D49D /* StrangeZero.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = StrangeZero.mp3; sourceTree = ""; }; 46 | 55CE65381DD3D32100B0C2B2 /* OClockViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OClockViewController.swift; sourceTree = ""; }; 47 | 607FACD01AFB9204008FA782 /* HGCircularSlider_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HGCircularSlider_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 50 | 607FACD71AFB9204008FA782 /* ClockViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClockViewController.swift; sourceTree = ""; }; 51 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 52 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 53 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 54 | 607FACE51AFB9204008FA782 /* HGCircularSlider_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HGCircularSlider_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 57 | 6C7918EC49141F7F4652E8F1 /* Pods_HGCircularSlider_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HGCircularSlider_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 99A3B0410141275989079EB6 /* Pods-HGCircularSlider_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HGCircularSlider_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests.release.xcconfig"; sourceTree = ""; }; 59 | 9BA305BCC009CE17283FE799 /* Pods-HGCircularSlider_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HGCircularSlider_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example.release.xcconfig"; sourceTree = ""; }; 60 | BB409EA7235C82CA006DC844 /* CircularSliderHelperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircularSliderHelperTests.swift; sourceTree = ""; }; 61 | BB409EAA235C8ACE006DC844 /* CircularSliderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularSliderTests.swift; sourceTree = ""; }; 62 | E7D1A678D25EC3365B800DB3 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 63 | EEE4816CB037512E066C24A8 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 64 | /* End PBXFileReference section */ 65 | 66 | /* Begin PBXFrameworksBuildPhase section */ 67 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | BDF84380A076F46A79D0C634 /* Pods_HGCircularSlider_Example.framework in Frameworks */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | 2DF970E3D7BE7173DEC1D05C /* Pods_HGCircularSlider_Tests.framework in Frameworks */, 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | /* End PBXFrameworksBuildPhase section */ 84 | 85 | /* Begin PBXGroup section */ 86 | 5B27ED662D1EECB9DB261057 /* Pods */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 04EAC630898381E6412A72E4 /* Pods-HGCircularSlider_Example.debug.xcconfig */, 90 | 9BA305BCC009CE17283FE799 /* Pods-HGCircularSlider_Example.release.xcconfig */, 91 | 2A9608AFE40174911E5079C3 /* Pods-HGCircularSlider_Tests.debug.xcconfig */, 92 | 99A3B0410141275989079EB6 /* Pods-HGCircularSlider_Tests.release.xcconfig */, 93 | ); 94 | name = Pods; 95 | sourceTree = ""; 96 | }; 97 | 607FACC71AFB9204008FA782 = { 98 | isa = PBXGroup; 99 | children = ( 100 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 101 | 607FACD21AFB9204008FA782 /* Example for HGCircularSlider */, 102 | 607FACE81AFB9204008FA782 /* Tests */, 103 | 607FACD11AFB9204008FA782 /* Products */, 104 | 5B27ED662D1EECB9DB261057 /* Pods */, 105 | DE059D042D578ECE6977B31D /* Frameworks */, 106 | ); 107 | sourceTree = ""; 108 | }; 109 | 607FACD11AFB9204008FA782 /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 607FACD01AFB9204008FA782 /* HGCircularSlider_Example.app */, 113 | 607FACE51AFB9204008FA782 /* HGCircularSlider_Tests.xctest */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | 607FACD21AFB9204008FA782 /* Example for HGCircularSlider */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 122 | 3EC27E511EA546F700631582 /* CircularSliderViewController.swift */, 123 | 607FACD71AFB9204008FA782 /* ClockViewController.swift */, 124 | 5539B1B81DD275250038D49D /* PlayerViewController.swift */, 125 | 551FF6F11DD3BFE300BD5B76 /* OtherExampleViewController.swift */, 126 | 55CE65381DD3D32100B0C2B2 /* OClockViewController.swift */, 127 | 607FACD91AFB9204008FA782 /* Main.storyboard */, 128 | 5539B1BA1DD276C00038D49D /* StrangeZero.mp3 */, 129 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 130 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 131 | 607FACD31AFB9204008FA782 /* Supporting Files */, 132 | ); 133 | name = "Example for HGCircularSlider"; 134 | path = HGCircularSlider; 135 | sourceTree = ""; 136 | }; 137 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 607FACD41AFB9204008FA782 /* Info.plist */, 141 | ); 142 | name = "Supporting Files"; 143 | sourceTree = ""; 144 | }; 145 | 607FACE81AFB9204008FA782 /* Tests */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | BB409EA7235C82CA006DC844 /* CircularSliderHelperTests.swift */, 149 | BB409EAA235C8ACE006DC844 /* CircularSliderTests.swift */, 150 | 607FACEB1AFB9204008FA782 /* Tests.swift */, 151 | 607FACE91AFB9204008FA782 /* Supporting Files */, 152 | ); 153 | path = Tests; 154 | sourceTree = ""; 155 | }; 156 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 607FACEA1AFB9204008FA782 /* Info.plist */, 160 | ); 161 | name = "Supporting Files"; 162 | sourceTree = ""; 163 | }; 164 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | 47EC1122B43F882A3D3679B7 /* HGCircularSlider.podspec */, 168 | EEE4816CB037512E066C24A8 /* README.md */, 169 | E7D1A678D25EC3365B800DB3 /* LICENSE */, 170 | ); 171 | name = "Podspec Metadata"; 172 | sourceTree = ""; 173 | }; 174 | DE059D042D578ECE6977B31D /* Frameworks */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 41A4019E034E0265198683A8 /* Pods_HGCircularSlider_Example.framework */, 178 | 6C7918EC49141F7F4652E8F1 /* Pods_HGCircularSlider_Tests.framework */, 179 | ); 180 | name = Frameworks; 181 | sourceTree = ""; 182 | }; 183 | /* End PBXGroup section */ 184 | 185 | /* Begin PBXNativeTarget section */ 186 | 607FACCF1AFB9204008FA782 /* HGCircularSlider_Example */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "HGCircularSlider_Example" */; 189 | buildPhases = ( 190 | E9C30214565096BEB7531CD5 /* [CP] Check Pods Manifest.lock */, 191 | 607FACCC1AFB9204008FA782 /* Sources */, 192 | 607FACCD1AFB9204008FA782 /* Frameworks */, 193 | 607FACCE1AFB9204008FA782 /* Resources */, 194 | 91331C76A6F912B59276B544 /* [CP] Embed Pods Frameworks */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | ); 200 | name = HGCircularSlider_Example; 201 | productName = HGCircularSlider; 202 | productReference = 607FACD01AFB9204008FA782 /* HGCircularSlider_Example.app */; 203 | productType = "com.apple.product-type.application"; 204 | }; 205 | 607FACE41AFB9204008FA782 /* HGCircularSlider_Tests */ = { 206 | isa = PBXNativeTarget; 207 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "HGCircularSlider_Tests" */; 208 | buildPhases = ( 209 | 066A95928ECD5B97A483FA2F /* [CP] Check Pods Manifest.lock */, 210 | 607FACE11AFB9204008FA782 /* Sources */, 211 | 607FACE21AFB9204008FA782 /* Frameworks */, 212 | 607FACE31AFB9204008FA782 /* Resources */, 213 | ); 214 | buildRules = ( 215 | ); 216 | dependencies = ( 217 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */, 218 | ); 219 | name = HGCircularSlider_Tests; 220 | productName = Tests; 221 | productReference = 607FACE51AFB9204008FA782 /* HGCircularSlider_Tests.xctest */; 222 | productType = "com.apple.product-type.bundle.unit-test"; 223 | }; 224 | /* End PBXNativeTarget section */ 225 | 226 | /* Begin PBXProject section */ 227 | 607FACC81AFB9204008FA782 /* Project object */ = { 228 | isa = PBXProject; 229 | attributes = { 230 | LastSwiftUpdateCheck = 0720; 231 | LastUpgradeCheck = 1010; 232 | ORGANIZATIONNAME = CocoaPods; 233 | TargetAttributes = { 234 | 607FACCF1AFB9204008FA782 = { 235 | CreatedOnToolsVersion = 6.3.1; 236 | DevelopmentTeam = 62L4CLZDFB; 237 | LastSwiftMigration = 1020; 238 | ProvisioningStyle = Automatic; 239 | }; 240 | 607FACE41AFB9204008FA782 = { 241 | CreatedOnToolsVersion = 6.3.1; 242 | DevelopmentTeam = 62L4CLZDFB; 243 | LastSwiftMigration = 1020; 244 | ProvisioningStyle = Manual; 245 | TestTargetID = 607FACCF1AFB9204008FA782; 246 | }; 247 | }; 248 | }; 249 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "HGCircularSlider" */; 250 | compatibilityVersion = "Xcode 3.2"; 251 | developmentRegion = en; 252 | hasScannedForEncodings = 0; 253 | knownRegions = ( 254 | en, 255 | Base, 256 | ); 257 | mainGroup = 607FACC71AFB9204008FA782; 258 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 259 | projectDirPath = ""; 260 | projectRoot = ""; 261 | targets = ( 262 | 607FACCF1AFB9204008FA782 /* HGCircularSlider_Example */, 263 | 607FACE41AFB9204008FA782 /* HGCircularSlider_Tests */, 264 | ); 265 | }; 266 | /* End PBXProject section */ 267 | 268 | /* Begin PBXResourcesBuildPhase section */ 269 | 607FACCE1AFB9204008FA782 /* Resources */ = { 270 | isa = PBXResourcesBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 274 | 5539B1BB1DD276C00038D49D /* StrangeZero.mp3 in Resources */, 275 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 276 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | 607FACE31AFB9204008FA782 /* Resources */ = { 281 | isa = PBXResourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | /* End PBXResourcesBuildPhase section */ 288 | 289 | /* Begin PBXShellScriptBuildPhase section */ 290 | 066A95928ECD5B97A483FA2F /* [CP] Check Pods Manifest.lock */ = { 291 | isa = PBXShellScriptBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | ); 295 | inputPaths = ( 296 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 297 | "${PODS_ROOT}/Manifest.lock", 298 | ); 299 | name = "[CP] Check Pods Manifest.lock"; 300 | outputPaths = ( 301 | "$(DERIVED_FILE_DIR)/Pods-HGCircularSlider_Tests-checkManifestLockResult.txt", 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | shellPath = /bin/sh; 305 | 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"; 306 | showEnvVarsInLog = 0; 307 | }; 308 | 91331C76A6F912B59276B544 /* [CP] Embed Pods Frameworks */ = { 309 | isa = PBXShellScriptBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | ); 313 | inputPaths = ( 314 | "${PODS_ROOT}/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-frameworks.sh", 315 | "${BUILT_PRODUCTS_DIR}/HGCircularSlider/HGCircularSlider.framework", 316 | ); 317 | name = "[CP] Embed Pods Frameworks"; 318 | outputPaths = ( 319 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HGCircularSlider.framework", 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | shellPath = /bin/sh; 323 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-frameworks.sh\"\n"; 324 | showEnvVarsInLog = 0; 325 | }; 326 | E9C30214565096BEB7531CD5 /* [CP] Check Pods Manifest.lock */ = { 327 | isa = PBXShellScriptBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | ); 331 | inputPaths = ( 332 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 333 | "${PODS_ROOT}/Manifest.lock", 334 | ); 335 | name = "[CP] Check Pods Manifest.lock"; 336 | outputPaths = ( 337 | "$(DERIVED_FILE_DIR)/Pods-HGCircularSlider_Example-checkManifestLockResult.txt", 338 | ); 339 | runOnlyForDeploymentPostprocessing = 0; 340 | shellPath = /bin/sh; 341 | 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"; 342 | showEnvVarsInLog = 0; 343 | }; 344 | /* End PBXShellScriptBuildPhase section */ 345 | 346 | /* Begin PBXSourcesBuildPhase section */ 347 | 607FACCC1AFB9204008FA782 /* Sources */ = { 348 | isa = PBXSourcesBuildPhase; 349 | buildActionMask = 2147483647; 350 | files = ( 351 | 551FF6F21DD3BFE300BD5B76 /* OtherExampleViewController.swift in Sources */, 352 | 607FACD81AFB9204008FA782 /* ClockViewController.swift in Sources */, 353 | 3EC27E521EA546F700631582 /* CircularSliderViewController.swift in Sources */, 354 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 355 | 5539B1B91DD275250038D49D /* PlayerViewController.swift in Sources */, 356 | 55CE65391DD3D32100B0C2B2 /* OClockViewController.swift in Sources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | 607FACE11AFB9204008FA782 /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, 365 | BB409EAB235C8ACE006DC844 /* CircularSliderTests.swift in Sources */, 366 | BB409EA9235C82CE006DC844 /* CircularSliderHelperTests.swift in Sources */, 367 | ); 368 | runOnlyForDeploymentPostprocessing = 0; 369 | }; 370 | /* End PBXSourcesBuildPhase section */ 371 | 372 | /* Begin PBXTargetDependency section */ 373 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { 374 | isa = PBXTargetDependency; 375 | target = 607FACCF1AFB9204008FA782 /* HGCircularSlider_Example */; 376 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; 377 | }; 378 | /* End PBXTargetDependency section */ 379 | 380 | /* Begin PBXVariantGroup section */ 381 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = { 382 | isa = PBXVariantGroup; 383 | children = ( 384 | 607FACDA1AFB9204008FA782 /* Base */, 385 | ); 386 | name = Main.storyboard; 387 | sourceTree = ""; 388 | }; 389 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 390 | isa = PBXVariantGroup; 391 | children = ( 392 | 607FACDF1AFB9204008FA782 /* Base */, 393 | ); 394 | name = LaunchScreen.xib; 395 | sourceTree = ""; 396 | }; 397 | /* End PBXVariantGroup section */ 398 | 399 | /* Begin XCBuildConfiguration section */ 400 | 607FACED1AFB9204008FA782 /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | ALWAYS_SEARCH_USER_PATHS = NO; 404 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 405 | CLANG_CXX_LIBRARY = "libc++"; 406 | CLANG_ENABLE_MODULES = YES; 407 | CLANG_ENABLE_OBJC_ARC = YES; 408 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 409 | CLANG_WARN_BOOL_CONVERSION = YES; 410 | CLANG_WARN_COMMA = YES; 411 | CLANG_WARN_CONSTANT_CONVERSION = YES; 412 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 413 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INFINITE_RECURSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 419 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 420 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 422 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 423 | CLANG_WARN_STRICT_PROTOTYPES = YES; 424 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 425 | CLANG_WARN_UNREACHABLE_CODE = YES; 426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 427 | COPY_PHASE_STRIP = NO; 428 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 429 | ENABLE_STRICT_OBJC_MSGSEND = YES; 430 | ENABLE_TESTABILITY = YES; 431 | GCC_C_LANGUAGE_STANDARD = gnu99; 432 | GCC_DYNAMIC_NO_PIC = NO; 433 | GCC_NO_COMMON_BLOCKS = YES; 434 | GCC_OPTIMIZATION_LEVEL = 0; 435 | GCC_PREPROCESSOR_DEFINITIONS = ( 436 | "DEBUG=1", 437 | "$(inherited)", 438 | ); 439 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 440 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 441 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 442 | GCC_WARN_UNDECLARED_SELECTOR = YES; 443 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 444 | GCC_WARN_UNUSED_FUNCTION = YES; 445 | GCC_WARN_UNUSED_VARIABLE = YES; 446 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 447 | MTL_ENABLE_DEBUG_INFO = YES; 448 | ONLY_ACTIVE_ARCH = YES; 449 | SDKROOT = iphoneos; 450 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 451 | }; 452 | name = Debug; 453 | }; 454 | 607FACEE1AFB9204008FA782 /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | buildSettings = { 457 | ALWAYS_SEARCH_USER_PATHS = NO; 458 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 459 | CLANG_CXX_LIBRARY = "libc++"; 460 | CLANG_ENABLE_MODULES = YES; 461 | CLANG_ENABLE_OBJC_ARC = YES; 462 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 463 | CLANG_WARN_BOOL_CONVERSION = YES; 464 | CLANG_WARN_COMMA = YES; 465 | CLANG_WARN_CONSTANT_CONVERSION = YES; 466 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 467 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 468 | CLANG_WARN_EMPTY_BODY = YES; 469 | CLANG_WARN_ENUM_CONVERSION = YES; 470 | CLANG_WARN_INFINITE_RECURSION = YES; 471 | CLANG_WARN_INT_CONVERSION = YES; 472 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 473 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 474 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 475 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 476 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 477 | CLANG_WARN_STRICT_PROTOTYPES = YES; 478 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 479 | CLANG_WARN_UNREACHABLE_CODE = YES; 480 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 481 | COPY_PHASE_STRIP = NO; 482 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 483 | ENABLE_NS_ASSERTIONS = NO; 484 | ENABLE_STRICT_OBJC_MSGSEND = YES; 485 | GCC_C_LANGUAGE_STANDARD = gnu99; 486 | GCC_NO_COMMON_BLOCKS = YES; 487 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 488 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 489 | GCC_WARN_UNDECLARED_SELECTOR = YES; 490 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 491 | GCC_WARN_UNUSED_FUNCTION = YES; 492 | GCC_WARN_UNUSED_VARIABLE = YES; 493 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 494 | MTL_ENABLE_DEBUG_INFO = NO; 495 | SDKROOT = iphoneos; 496 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 497 | VALIDATE_PRODUCT = YES; 498 | }; 499 | name = Release; 500 | }; 501 | 607FACF01AFB9204008FA782 /* Debug */ = { 502 | isa = XCBuildConfiguration; 503 | baseConfigurationReference = 04EAC630898381E6412A72E4 /* Pods-HGCircularSlider_Example.debug.xcconfig */; 504 | buildSettings = { 505 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; 506 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 507 | CODE_SIGN_IDENTITY = "iPhone Developer"; 508 | "CODE_SIGN_IDENTITY[sdk=*]" = "iPhone Developer"; 509 | CODE_SIGN_STYLE = Automatic; 510 | DEVELOPMENT_TEAM = ""; 511 | "DEVELOPMENT_TEAM[sdk=*]" = 62L4CLZDFB; 512 | INFOPLIST_FILE = HGCircularSlider/Info.plist; 513 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 514 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 515 | MODULE_NAME = ExampleApp; 516 | PRODUCT_BUNDLE_IDENTIFIER = "robert-chalmers.uk.HGCircularSlider-Example"; 517 | PRODUCT_NAME = "$(TARGET_NAME)"; 518 | "PROVISIONING_PROFILE[arch=*]" = ""; 519 | PROVISIONING_PROFILE_SPECIFIER = ""; 520 | SWIFT_VERSION = 5.0; 521 | }; 522 | name = Debug; 523 | }; 524 | 607FACF11AFB9204008FA782 /* Release */ = { 525 | isa = XCBuildConfiguration; 526 | baseConfigurationReference = 9BA305BCC009CE17283FE799 /* Pods-HGCircularSlider_Example.release.xcconfig */; 527 | buildSettings = { 528 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; 529 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 530 | CODE_SIGN_IDENTITY = "iPhone Developer"; 531 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 532 | CODE_SIGN_STYLE = Automatic; 533 | DEVELOPMENT_TEAM = ""; 534 | "DEVELOPMENT_TEAM[sdk=*]" = 62L4CLZDFB; 535 | INFOPLIST_FILE = HGCircularSlider/Info.plist; 536 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 537 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 538 | MODULE_NAME = ExampleApp; 539 | PRODUCT_BUNDLE_IDENTIFIER = "robert-chalmers.uk.HGCircularSlider-Example"; 540 | PRODUCT_NAME = "$(TARGET_NAME)"; 541 | "PROVISIONING_PROFILE[arch=*]" = ""; 542 | PROVISIONING_PROFILE_SPECIFIER = ""; 543 | SWIFT_VERSION = 5.0; 544 | }; 545 | name = Release; 546 | }; 547 | 607FACF31AFB9204008FA782 /* Debug */ = { 548 | isa = XCBuildConfiguration; 549 | baseConfigurationReference = 2A9608AFE40174911E5079C3 /* Pods-HGCircularSlider_Tests.debug.xcconfig */; 550 | buildSettings = { 551 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 552 | DEVELOPMENT_TEAM = 62L4CLZDFB; 553 | GCC_PREPROCESSOR_DEFINITIONS = ( 554 | "DEBUG=1", 555 | "$(inherited)", 556 | ); 557 | INFOPLIST_FILE = Tests/Info.plist; 558 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 559 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 560 | PRODUCT_NAME = "$(TARGET_NAME)"; 561 | PROVISIONING_PROFILE_SPECIFIER = ""; 562 | SWIFT_VERSION = 5.0; 563 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HGCircularSlider_Example.app/HGCircularSlider_Example"; 564 | }; 565 | name = Debug; 566 | }; 567 | 607FACF41AFB9204008FA782 /* Release */ = { 568 | isa = XCBuildConfiguration; 569 | baseConfigurationReference = 99A3B0410141275989079EB6 /* Pods-HGCircularSlider_Tests.release.xcconfig */; 570 | buildSettings = { 571 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 572 | DEVELOPMENT_TEAM = 62L4CLZDFB; 573 | INFOPLIST_FILE = Tests/Info.plist; 574 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 575 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 576 | PRODUCT_NAME = "$(TARGET_NAME)"; 577 | PROVISIONING_PROFILE_SPECIFIER = ""; 578 | SWIFT_VERSION = 5.0; 579 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HGCircularSlider_Example.app/HGCircularSlider_Example"; 580 | }; 581 | name = Release; 582 | }; 583 | /* End XCBuildConfiguration section */ 584 | 585 | /* Begin XCConfigurationList section */ 586 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "HGCircularSlider" */ = { 587 | isa = XCConfigurationList; 588 | buildConfigurations = ( 589 | 607FACED1AFB9204008FA782 /* Debug */, 590 | 607FACEE1AFB9204008FA782 /* Release */, 591 | ); 592 | defaultConfigurationIsVisible = 0; 593 | defaultConfigurationName = Release; 594 | }; 595 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "HGCircularSlider_Example" */ = { 596 | isa = XCConfigurationList; 597 | buildConfigurations = ( 598 | 607FACF01AFB9204008FA782 /* Debug */, 599 | 607FACF11AFB9204008FA782 /* Release */, 600 | ); 601 | defaultConfigurationIsVisible = 0; 602 | defaultConfigurationName = Release; 603 | }; 604 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "HGCircularSlider_Tests" */ = { 605 | isa = XCConfigurationList; 606 | buildConfigurations = ( 607 | 607FACF31AFB9204008FA782 /* Debug */, 608 | 607FACF41AFB9204008FA782 /* Release */, 609 | ); 610 | defaultConfigurationIsVisible = 0; 611 | defaultConfigurationName = Release; 612 | }; 613 | /* End XCConfigurationList section */ 614 | }; 615 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 616 | } 617 | -------------------------------------------------------------------------------- /Example/HGCircularSlider.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/HGCircularSlider.xcodeproj/xcshareddata/xcschemes/HGCircularSlider-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 51 | 52 | 53 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 76 | 78 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Example/HGCircularSlider.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/HGCircularSlider.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // HGCircularSlider 4 | // 5 | // Created by Hamza Ghazouani on 10/19/2016. 6 | // Copyright (c) 2016 Hamza Ghazouani. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/CircularSliderViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularSliderViewController.swift 3 | // HGCircularSlider 4 | // 5 | // Created by Hamza Ghazouani on 16/04/2017. 6 | // Copyright © 2017 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | import HGCircularSlider 12 | 13 | class CircularSliderViewController: UIViewController { 14 | 15 | @IBOutlet weak var circularSlider: CircularSlider! 16 | @IBOutlet weak var roundsLabel: UILabel! 17 | @IBOutlet weak var maxValueLabel: UILabel! 18 | @IBOutlet weak var minValueLabel: UILabel! 19 | @IBOutlet weak var currentValueLabel: UILabel! 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | circularSlider.endPointValue = 1 25 | updateTexts() 26 | circularSlider.addTarget(self, action: #selector(updateTexts), for: .valueChanged) 27 | } 28 | 29 | override func didReceiveMemoryWarning() { 30 | super.didReceiveMemoryWarning() 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | @objc func updateTexts() { 35 | let value = circularSlider.endPointValue 36 | let ok = (circularSlider.maximumValue / CGFloat(circularSlider.numberOfRounds)) 37 | let ff = ceil(value / ok) 38 | 39 | maxValueLabel.text = String(format: "%.0f", circularSlider.maximumValue) 40 | minValueLabel.text = String(format: "%.0f", circularSlider.minimumValue) 41 | 42 | currentValueLabel.text = String(format: "%.0f", value) 43 | roundsLabel.text = "Round N° " + String(format: "%.0f", ff) 44 | } 45 | 46 | /* 47 | // MARK: - Navigation 48 | 49 | // In a storyboard-based application, you will often want to do a little preparation before navigation 50 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 51 | // Get the new view controller using segue.destinationViewController. 52 | // Pass the selected object to the new view controller. 53 | } 54 | */ 55 | 56 | } 57 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/ClockViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // HGCircularSlider 4 | // 5 | // Created by Hamza Ghazouani on 10/19/2016. 6 | // Copyright (c) 2016 Hamza Ghazouani. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import HGCircularSlider 11 | 12 | extension Date { 13 | 14 | } 15 | 16 | class ClockViewController: UIViewController { 17 | 18 | 19 | @IBOutlet weak var durationLabel: UILabel! 20 | @IBOutlet weak var bedtimeLabel: UILabel! 21 | @IBOutlet weak var wakeLabel: UILabel! 22 | @IBOutlet weak var rangeCircularSlider: RangeCircularSlider! 23 | @IBOutlet weak var clockFormatSegmentedControl: UISegmentedControl! 24 | 25 | lazy var dateFormatter: DateFormatter = { 26 | let dateFormatter = DateFormatter() 27 | dateFormatter.timeZone = TimeZone(abbreviation: "UTC") 28 | dateFormatter.dateFormat = "hh:mm a" 29 | return dateFormatter 30 | }() 31 | 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | 36 | // setup O'clock 37 | rangeCircularSlider.startThumbImage = UIImage(named: "Bedtime") 38 | rangeCircularSlider.endThumbImage = UIImage(named: "Wake") 39 | 40 | let dayInSeconds = 24 * 60 * 60 41 | rangeCircularSlider.maximumValue = CGFloat(dayInSeconds) 42 | 43 | rangeCircularSlider.startPointValue = 1 * 60 * 60 44 | rangeCircularSlider.endPointValue = 8 * 60 * 60 45 | 46 | updateTexts(rangeCircularSlider) 47 | } 48 | 49 | override func didReceiveMemoryWarning() { 50 | super.didReceiveMemoryWarning() 51 | // Dispose of any resources that can be recreated. 52 | } 53 | 54 | @IBAction func updateTexts(_ sender: AnyObject) { 55 | 56 | adjustValue(value: &rangeCircularSlider.startPointValue) 57 | adjustValue(value: &rangeCircularSlider.endPointValue) 58 | 59 | 60 | let bedtime = TimeInterval(rangeCircularSlider.startPointValue) 61 | let bedtimeDate = Date(timeIntervalSinceReferenceDate: bedtime) 62 | bedtimeLabel.text = dateFormatter.string(from: bedtimeDate) 63 | 64 | let wake = TimeInterval(rangeCircularSlider.endPointValue) 65 | let wakeDate = Date(timeIntervalSinceReferenceDate: wake) 66 | wakeLabel.text = dateFormatter.string(from: wakeDate) 67 | 68 | let duration = wake - bedtime 69 | let durationDate = Date(timeIntervalSinceReferenceDate: duration) 70 | dateFormatter.dateFormat = "HH:mm" 71 | durationLabel.text = dateFormatter.string(from: durationDate) 72 | dateFormatter.dateFormat = "hh:mm a" 73 | } 74 | 75 | func adjustValue(value: inout CGFloat) { 76 | let minutes = value / 60 77 | let adjustedMinutes = ceil(minutes / 5.0) * 5 78 | value = adjustedMinutes * 60 79 | } 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "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 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/Bedtime.imageset/Bedtime.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/Bedtime.imageset/Bedtime.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/Bedtime.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Bedtime.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/Hours.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Hours.pdf", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/Hours.imageset/Hours.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/Hours.imageset/Hours.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/Wake.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Wake.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/Wake.imageset/Wake.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/Wake.imageset/Wake.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "first.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/first.imageset/first.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/first.imageset/first.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/ic_bedtime.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_bedtime.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | }, 12 | "properties" : { 13 | "template-rendering-intent" : "template" 14 | } 15 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/ic_bedtime.imageset/ic_bedtime.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/ic_bedtime.imageset/ic_bedtime.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/ic_wake.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_wake.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/ic_wake.imageset/ic_wake.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/ic_wake.imageset/ic_wake.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "second.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/second.imageset/second.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/second.imageset/second.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/time_indicators.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "time_indicators.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/HGCircularSlider/Images.xcassets/time_indicators.imageset/time_indicators.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/Images.xcassets/time_indicators.imageset/time_indicators.pdf -------------------------------------------------------------------------------- /Example/HGCircularSlider/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/OClockViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OClockViewController.swift 3 | // HGCircularSlider 4 | // 5 | // Created by Hamza Ghazouani on 09/11/2016. 6 | // Copyright © 2016 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import HGCircularSlider 11 | 12 | class OClockViewController: UIViewController { 13 | 14 | @IBOutlet weak var minutesCircularSlider: CircularSlider! 15 | @IBOutlet weak var hoursCircularSlider: CircularSlider! 16 | 17 | @IBOutlet weak var hoursLabel: UILabel! 18 | @IBOutlet weak var minutesLabel: UILabel! 19 | @IBOutlet weak var AMPMLabel: UILabel! 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | setupSliders() 25 | } 26 | 27 | override func didReceiveMemoryWarning() { 28 | super.didReceiveMemoryWarning() 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | func setupSliders() { 33 | // hours 34 | hoursCircularSlider.minimumValue = 0 35 | hoursCircularSlider.maximumValue = 12 36 | hoursCircularSlider.endPointValue = 6 37 | hoursCircularSlider.addTarget(self, action: #selector(updateHours), for: .valueChanged) 38 | hoursCircularSlider.addTarget(self, action: #selector(adjustHours), for: .editingDidEnd) 39 | 40 | // minutes 41 | minutesCircularSlider.minimumValue = 0 42 | minutesCircularSlider.maximumValue = 60 43 | minutesCircularSlider.endPointValue = 35 44 | minutesCircularSlider.addTarget(self, action: #selector(updateMinutes), for: .valueChanged) 45 | minutesCircularSlider.addTarget(self, action: #selector(adjustMinutes), for: .editingDidEnd) 46 | } 47 | 48 | // MARK: user interaction methods 49 | 50 | @objc func updateHours() { 51 | var selectedHour = Int(hoursCircularSlider.endPointValue) 52 | // TODO: use date formatter 53 | selectedHour = (selectedHour == 0 ? 12 : selectedHour) 54 | hoursLabel.text = String(format: "%02d", selectedHour) 55 | } 56 | 57 | @objc func adjustHours() { 58 | let selectedHour = round(hoursCircularSlider.endPointValue) 59 | hoursCircularSlider.endPointValue = selectedHour 60 | updateHours() 61 | } 62 | 63 | @objc func updateMinutes() { 64 | var selectedMinute = Int(minutesCircularSlider.endPointValue) 65 | // TODO: use date formatter 66 | selectedMinute = (selectedMinute == 60 ? 0 : selectedMinute) 67 | minutesLabel.text = String(format: "%02d", selectedMinute) 68 | } 69 | 70 | @objc func adjustMinutes() { 71 | let selectedMinute = round(minutesCircularSlider.endPointValue) 72 | minutesCircularSlider.endPointValue = selectedMinute 73 | updateMinutes() 74 | } 75 | 76 | @IBAction func switchBetweenAMAndPM(_ sender: UISegmentedControl) { 77 | AMPMLabel.text = sender.selectedSegmentIndex == 0 ? "AM" : "PM" 78 | } 79 | 80 | 81 | /* 82 | // MARK: - Navigation 83 | 84 | // In a storyboard-based application, you will often want to do a little preparation before navigation 85 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 86 | // Get the new view controller using segue.destinationViewController. 87 | // Pass the selected object to the new view controller. 88 | } 89 | */ 90 | 91 | } 92 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/OtherExampleViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OtherExampleViewController.swift 3 | // HGCircularSlider 4 | // 5 | // Created by Hamza Ghazouani on 09/11/2016. 6 | // Copyright © 2016 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import HGCircularSlider 11 | 12 | extension CALayer { 13 | 14 | func borderUIColor() -> UIColor? { 15 | return borderColor != nil ? UIColor(cgColor: borderColor!) : nil 16 | } 17 | 18 | func setBorderUIColor(_ color: UIColor) { 19 | borderColor = color.cgColor 20 | } 21 | } 22 | 23 | class OtherExampleViewController: UIViewController { 24 | 25 | @IBOutlet weak var circularSlider: MidPointCircularSlider! 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | 30 | circularSlider.minimumValue = 0.0 31 | circularSlider.maximumValue = 10.0 32 | circularSlider.distance = 1.0 33 | circularSlider.midPointValue = 5.0 34 | } 35 | 36 | override func didReceiveMemoryWarning() { 37 | super.didReceiveMemoryWarning() 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | 42 | /* 43 | // MARK: - Navigation 44 | 45 | // In a storyboard-based application, you will often want to do a little preparation before navigation 46 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 47 | // Get the new view controller using segue.destinationViewController. 48 | // Pass the selected object to the new view controller. 49 | } 50 | */ 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/PlayerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerViewController.swift 3 | // HGCircularSlider 4 | // 5 | // Created by Hamza Ghazouani on 08/11/2016. 6 | // Copyright © 2016 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import AVFoundation 11 | 12 | import HGCircularSlider 13 | 14 | /* 15 | KVO context used to differentiate KVO callbacks for this class versus other 16 | classes in its class hierarchy. 17 | */ 18 | private var playerViewControllerKVOContext = 0 19 | 20 | 21 | class PlayerViewController: UIViewController { 22 | 23 | @IBOutlet weak var circularSlider: CircularSlider! 24 | @IBOutlet weak var timerLabel: UILabel! 25 | @IBOutlet weak var playerSegmentedControl: UISegmentedControl! 26 | 27 | let audioPlayer = AVPlayer() 28 | 29 | // date formatter user for timer label 30 | let dateComponentsFormatter: DateComponentsFormatter = { 31 | let formatter = DateComponentsFormatter() 32 | formatter.zeroFormattingBehavior = .pad 33 | formatter.allowedUnits = [.minute, .second] 34 | 35 | return formatter 36 | }() 37 | 38 | override func viewDidLoad() { 39 | super.viewDidLoad() 40 | 41 | setupAudioPlayer() 42 | 43 | circularSlider.addTarget(self, action: #selector(pause), for: .editingDidBegin) 44 | circularSlider.addTarget(self, action: #selector(play), for: .editingDidEnd) 45 | circularSlider.addTarget(self, action: #selector(updateTimer), for: .valueChanged) 46 | 47 | NotificationCenter.default.addObserver(self, 48 | selector: #selector(playerItemDidReachEnd(_:)), 49 | name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, 50 | object: audioPlayer.currentItem) 51 | } 52 | 53 | override func didReceiveMemoryWarning() { 54 | super.didReceiveMemoryWarning() 55 | // Dispose of any resources that can be recreated. 56 | } 57 | 58 | @IBAction func togglePlayer(_ sender: UISegmentedControl) { 59 | switch sender.selectedSegmentIndex { 60 | case 0: 61 | let currentTime = Float64(circularSlider.endPointValue) 62 | let newTime = CMTimeMakeWithSeconds(currentTime, preferredTimescale: 600) 63 | audioPlayer.seek(to: newTime, toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero) 64 | audioPlayer.play() 65 | default: 66 | audioPlayer.pause() 67 | } 68 | } 69 | 70 | @objc func play() { 71 | self.playerSegmentedControl.selectedSegmentIndex = 0 72 | togglePlayer(playerSegmentedControl) 73 | } 74 | 75 | @objc func pause() { 76 | self.playerSegmentedControl.selectedSegmentIndex = UISegmentedControl.noSegment 77 | togglePlayer(playerSegmentedControl) 78 | } 79 | 80 | 81 | /** 82 | setup and play the sound of the local mp3 file 83 | */ 84 | func setupAudioPlayer() { 85 | // TODO: load the audio file asynchronously and observe player status 86 | guard let audioFileURL = Bundle.main.url(forResource: "StrangeZero", withExtension: "mp3") else { return } 87 | let asset = AVURLAsset(url: audioFileURL, options: nil) 88 | let playerItem = AVPlayerItem(asset: asset) 89 | audioPlayer.replaceCurrentItem(with: playerItem) 90 | audioPlayer.actionAtItemEnd = .pause 91 | 92 | let durationInSeconds = CMTimeGetSeconds(asset.duration) 93 | circularSlider.maximumValue = CGFloat(durationInSeconds) 94 | let interval = CMTimeMake(value: 1, timescale: 4) 95 | audioPlayer.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main) { 96 | [weak self] time in 97 | let seconds = CMTimeGetSeconds(time) 98 | self?.updatePlayerUI(withCurrentTime: CGFloat(seconds)) 99 | } 100 | 101 | self.audioPlayer.play() 102 | } 103 | 104 | 105 | // update the slider position and the timer text 106 | func updatePlayerUI(withCurrentTime currentTime: CGFloat) { 107 | circularSlider.endPointValue = currentTime 108 | var components = DateComponents() 109 | components.second = Int(currentTime) 110 | timerLabel.text = dateComponentsFormatter.string(from: components) 111 | } 112 | 113 | @objc func updateTimer() { 114 | var components = DateComponents() 115 | components.second = Int(circularSlider.endPointValue) 116 | timerLabel.text = dateComponentsFormatter.string(from: components) 117 | } 118 | 119 | // MARK: - Notification 120 | 121 | @objc func playerItemDidReachEnd(_ notification: Notification) { 122 | if let playerItem: AVPlayerItem = notification.object as? AVPlayerItem { 123 | playerItem.seek(to: CMTime.zero, toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero,completionHandler:nil) 124 | playerSegmentedControl.selectedSegmentIndex = UISegmentedControl.noSegment 125 | } 126 | } 127 | 128 | /* 129 | // MARK: - Navigation 130 | 131 | // In a storyboard-based application, you will often want to do a little preparation before navigation 132 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 133 | // Get the new view controller using segue.destinationViewController. 134 | // Pass the selected object to the new view controller. 135 | } 136 | */ 137 | } 138 | -------------------------------------------------------------------------------- /Example/HGCircularSlider/StrangeZero.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Example/HGCircularSlider/StrangeZero.mp3 -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | platform :ios, '12.0' 3 | 4 | target 'HGCircularSlider_Example' do 5 | pod 'HGCircularSlider', :path => '../' 6 | 7 | target 'HGCircularSlider_Tests' do 8 | inherit! :search_paths 9 | 10 | 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - HGCircularSlider (2.2.0) 3 | 4 | DEPENDENCIES: 5 | - HGCircularSlider (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | HGCircularSlider: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | HGCircularSlider: afb1942743a2df156dcc7a3500216e523e14266b 13 | 14 | PODFILE CHECKSUM: 5935efe45bed5ee625cec9162a170ce99849ca5c 15 | 16 | COCOAPODS: 1.7.5 17 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/HGCircularSlider.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HGCircularSlider", 3 | "version": "2.2.0", 4 | "summary": "Multiple Circular Sliders used to select a value from a continuous range of values.", 5 | "swift_versions": "5.0", 6 | "description": "Circular Sliders used to select a value from a continuous range of values.\n\nCircularSlider: simple circular slider\nRangeCircularSlider: slider with two points to select a range of values from a continuous range of values\nMidPointCircularSlider: slider with fixed range to select a range of values from a continuois range of values", 7 | "homepage": "https://github.com/HamzaGhazouani/HGCircularSlider", 8 | "license": { 9 | "type": "MIT", 10 | "file": "LICENSE" 11 | }, 12 | "authors": { 13 | "Hamza Ghazouani": "hamza.ghazouani@gmail.com" 14 | }, 15 | "source": { 16 | "git": "https://github.com/HamzaGhazouani/HGCircularSlider.git", 17 | "tag": "2.2.0" 18 | }, 19 | "social_media_url": "https://twitter.com/GhazouaniHamza", 20 | "platforms": { 21 | "ios": "8.0" 22 | }, 23 | "source_files": "HGCircularSlider/Classes/**/*", 24 | "swift_version": "5.0" 25 | } 26 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - HGCircularSlider (2.2.0) 3 | 4 | DEPENDENCIES: 5 | - HGCircularSlider (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | HGCircularSlider: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | HGCircularSlider: afb1942743a2df156dcc7a3500216e523e14266b 13 | 14 | PODFILE CHECKSUM: 5935efe45bed5ee625cec9162a170ce99849ca5c 15 | 16 | COCOAPODS: 1.7.5 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/HGCircularSlider/HGCircularSlider-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 | FMWK 17 | CFBundleShortVersionString 18 | 2.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/HGCircularSlider/HGCircularSlider-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_HGCircularSlider : NSObject 3 | @end 4 | @implementation PodsDummy_HGCircularSlider 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/HGCircularSlider/HGCircularSlider-prefix.pch: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/HGCircularSlider/HGCircularSlider-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 HGCircularSliderVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char HGCircularSliderVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/HGCircularSlider/HGCircularSlider.modulemap: -------------------------------------------------------------------------------- 1 | framework module HGCircularSlider { 2 | umbrella header "HGCircularSlider-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/HGCircularSlider/HGCircularSlider.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/HGCircularSlider/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 | FMWK 17 | CFBundleShortVersionString 18 | 2.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## HGCircularSlider 5 | 6 | Copyright (c) 2016 Hamza Ghazouani 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2016 Hamza Ghazouani <hamza.ghazouani@gmail.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | HGCircularSlider 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_HGCircularSlider_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_HGCircularSlider_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 13 | # frameworks to, so exit 0 (signalling the script phase was successful). 14 | exit 0 15 | fi 16 | 17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 19 | 20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 22 | 23 | # Used as a return value for each invocation of `strip_invalid_archs` function. 24 | STRIP_BINARY_RETVAL=0 25 | 26 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 27 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 28 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 29 | 30 | # Copies and strips a vendored framework 31 | install_framework() 32 | { 33 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 34 | local source="${BUILT_PRODUCTS_DIR}/$1" 35 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 36 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 37 | elif [ -r "$1" ]; then 38 | local source="$1" 39 | fi 40 | 41 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 42 | 43 | if [ -L "${source}" ]; then 44 | echo "Symlinked..." 45 | source="$(readlink "${source}")" 46 | fi 47 | 48 | # Use filter instead of exclude so missing patterns don't throw errors. 49 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 50 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 51 | 52 | local basename 53 | basename="$(basename -s .framework "$1")" 54 | binary="${destination}/${basename}.framework/${basename}" 55 | 56 | if ! [ -r "$binary" ]; then 57 | binary="${destination}/${basename}" 58 | elif [ -L "${binary}" ]; then 59 | echo "Destination binary is symlinked..." 60 | dirname="$(dirname "${binary}")" 61 | binary="${dirname}/$(readlink "${binary}")" 62 | fi 63 | 64 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 65 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 66 | strip_invalid_archs "$binary" 67 | fi 68 | 69 | # Resign the code if required by the build settings to avoid unstable apps 70 | code_sign_if_enabled "${destination}/$(basename "$1")" 71 | 72 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 73 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 74 | local swift_runtime_libs 75 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) 76 | for lib in $swift_runtime_libs; do 77 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 78 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 79 | code_sign_if_enabled "${destination}/${lib}" 80 | done 81 | fi 82 | } 83 | 84 | # Copies and strips a vendored dSYM 85 | install_dsym() { 86 | local source="$1" 87 | if [ -r "$source" ]; then 88 | # Copy the dSYM into a the targets temp dir. 89 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 90 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 91 | 92 | local basename 93 | basename="$(basename -s .framework.dSYM "$source")" 94 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 95 | 96 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 97 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then 98 | strip_invalid_archs "$binary" 99 | fi 100 | 101 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 102 | # Move the stripped file into its final destination. 103 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 104 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 105 | else 106 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 107 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 108 | fi 109 | fi 110 | } 111 | 112 | # Copies the bcsymbolmap files of a vendored framework 113 | install_bcsymbolmap() { 114 | local bcsymbolmap_path="$1" 115 | local destination="${BUILT_PRODUCTS_DIR}" 116 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" 117 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" 118 | } 119 | 120 | # Signs a framework with the provided identity 121 | code_sign_if_enabled() { 122 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 123 | # Use the current code_sign_identity 124 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 125 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 126 | 127 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 128 | code_sign_cmd="$code_sign_cmd &" 129 | fi 130 | echo "$code_sign_cmd" 131 | eval "$code_sign_cmd" 132 | fi 133 | } 134 | 135 | # Strip invalid architectures 136 | strip_invalid_archs() { 137 | binary="$1" 138 | # Get architectures for current target binary 139 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 140 | # Intersect them with the architectures we are building for 141 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 142 | # If there are no archs supported by this binary then warn the user 143 | if [[ -z "$intersected_archs" ]]; then 144 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 145 | STRIP_BINARY_RETVAL=0 146 | return 147 | fi 148 | stripped="" 149 | for arch in $binary_archs; do 150 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 151 | # Strip non-valid architectures in-place 152 | lipo -remove "$arch" -output "$binary" "$binary" 153 | stripped="$stripped $arch" 154 | fi 155 | done 156 | if [[ "$stripped" ]]; then 157 | echo "Stripped $binary of architectures:$stripped" 158 | fi 159 | STRIP_BINARY_RETVAL=1 160 | } 161 | 162 | 163 | if [[ "$CONFIGURATION" == "Debug" ]]; then 164 | install_framework "${BUILT_PRODUCTS_DIR}/HGCircularSlider/HGCircularSlider.framework" 165 | fi 166 | if [[ "$CONFIGURATION" == "Release" ]]; then 167 | install_framework "${BUILT_PRODUCTS_DIR}/HGCircularSlider/HGCircularSlider.framework" 168 | fi 169 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 170 | wait 171 | fi 172 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example-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 Pods_HGCircularSlider_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_HGCircularSlider_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider/HGCircularSlider.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "HGCircularSlider" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_HGCircularSlider_Example { 2 | umbrella header "Pods-HGCircularSlider_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Example/Pods-HGCircularSlider_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider/HGCircularSlider.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "HGCircularSlider" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_HGCircularSlider_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_HGCircularSlider_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests-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 Pods_HGCircularSlider_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_HGCircularSlider_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider/HGCircularSlider.framework/Headers" 4 | OTHER_LDFLAGS = $(inherited) -framework "HGCircularSlider" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_HGCircularSlider_Tests { 2 | umbrella header "Pods-HGCircularSlider_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-HGCircularSlider_Tests/Pods-HGCircularSlider_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/HGCircularSlider/HGCircularSlider.framework/Headers" 4 | OTHER_LDFLAGS = $(inherited) -framework "HGCircularSlider" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Tests/CircularSliderHelperTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularSliderHelperTests.swift 3 | // HGCircularSlider_Tests 4 | // 5 | // Created by Hamza GHAZOUANI on 24/07/2019. 6 | // Copyright © 2019 CocoaPods. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import HGCircularSlider 11 | 12 | extension CGFloat { 13 | 14 | var toDegrees: CGFloat { 15 | return self * 180.0 / CGFloat(Double.pi) 16 | } 17 | } 18 | 19 | class CircularSliderHelperTests: XCTestCase { 20 | 21 | let cirlceInterval = Interval(min: 0 , max: CGFloat(2 * Double.pi)) 22 | let valuesInterval = Interval(min: 0, max: 1.2) 23 | 24 | func testInitialValueScale() { 25 | // Given 26 | let value = valuesInterval.min 27 | 28 | // Thene 29 | let angle = CircularSliderHelper.scaleValue(value, fromInterval: valuesInterval, toInterval: cirlceInterval).toDegrees 30 | XCTAssertEqual(angle, 0) 31 | } 32 | 33 | func testFinalValueScale() { 34 | // Given 35 | let value: CGFloat = valuesInterval.max 36 | 37 | // Thene 38 | let angle = CircularSliderHelper.scaleValue(value, fromInterval: valuesInterval, toInterval: cirlceInterval).toDegrees 39 | XCTAssertEqual(angle, 360) 40 | } 41 | 42 | func testMedianValueScale() { 43 | // Given 44 | let value: CGFloat = valuesInterval.max / 2 45 | 46 | // Thene 47 | let angle = CircularSliderHelper.scaleValue(value, fromInterval: valuesInterval, toInterval: cirlceInterval).toDegrees 48 | XCTAssertEqual(angle, 180) 49 | } 50 | 51 | func testValueFromRangeToAnotherRangeMinValueEqualToZero() { 52 | let oldRange = Interval(min: 0, max: 100) 53 | let newRange = Interval(min: 10, max: 20) 54 | 55 | let value: CGFloat = 10 56 | 57 | let newValue = CircularSliderHelper.scaleValue(value, fromInterval: oldRange, toInterval: newRange) 58 | 59 | XCTAssertEqual(newValue, 11) 60 | } 61 | 62 | func testValueFromRangeToAnotherRangeMinValueGratherThanZero() { 63 | let oldRange = Interval(min: 5, max: 30) 64 | let newRange = Interval(min: 0, max: 100) 65 | 66 | let value: CGFloat = 10 67 | 68 | let newValue = CircularSliderHelper.scaleValue(value, fromInterval: oldRange, toInterval: newRange) 69 | 70 | XCTAssertEqual(newValue, 20) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Example/Tests/CircularSliderTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularSliderTests.swift 3 | // HGCircularSlider_Tests 4 | // 5 | // Created by Hamza on 20/10/2019. 6 | // Copyright © 2019 CocoaPods. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import HGCircularSlider 11 | 12 | class CircularSliderTests: XCTestCase { 13 | 14 | func testEndPointPositionWithZeroAsInitialValueAnd90DegreesAsTouchPosition() { 15 | // Given 16 | let circularSlider = CircularSlider(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) 17 | let startPosition = CGPoint(x: 25, y: 0) 18 | circularSlider.minimumValue = 0 19 | circularSlider.maximumValue = 100 20 | circularSlider.endPointValue = 0 21 | 22 | let touchPosition = CGPoint(x: 50, y: 25) 23 | 24 | // When 25 | let newValue = circularSlider.newValue(from: circularSlider.endPointValue, touch: touchPosition, start: startPosition) 26 | 27 | // Then 28 | XCTAssertEqual(newValue, 25, accuracy: 0.001) 29 | } 30 | 31 | func testEndPointPositionWithValueGratherThanZeroAsInitialValueAnd90DegreesAsTouchPosition() { 32 | // Given 33 | let circularSlider = CircularSlider(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) 34 | let startPosition = CGPoint(x: 25, y: 0) 35 | circularSlider.minimumValue = 5 36 | circularSlider.maximumValue = 25 37 | circularSlider.endPointValue = 5 38 | 39 | let touchPosition = CGPoint(x: 50, y: 25) 40 | 41 | // When 42 | let newValue = circularSlider.newValue(from: circularSlider.endPointValue, touch: touchPosition, start: startPosition) 43 | 44 | // Then 45 | XCTAssertEqual(newValue, 10, accuracy: 0.001) 46 | } 47 | 48 | func testndPointPositionWithValueGratherThanZeroAsInitialValueAnd180DegreesAsTouchPosition() { 49 | // Given 50 | let circularSlider = CircularSlider(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) 51 | let startPosition = CGPoint(x: 25, y: 0) 52 | circularSlider.minimumValue = 5 53 | circularSlider.maximumValue = 25 54 | circularSlider.endPointValue = 10 55 | 56 | let touchPosition = CGPoint(x: 25, y: 50) 57 | 58 | // When 59 | let newValue = circularSlider.newValue(from: circularSlider.endPointValue, touch: touchPosition, start: startPosition) 60 | 61 | // Then 62 | XCTAssertEqual(newValue, 15, accuracy: 0.001) 63 | } 64 | 65 | func testndPointPositionWithValueGratherThanZeroAsInitialValueAnd270DegreesAsTouchPosition() { 66 | // Given 67 | let circularSlider = CircularSlider(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) 68 | let startPosition = CGPoint(x: 25, y: 0) 69 | circularSlider.minimumValue = 5 70 | circularSlider.maximumValue = 25 71 | circularSlider.endPointValue = 10 72 | 73 | let touchPosition = CGPoint(x: 0, y: 25) 74 | 75 | // When 76 | let newValue = circularSlider.newValue(from: circularSlider.endPointValue, touch: touchPosition, start: startPosition) 77 | 78 | // Then 79 | XCTAssertEqual(newValue, 20, accuracy: 0.001) 80 | } 81 | 82 | func testndPointPositionWithValueGratherThanZeroAsInitialValueAnd360DegreesAsTouchPosition() { 83 | // Given 84 | let circularSlider = CircularSlider(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) 85 | let startPosition = CGPoint(x: 25, y: 0) 86 | circularSlider.minimumValue = 5 87 | circularSlider.maximumValue = 25 88 | circularSlider.endPointValue = 10 89 | 90 | let touchPosition = CGPoint(x: 24.999, y: 0) 91 | 92 | // When 93 | let newValue = circularSlider.newValue(from: circularSlider.endPointValue, touch: touchPosition, start: startPosition) 94 | 95 | // Then 96 | XCTAssertEqual(newValue, 25, accuracy: 0.001) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Example/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 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import XCTest 3 | import HGCircularSlider 4 | 5 | class Tests: XCTestCase { 6 | 7 | override func setUp() { 8 | super.setUp() 9 | // Put setup code here. This method is called before the invocation of each test method in the class. 10 | } 11 | 12 | override func tearDown() { 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | super.tearDown() 15 | } 16 | 17 | func testExample() { 18 | // This is an example of a functional test case. 19 | XCTAssert(true, "Pass") 20 | } 21 | 22 | func testPerformanceExample() { 23 | // This is an example of a performance test case. 24 | self.measure() { 25 | // Put the code you want to measure the time of here. 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /HGCircularSlider.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint HGCircularSlider.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 = 'HGCircularSlider' 11 | s.version = '2.2.0' 12 | s.summary = 'Multiple Circular Sliders used to select a value from a continuous range of values.' 13 | s.swift_version = '5.0' 14 | 15 | s.description = <<-DESC 16 | Circular Sliders used to select a value from a continuous range of values. 17 | 18 | CircularSlider: simple circular slider 19 | RangeCircularSlider: slider with two points to select a range of values from a continuous range of values 20 | MidPointCircularSlider: slider with fixed range to select a range of values from a continuois range of values 21 | 22 | DESC 23 | 24 | s.homepage = 'https://github.com/HamzaGhazouani/HGCircularSlider' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { 'Hamza Ghazouani' => 'hamza.ghazouani@gmail.com' } 28 | s.source = { :git => 'https://github.com/HamzaGhazouani/HGCircularSlider.git', :tag => s.version.to_s } 29 | s.social_media_url = 'https://twitter.com/GhazouaniHamza' 30 | 31 | s.ios.deployment_target = '9.0' 32 | 33 | s.source_files = 'HGCircularSlider/Classes/**/*' 34 | 35 | end 36 | -------------------------------------------------------------------------------- /HGCircularSlider.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BB692D2E235C9EB300CB74DA /* HGCircularSliderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB692D2D235C9EB300CB74DA /* HGCircularSliderTests.swift */; }; 11 | BB692D30235C9EB300CB74DA /* HGCircularSlider.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCDBFDDB1E43366F005D6F08 /* HGCircularSlider.framework */; }; 12 | BB692D37235C9F1100CB74DA /* CircularSliderHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB692D36235C9F1100CB74DA /* CircularSliderHelperTests.swift */; }; 13 | BB692D39235C9F1C00CB74DA /* CircularSliderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB692D38235C9F1C00CB74DA /* CircularSliderTests.swift */; }; 14 | CCCC96461E9F7FD000999D34 /* MidPointCircularSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCCC96451E9F7FD000999D34 /* MidPointCircularSlider.swift */; }; 15 | CCDBFDE01E43366F005D6F08 /* HGCircularSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = CCDBFDDE1E43366F005D6F08 /* HGCircularSlider.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16 | CCDBFDFD1E4336C9005D6F08 /* .gitkeep in Resources */ = {isa = PBXBuildFile; fileRef = CCDBFDF61E4336C9005D6F08 /* .gitkeep */; }; 17 | CCDBFDFF1E4336C9005D6F08 /* CircularSlider+Draw.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDBFDF91E4336C9005D6F08 /* CircularSlider+Draw.swift */; }; 18 | CCDBFE001E4336C9005D6F08 /* CircularSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDBFDFA1E4336C9005D6F08 /* CircularSlider.swift */; }; 19 | CCDBFE011E4336C9005D6F08 /* CircularSliderHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDBFDFB1E4336C9005D6F08 /* CircularSliderHelper.swift */; }; 20 | CCDBFE021E4336C9005D6F08 /* RangeCircularSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDBFDFC1E4336C9005D6F08 /* RangeCircularSlider.swift */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | BB692D31235C9EB300CB74DA /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = CCDBFDD21E43366F005D6F08 /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = CCDBFDDA1E43366F005D6F08; 29 | remoteInfo = HGCircularSlider; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | BB692D2B235C9EB300CB74DA /* HGCircularSliderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HGCircularSliderTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | BB692D2D235C9EB300CB74DA /* HGCircularSliderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HGCircularSliderTests.swift; sourceTree = ""; }; 36 | BB692D2F235C9EB300CB74DA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | BB692D36235C9F1100CB74DA /* CircularSliderHelperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CircularSliderHelperTests.swift; path = Example/Tests/CircularSliderHelperTests.swift; sourceTree = SOURCE_ROOT; }; 38 | BB692D38235C9F1C00CB74DA /* CircularSliderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CircularSliderTests.swift; path = Example/Tests/CircularSliderTests.swift; sourceTree = SOURCE_ROOT; }; 39 | CCCC96451E9F7FD000999D34 /* MidPointCircularSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MidPointCircularSlider.swift; sourceTree = ""; }; 40 | CCDBFDDB1E43366F005D6F08 /* HGCircularSlider.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HGCircularSlider.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | CCDBFDDE1E43366F005D6F08 /* HGCircularSlider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HGCircularSlider.h; sourceTree = ""; }; 42 | CCDBFDDF1E43366F005D6F08 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | CCDBFDF61E4336C9005D6F08 /* .gitkeep */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; 44 | CCDBFDF91E4336C9005D6F08 /* CircularSlider+Draw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CircularSlider+Draw.swift"; sourceTree = ""; }; 45 | CCDBFDFA1E4336C9005D6F08 /* CircularSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircularSlider.swift; sourceTree = ""; }; 46 | CCDBFDFB1E4336C9005D6F08 /* CircularSliderHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircularSliderHelper.swift; sourceTree = ""; }; 47 | CCDBFDFC1E4336C9005D6F08 /* RangeCircularSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RangeCircularSlider.swift; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | BB692D28235C9EB300CB74DA /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | BB692D30235C9EB300CB74DA /* HGCircularSlider.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | CCDBFDD71E43366F005D6F08 /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | BB692D2C235C9EB300CB74DA /* HGCircularSliderTests */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | BB692D36235C9F1100CB74DA /* CircularSliderHelperTests.swift */, 73 | BB692D38235C9F1C00CB74DA /* CircularSliderTests.swift */, 74 | BB692D2D235C9EB300CB74DA /* HGCircularSliderTests.swift */, 75 | BB692D2F235C9EB300CB74DA /* Info.plist */, 76 | ); 77 | path = HGCircularSliderTests; 78 | sourceTree = ""; 79 | }; 80 | CCDBFDD11E43366F005D6F08 = { 81 | isa = PBXGroup; 82 | children = ( 83 | CCDBFDDD1E43366F005D6F08 /* HGCircularSlider */, 84 | BB692D2C235C9EB300CB74DA /* HGCircularSliderTests */, 85 | CCDBFDDC1E43366F005D6F08 /* Products */, 86 | ); 87 | sourceTree = ""; 88 | }; 89 | CCDBFDDC1E43366F005D6F08 /* Products */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | CCDBFDDB1E43366F005D6F08 /* HGCircularSlider.framework */, 93 | BB692D2B235C9EB300CB74DA /* HGCircularSliderTests.xctest */, 94 | ); 95 | name = Products; 96 | sourceTree = ""; 97 | }; 98 | CCDBFDDD1E43366F005D6F08 /* HGCircularSlider */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | CCDBFDF51E4336C9005D6F08 /* Assets */, 102 | CCDBFDF71E4336C9005D6F08 /* Classes */, 103 | CCDBFDDE1E43366F005D6F08 /* HGCircularSlider.h */, 104 | CCDBFDDF1E43366F005D6F08 /* Info.plist */, 105 | ); 106 | path = HGCircularSlider; 107 | sourceTree = ""; 108 | }; 109 | CCDBFDF51E4336C9005D6F08 /* Assets */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | CCDBFDF61E4336C9005D6F08 /* .gitkeep */, 113 | ); 114 | path = Assets; 115 | sourceTree = ""; 116 | }; 117 | CCDBFDF71E4336C9005D6F08 /* Classes */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | CCDBFDF91E4336C9005D6F08 /* CircularSlider+Draw.swift */, 121 | CCDBFDFA1E4336C9005D6F08 /* CircularSlider.swift */, 122 | CCDBFDFB1E4336C9005D6F08 /* CircularSliderHelper.swift */, 123 | CCCC96451E9F7FD000999D34 /* MidPointCircularSlider.swift */, 124 | CCDBFDFC1E4336C9005D6F08 /* RangeCircularSlider.swift */, 125 | ); 126 | path = Classes; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXHeadersBuildPhase section */ 132 | CCDBFDD81E43366F005D6F08 /* Headers */ = { 133 | isa = PBXHeadersBuildPhase; 134 | buildActionMask = 2147483647; 135 | files = ( 136 | CCDBFDE01E43366F005D6F08 /* HGCircularSlider.h in Headers */, 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXHeadersBuildPhase section */ 141 | 142 | /* Begin PBXNativeTarget section */ 143 | BB692D2A235C9EB300CB74DA /* HGCircularSliderTests */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = BB692D35235C9EB300CB74DA /* Build configuration list for PBXNativeTarget "HGCircularSliderTests" */; 146 | buildPhases = ( 147 | BB692D27235C9EB300CB74DA /* Sources */, 148 | BB692D28235C9EB300CB74DA /* Frameworks */, 149 | BB692D29235C9EB300CB74DA /* Resources */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | BB692D32235C9EB300CB74DA /* PBXTargetDependency */, 155 | ); 156 | name = HGCircularSliderTests; 157 | productName = HGCircularSliderTests; 158 | productReference = BB692D2B235C9EB300CB74DA /* HGCircularSliderTests.xctest */; 159 | productType = "com.apple.product-type.bundle.unit-test"; 160 | }; 161 | CCDBFDDA1E43366F005D6F08 /* HGCircularSlider */ = { 162 | isa = PBXNativeTarget; 163 | buildConfigurationList = CCDBFDE31E43366F005D6F08 /* Build configuration list for PBXNativeTarget "HGCircularSlider" */; 164 | buildPhases = ( 165 | CCDBFDD61E43366F005D6F08 /* Sources */, 166 | CCDBFDD71E43366F005D6F08 /* Frameworks */, 167 | CCDBFDD81E43366F005D6F08 /* Headers */, 168 | CCDBFDD91E43366F005D6F08 /* Resources */, 169 | ); 170 | buildRules = ( 171 | ); 172 | dependencies = ( 173 | ); 174 | name = HGCircularSlider; 175 | productName = HGCircularSlider; 176 | productReference = CCDBFDDB1E43366F005D6F08 /* HGCircularSlider.framework */; 177 | productType = "com.apple.product-type.framework"; 178 | }; 179 | /* End PBXNativeTarget section */ 180 | 181 | /* Begin PBXProject section */ 182 | CCDBFDD21E43366F005D6F08 /* Project object */ = { 183 | isa = PBXProject; 184 | attributes = { 185 | LastSwiftUpdateCheck = 1110; 186 | LastUpgradeCheck = 1020; 187 | ORGANIZATIONNAME = intive; 188 | TargetAttributes = { 189 | BB692D2A235C9EB300CB74DA = { 190 | CreatedOnToolsVersion = 11.1; 191 | ProvisioningStyle = Automatic; 192 | }; 193 | CCDBFDDA1E43366F005D6F08 = { 194 | CreatedOnToolsVersion = 8.2.1; 195 | DevelopmentTeam = R6JBLAQ685; 196 | ProvisioningStyle = Automatic; 197 | }; 198 | }; 199 | }; 200 | buildConfigurationList = CCDBFDD51E43366F005D6F08 /* Build configuration list for PBXProject "HGCircularSlider" */; 201 | compatibilityVersion = "Xcode 3.2"; 202 | developmentRegion = en; 203 | hasScannedForEncodings = 0; 204 | knownRegions = ( 205 | en, 206 | Base, 207 | ); 208 | mainGroup = CCDBFDD11E43366F005D6F08; 209 | productRefGroup = CCDBFDDC1E43366F005D6F08 /* Products */; 210 | projectDirPath = ""; 211 | projectRoot = ""; 212 | targets = ( 213 | CCDBFDDA1E43366F005D6F08 /* HGCircularSlider */, 214 | BB692D2A235C9EB300CB74DA /* HGCircularSliderTests */, 215 | ); 216 | }; 217 | /* End PBXProject section */ 218 | 219 | /* Begin PBXResourcesBuildPhase section */ 220 | BB692D29235C9EB300CB74DA /* Resources */ = { 221 | isa = PBXResourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | CCDBFDD91E43366F005D6F08 /* Resources */ = { 228 | isa = PBXResourcesBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | CCDBFDFD1E4336C9005D6F08 /* .gitkeep in Resources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXResourcesBuildPhase section */ 236 | 237 | /* Begin PBXSourcesBuildPhase section */ 238 | BB692D27235C9EB300CB74DA /* Sources */ = { 239 | isa = PBXSourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | BB692D2E235C9EB300CB74DA /* HGCircularSliderTests.swift in Sources */, 243 | BB692D39235C9F1C00CB74DA /* CircularSliderTests.swift in Sources */, 244 | BB692D37235C9F1100CB74DA /* CircularSliderHelperTests.swift in Sources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | CCDBFDD61E43366F005D6F08 /* Sources */ = { 249 | isa = PBXSourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | CCDBFDFF1E4336C9005D6F08 /* CircularSlider+Draw.swift in Sources */, 253 | CCDBFE021E4336C9005D6F08 /* RangeCircularSlider.swift in Sources */, 254 | CCDBFE001E4336C9005D6F08 /* CircularSlider.swift in Sources */, 255 | CCCC96461E9F7FD000999D34 /* MidPointCircularSlider.swift in Sources */, 256 | CCDBFE011E4336C9005D6F08 /* CircularSliderHelper.swift in Sources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | /* End PBXSourcesBuildPhase section */ 261 | 262 | /* Begin PBXTargetDependency section */ 263 | BB692D32235C9EB300CB74DA /* PBXTargetDependency */ = { 264 | isa = PBXTargetDependency; 265 | target = CCDBFDDA1E43366F005D6F08 /* HGCircularSlider */; 266 | targetProxy = BB692D31235C9EB300CB74DA /* PBXContainerItemProxy */; 267 | }; 268 | /* End PBXTargetDependency section */ 269 | 270 | /* Begin XCBuildConfiguration section */ 271 | BB692D33235C9EB300CB74DA /* Debug */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 275 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 276 | CLANG_ENABLE_OBJC_WEAK = YES; 277 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 278 | CODE_SIGN_STYLE = Automatic; 279 | GCC_C_LANGUAGE_STANDARD = gnu11; 280 | INFOPLIST_FILE = HGCircularSliderTests/Info.plist; 281 | IPHONEOS_DEPLOYMENT_TARGET = 13.1; 282 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 283 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 284 | MTL_FAST_MATH = YES; 285 | PRODUCT_BUNDLE_IDENTIFIER = com.github.HGCircularSliderTests; 286 | PRODUCT_NAME = "$(TARGET_NAME)"; 287 | SWIFT_VERSION = 5.0; 288 | TARGETED_DEVICE_FAMILY = "1,2"; 289 | }; 290 | name = Debug; 291 | }; 292 | BB692D34235C9EB300CB74DA /* Release */ = { 293 | isa = XCBuildConfiguration; 294 | buildSettings = { 295 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 296 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 297 | CLANG_ENABLE_OBJC_WEAK = YES; 298 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 299 | CODE_SIGN_STYLE = Automatic; 300 | GCC_C_LANGUAGE_STANDARD = gnu11; 301 | INFOPLIST_FILE = HGCircularSliderTests/Info.plist; 302 | IPHONEOS_DEPLOYMENT_TARGET = 13.1; 303 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 304 | MTL_FAST_MATH = YES; 305 | PRODUCT_BUNDLE_IDENTIFIER = com.github.HGCircularSliderTests; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SWIFT_VERSION = 5.0; 308 | TARGETED_DEVICE_FAMILY = "1,2"; 309 | }; 310 | name = Release; 311 | }; 312 | CCDBFDE11E43366F005D6F08 /* Debug */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 317 | CLANG_ANALYZER_NONNULL = YES; 318 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 319 | CLANG_CXX_LIBRARY = "libc++"; 320 | CLANG_ENABLE_MODULES = YES; 321 | CLANG_ENABLE_OBJC_ARC = YES; 322 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 323 | CLANG_WARN_BOOL_CONVERSION = YES; 324 | CLANG_WARN_COMMA = YES; 325 | CLANG_WARN_CONSTANT_CONVERSION = YES; 326 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 327 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 328 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 329 | CLANG_WARN_EMPTY_BODY = YES; 330 | CLANG_WARN_ENUM_CONVERSION = YES; 331 | CLANG_WARN_INFINITE_RECURSION = YES; 332 | CLANG_WARN_INT_CONVERSION = YES; 333 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 334 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 335 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 336 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 337 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 338 | CLANG_WARN_STRICT_PROTOTYPES = YES; 339 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 340 | CLANG_WARN_UNREACHABLE_CODE = YES; 341 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 342 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 343 | COPY_PHASE_STRIP = NO; 344 | CURRENT_PROJECT_VERSION = 1; 345 | DEBUG_INFORMATION_FORMAT = dwarf; 346 | ENABLE_STRICT_OBJC_MSGSEND = YES; 347 | ENABLE_TESTABILITY = YES; 348 | GCC_C_LANGUAGE_STANDARD = gnu99; 349 | GCC_DYNAMIC_NO_PIC = NO; 350 | GCC_NO_COMMON_BLOCKS = YES; 351 | GCC_OPTIMIZATION_LEVEL = 0; 352 | GCC_PREPROCESSOR_DEFINITIONS = ( 353 | "DEBUG=1", 354 | "$(inherited)", 355 | ); 356 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 357 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 358 | GCC_WARN_UNDECLARED_SELECTOR = YES; 359 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 360 | GCC_WARN_UNUSED_FUNCTION = YES; 361 | GCC_WARN_UNUSED_VARIABLE = YES; 362 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 363 | MTL_ENABLE_DEBUG_INFO = YES; 364 | ONLY_ACTIVE_ARCH = YES; 365 | SDKROOT = iphoneos; 366 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 367 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 368 | TARGETED_DEVICE_FAMILY = "1,2"; 369 | VERSIONING_SYSTEM = "apple-generic"; 370 | VERSION_INFO_PREFIX = ""; 371 | }; 372 | name = Debug; 373 | }; 374 | CCDBFDE21E43366F005D6F08 /* Release */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | ALWAYS_SEARCH_USER_PATHS = NO; 378 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 379 | CLANG_ANALYZER_NONNULL = YES; 380 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 381 | CLANG_CXX_LIBRARY = "libc++"; 382 | CLANG_ENABLE_MODULES = YES; 383 | CLANG_ENABLE_OBJC_ARC = YES; 384 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 385 | CLANG_WARN_BOOL_CONVERSION = YES; 386 | CLANG_WARN_COMMA = YES; 387 | CLANG_WARN_CONSTANT_CONVERSION = YES; 388 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 389 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 390 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 391 | CLANG_WARN_EMPTY_BODY = YES; 392 | CLANG_WARN_ENUM_CONVERSION = YES; 393 | CLANG_WARN_INFINITE_RECURSION = YES; 394 | CLANG_WARN_INT_CONVERSION = YES; 395 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 396 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 400 | CLANG_WARN_STRICT_PROTOTYPES = YES; 401 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 402 | CLANG_WARN_UNREACHABLE_CODE = YES; 403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 405 | COPY_PHASE_STRIP = NO; 406 | CURRENT_PROJECT_VERSION = 1; 407 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 408 | ENABLE_NS_ASSERTIONS = NO; 409 | ENABLE_STRICT_OBJC_MSGSEND = YES; 410 | GCC_C_LANGUAGE_STANDARD = gnu99; 411 | GCC_NO_COMMON_BLOCKS = YES; 412 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 413 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 414 | GCC_WARN_UNDECLARED_SELECTOR = YES; 415 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 416 | GCC_WARN_UNUSED_FUNCTION = YES; 417 | GCC_WARN_UNUSED_VARIABLE = YES; 418 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 419 | MTL_ENABLE_DEBUG_INFO = NO; 420 | SDKROOT = iphoneos; 421 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 422 | TARGETED_DEVICE_FAMILY = "1,2"; 423 | VALIDATE_PRODUCT = YES; 424 | VERSIONING_SYSTEM = "apple-generic"; 425 | VERSION_INFO_PREFIX = ""; 426 | }; 427 | name = Release; 428 | }; 429 | CCDBFDE41E43366F005D6F08 /* Debug */ = { 430 | isa = XCBuildConfiguration; 431 | buildSettings = { 432 | CODE_SIGN_IDENTITY = ""; 433 | DEFINES_MODULE = YES; 434 | DEVELOPMENT_TEAM = R6JBLAQ685; 435 | DYLIB_COMPATIBILITY_VERSION = 1; 436 | DYLIB_CURRENT_VERSION = 1; 437 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 438 | INFOPLIST_FILE = HGCircularSlider/Info.plist; 439 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 440 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 441 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 442 | PRODUCT_BUNDLE_IDENTIFIER = com.intive.HGCircularSlider; 443 | PRODUCT_NAME = "$(TARGET_NAME)"; 444 | SKIP_INSTALL = YES; 445 | SWIFT_VERSION = 5.0; 446 | }; 447 | name = Debug; 448 | }; 449 | CCDBFDE51E43366F005D6F08 /* Release */ = { 450 | isa = XCBuildConfiguration; 451 | buildSettings = { 452 | CODE_SIGN_IDENTITY = ""; 453 | DEFINES_MODULE = YES; 454 | DEVELOPMENT_TEAM = R6JBLAQ685; 455 | DYLIB_COMPATIBILITY_VERSION = 1; 456 | DYLIB_CURRENT_VERSION = 1; 457 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 458 | INFOPLIST_FILE = HGCircularSlider/Info.plist; 459 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 460 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 461 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 462 | PRODUCT_BUNDLE_IDENTIFIER = com.intive.HGCircularSlider; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | SKIP_INSTALL = YES; 465 | SWIFT_VERSION = 5.0; 466 | }; 467 | name = Release; 468 | }; 469 | /* End XCBuildConfiguration section */ 470 | 471 | /* Begin XCConfigurationList section */ 472 | BB692D35235C9EB300CB74DA /* Build configuration list for PBXNativeTarget "HGCircularSliderTests" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | BB692D33235C9EB300CB74DA /* Debug */, 476 | BB692D34235C9EB300CB74DA /* Release */, 477 | ); 478 | defaultConfigurationIsVisible = 0; 479 | defaultConfigurationName = Release; 480 | }; 481 | CCDBFDD51E43366F005D6F08 /* Build configuration list for PBXProject "HGCircularSlider" */ = { 482 | isa = XCConfigurationList; 483 | buildConfigurations = ( 484 | CCDBFDE11E43366F005D6F08 /* Debug */, 485 | CCDBFDE21E43366F005D6F08 /* Release */, 486 | ); 487 | defaultConfigurationIsVisible = 0; 488 | defaultConfigurationName = Release; 489 | }; 490 | CCDBFDE31E43366F005D6F08 /* Build configuration list for PBXNativeTarget "HGCircularSlider" */ = { 491 | isa = XCConfigurationList; 492 | buildConfigurations = ( 493 | CCDBFDE41E43366F005D6F08 /* Debug */, 494 | CCDBFDE51E43366F005D6F08 /* Release */, 495 | ); 496 | defaultConfigurationIsVisible = 0; 497 | defaultConfigurationName = Release; 498 | }; 499 | /* End XCConfigurationList section */ 500 | }; 501 | rootObject = CCDBFDD21E43366F005D6F08 /* Project object */; 502 | } 503 | -------------------------------------------------------------------------------- /HGCircularSlider.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HGCircularSlider.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HGCircularSlider.xcodeproj/xcshareddata/xcschemes/HGCircularSlider.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 54 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /HGCircularSlider/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/HGCircularSlider/Assets/.gitkeep -------------------------------------------------------------------------------- /HGCircularSlider/Classes/CircularSlider+Draw.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularSlider+Draw.swift 3 | // Pods 4 | // 5 | // Created by Hamza Ghazouani on 21/10/2016. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | extension CircularSlider { 12 | 13 | /** 14 | Draw arc with stroke mode (Stroke) or Disk (Fill) or both (FillStroke) mode 15 | FillStroke used by default 16 | 17 | - parameter arc: the arc coordinates (origin, radius, start angle, end angle) 18 | - parameter lineWidth: the with of the circle line (optional) by default 2px 19 | - parameter mode: the mode of the path drawing (optional) by default FillStroke 20 | - parameter context: the context 21 | 22 | */ 23 | internal static func drawArc(withArc arc: Arc, lineWidth: CGFloat = 2, mode: CGPathDrawingMode = .fillStroke, inContext context: CGContext) { 24 | 25 | let circle = arc.circle 26 | let origin = circle.origin 27 | 28 | UIGraphicsPushContext(context) 29 | context.beginPath() 30 | 31 | context.setLineWidth(lineWidth) 32 | context.setLineCap(CGLineCap.round) 33 | context.addArc(center: origin, radius: circle.radius, startAngle: arc.startAngle, endAngle: arc.endAngle, clockwise: false) 34 | context.move(to: CGPoint(x: origin.x, y: origin.y)) 35 | context.drawPath(using: mode) 36 | 37 | UIGraphicsPopContext() 38 | } 39 | 40 | /** 41 | Draw disk using arc coordinates 42 | 43 | - parameter arc: the arc coordinates (origin, radius, start angle, end angle) 44 | - parameter context: the context 45 | */ 46 | internal static func drawDisk(withArc arc: Arc, inContext context: CGContext) { 47 | 48 | let circle = arc.circle 49 | let origin = circle.origin 50 | 51 | UIGraphicsPushContext(context) 52 | context.beginPath() 53 | 54 | context.setLineWidth(0) 55 | context.addArc(center: origin, radius: circle.radius, startAngle: arc.startAngle, endAngle: arc.endAngle, clockwise: false) 56 | context.addLine(to: CGPoint(x: origin.x, y: origin.y)) 57 | context.drawPath(using: .fill) 58 | 59 | UIGraphicsPopContext() 60 | } 61 | 62 | // MARK: drawing instance methods 63 | 64 | /// Draw the circular slider 65 | internal func drawCircularSlider(inContext context: CGContext) { 66 | diskColor.setFill() 67 | trackColor.setStroke() 68 | 69 | let circle = Circle(origin: bounds.center, radius: self.radius) 70 | let sliderArc = Arc(circle: circle, startAngle: CircularSliderHelper.circleMinValue, endAngle: CircularSliderHelper.circleMaxValue) 71 | CircularSlider.drawArc(withArc: sliderArc, lineWidth: backtrackLineWidth, inContext: context) 72 | } 73 | 74 | /// draw Filled arc between start an end angles 75 | internal func drawFilledArc(fromAngle startAngle: CGFloat, toAngle endAngle: CGFloat, inContext context: CGContext) { 76 | diskFillColor.setFill() 77 | trackFillColor.setStroke() 78 | 79 | let circle = Circle(origin: bounds.center, radius: self.radius) 80 | let arc = Arc(circle: circle, startAngle: startAngle, endAngle: endAngle) 81 | 82 | // fill Arc 83 | CircularSlider.drawDisk(withArc: arc, inContext: context) 84 | // stroke Arc 85 | CircularSlider.drawArc(withArc: arc, lineWidth: lineWidth, mode: .stroke, inContext: context) 86 | } 87 | 88 | internal func drawShadowArc(fromAngle startAngle: CGFloat, toAngle endAngle: CGFloat, inContext context: CGContext) { 89 | trackShadowColor.setStroke() 90 | 91 | let origin = CGPoint(x: bounds.center.x + trackShadowOffset.x, y: bounds.center.y + trackShadowOffset.y) 92 | let circle = Circle(origin: origin, radius: self.radius) 93 | let arc = Arc(circle: circle, startAngle: startAngle, endAngle: endAngle) 94 | 95 | // stroke Arc 96 | CircularSlider.drawArc(withArc: arc, lineWidth: lineWidth, mode: .stroke, inContext: context) 97 | } 98 | 99 | /** 100 | Draw the thumb and return the coordinates of its center 101 | 102 | - parameter angle: the angle of the point in the main circle 103 | - parameter image: the image of the thumb, if it's nil we use a disk (circle), the default value is nil 104 | - parameter context: the context 105 | 106 | - returns: return the origin point of the thumb 107 | */ 108 | @discardableResult 109 | internal func drawThumbAt(_ angle: CGFloat, with image: UIImage? = nil, inContext context: CGContext) -> CGPoint { 110 | let circle = Circle(origin: bounds.center, radius: self.radius + self.thumbOffset) 111 | let thumbOrigin = CircularSliderHelper.endPoint(fromCircle: circle, angle: angle) 112 | 113 | if let image = image { 114 | return drawThumb(withImage: image, thumbOrigin: thumbOrigin, inContext: context) 115 | } 116 | 117 | // Draw a disk as thumb 118 | let thumbCircle = Circle(origin: thumbOrigin, radius: thumbRadius) 119 | let thumbArc = Arc(circle: thumbCircle, startAngle: CircularSliderHelper.circleMinValue, endAngle: CircularSliderHelper.circleMaxValue) 120 | 121 | CircularSlider.drawArc(withArc: thumbArc, lineWidth: thumbLineWidth, inContext: context) 122 | return thumbOrigin 123 | } 124 | 125 | /** 126 | Draw thumb using image and return the coordinates of its center 127 | 128 | - parameter image: the image of the thumb 129 | - parameter angle: the angle of the point in the main circle 130 | - parameter context: the context 131 | 132 | - returns: return the origin point of the thumb 133 | */ 134 | @discardableResult 135 | private func drawThumb(withImage image: UIImage, thumbOrigin: CGPoint, inContext context: CGContext) -> CGPoint { 136 | UIGraphicsPushContext(context) 137 | context.beginPath() 138 | let imageSize = image.size 139 | let imageFrame = CGRect(x: thumbOrigin.x - (imageSize.width / 2), y: thumbOrigin.y - (imageSize.height / 2), width: imageSize.width, height: imageSize.height) 140 | image.draw(in: imageFrame) 141 | UIGraphicsPopContext() 142 | 143 | return thumbOrigin 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /HGCircularSlider/Classes/CircularSlider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularSlider.swift 3 | // Pods 4 | // 5 | // Created by Hamza Ghazouani on 19/10/2016. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | * A visual control used to select a single value from a continuous range of values. 13 | * Can also be used like a circular progress view 14 | * CircularSlider uses the target-action mechanism to report changes made during the course of editing: 15 | * ValueChanged, EditingDidBegin and EditingDidEnd 16 | */ 17 | @IBDesignable 18 | open class CircularSlider: UIControl { 19 | 20 | // MARK: Changing the Slider’s Appearance 21 | 22 | /** 23 | * The color shown for the selected portion of the slider disk. (between start and end values) 24 | * The default value is a transparent color. 25 | */ 26 | @IBInspectable 27 | open var diskFillColor: UIColor = .clear 28 | 29 | /** 30 | * The color shown for the unselected portion of the slider disk. (outside start and end values) 31 | * The default value of this property is the black color with alpha = 0.3. 32 | */ 33 | @IBInspectable 34 | open var diskColor: UIColor = .gray 35 | 36 | /** 37 | * The color shown for the selected track portion. (between start and end values) 38 | * The default value of this property is the tint color. 39 | */ 40 | @IBInspectable 41 | open var trackFillColor: UIColor = .clear 42 | 43 | /** 44 | * The color shown for the unselected track portion. (outside start and end values) 45 | * The default value of this property is the white color. 46 | */ 47 | @IBInspectable 48 | open var trackColor: UIColor = .white 49 | 50 | /** 51 | * The width of the circular line 52 | * 53 | * The default value of this property is 5.0. 54 | */ 55 | @IBInspectable 56 | open var lineWidth: CGFloat = 5.0 57 | 58 | /** 59 | * The width of the unselected track portion of the slider 60 | * 61 | * The default value of this property is 5.0. 62 | */ 63 | @IBInspectable 64 | open var backtrackLineWidth: CGFloat = 5.0 65 | 66 | /** 67 | * The shadow offset of the slider 68 | * 69 | * The default value of this property is .zero. 70 | */ 71 | @IBInspectable 72 | open var trackShadowOffset: CGPoint = .zero 73 | 74 | /** 75 | * The color of the shadow offset of the slider 76 | * 77 | * The default value of this property is .gray. 78 | */ 79 | @IBInspectable 80 | open var trackShadowColor: UIColor = .gray 81 | 82 | /** 83 | * The width of the thumb stroke line 84 | * 85 | * The default value of this property is 4.0. 86 | */ 87 | @IBInspectable 88 | open var thumbLineWidth: CGFloat = 4.0 89 | 90 | /** 91 | * The radius of the thumb 92 | * 93 | * The default value of this property is 13.0. 94 | */ 95 | @IBInspectable 96 | open var thumbRadius: CGFloat = 13.0 97 | 98 | /** 99 | * The color used to tint the thumb 100 | * Ignored if the endThumbImage != nil 101 | * 102 | * The default value of this property is the groupTableViewBackgroundColor. 103 | */ 104 | @IBInspectable 105 | open var endThumbTintColor: UIColor = .groupTableViewBackground 106 | 107 | /** 108 | * The stroke highlighted color of the end thumb 109 | * The default value of this property is blue 110 | */ 111 | @IBInspectable 112 | open var endThumbStrokeHighlightedColor: UIColor = .blue 113 | 114 | /** 115 | * The color used to tint the stroke of the end thumb 116 | * Ignored if the endThumbImage != nil 117 | * 118 | * The default value of this property is red. 119 | */ 120 | @IBInspectable 121 | open var endThumbStrokeColor: UIColor = .red 122 | 123 | /** 124 | * The image of the end thumb 125 | * Clears any custom color you may have provided for the end thumb. 126 | * 127 | * The default value of this property is nil 128 | */ 129 | open var endThumbImage: UIImage? 130 | 131 | // MARK: Accessing the Slider’s Value Limits 132 | 133 | /** 134 | * Fixed number of rounds - how many circles has user to do to reach max value (like apple bedtime clock - which have 2) 135 | * the default value if this property is 1 136 | */ 137 | @IBInspectable 138 | open var numberOfRounds: Int = 1 { 139 | didSet { 140 | assert(numberOfRounds > 0, "Number of rounds has to be positive value!") 141 | setNeedsDisplay() 142 | } 143 | } 144 | 145 | /** 146 | * The minimum value of the receiver. 147 | * 148 | * If you change the value of this property, and the end value of the receiver is below the new minimum, the end point value is adjusted to match the new minimum value automatically. 149 | * The default value of this property is 0.0. 150 | */ 151 | @IBInspectable 152 | open var minimumValue: CGFloat = 0.0 { 153 | didSet { 154 | if endPointValue < minimumValue { 155 | endPointValue = minimumValue 156 | } 157 | } 158 | } 159 | 160 | /** 161 | * The maximum value of the receiver. 162 | * 163 | * If you change the value of this property, and the end value of the receiver is above the new maximum, the end value is adjusted to match the new maximum value automatically. 164 | * The default value of this property is 1.0. 165 | */ 166 | @IBInspectable 167 | open var maximumValue: CGFloat = 1.0 { 168 | didSet { 169 | if endPointValue > maximumValue { 170 | endPointValue = maximumValue 171 | } 172 | } 173 | } 174 | 175 | /** 176 | * The offset of the thumb centre from the circle. 177 | * 178 | * You can use this to move the thumb inside or outside the circle of the slider 179 | * If the value is grather than 0 the thumb will be displayed outside the cirlce 180 | * And if the value is negative, the thumb will be displayed inside the circle 181 | */ 182 | @IBInspectable 183 | open var thumbOffset: CGFloat = 0.0 { 184 | didSet { 185 | setNeedsDisplay() 186 | } 187 | } 188 | 189 | /** 190 | * Stop the thumb going beyond the min/max. 191 | * 192 | */ 193 | @IBInspectable 194 | open var stopThumbAtMinMax: Bool = false 195 | 196 | 197 | /** 198 | * The value of the endThumb (changed when the user change the position of the end thumb) 199 | * 200 | * If you try to set a value that is above the maximum value, the property automatically resets to the maximum value. 201 | * And if you try to set a value that is below the minimum value, the property automatically resets to the minimum value. 202 | * 203 | * The default value of this property is 0.5 204 | */ 205 | open var endPointValue: CGFloat = 0.5 { 206 | didSet { 207 | if oldValue == endPointValue { 208 | return 209 | } 210 | if endPointValue > maximumValue { 211 | endPointValue = maximumValue 212 | } 213 | if endPointValue < minimumValue { 214 | endPointValue = minimumValue 215 | } 216 | 217 | setNeedsDisplay() 218 | } 219 | } 220 | 221 | /** 222 | * The radius of circle 223 | */ 224 | internal var radius: CGFloat { 225 | get { 226 | // the minimum between the height/2 and the width/2 227 | var radius = min(bounds.center.x, bounds.center.y) 228 | 229 | // if we use an image for the thumb, the radius of the image will be used 230 | let maxThumbRadius = max(thumbRadius, (self.endThumbImage?.size.height ?? 0) / 2) 231 | 232 | // all elements should be inside the view rect, for that we should subtract the highest value between the radius of thumb and the line width 233 | radius -= max(lineWidth, (maxThumbRadius + thumbLineWidth + thumbOffset)) 234 | return radius 235 | } 236 | } 237 | 238 | /// See superclass documentation 239 | override open var isHighlighted: Bool { 240 | didSet { 241 | setNeedsDisplay() 242 | } 243 | } 244 | 245 | // MARK: init methods 246 | 247 | /** 248 | See superclass documentation 249 | */ 250 | override public init(frame: CGRect) { 251 | super.init(frame: frame) 252 | 253 | setup() 254 | } 255 | 256 | /** 257 | See superclass documentation 258 | */ 259 | required public init?(coder aDecoder: NSCoder) { 260 | super.init(coder: aDecoder) 261 | 262 | setup() 263 | } 264 | 265 | internal func setup() { 266 | trackFillColor = tintColor 267 | } 268 | 269 | 270 | // MARK: Drawing methods 271 | 272 | /** 273 | See superclass documentation 274 | */ 275 | override open func draw(_ rect: CGRect) { 276 | guard let context = UIGraphicsGetCurrentContext() else { return } 277 | 278 | drawCircularSlider(inContext: context) 279 | 280 | let valuesInterval = Interval(min: minimumValue, max: maximumValue, rounds: numberOfRounds) 281 | // get end angle from end value 282 | let endAngle = CircularSliderHelper.scaleToAngle(value: endPointValue, inInterval: valuesInterval) + CircularSliderHelper.circleInitialAngle 283 | 284 | drawFilledArc(fromAngle: CircularSliderHelper.circleInitialAngle, toAngle: endAngle, inContext: context) 285 | 286 | // draw end thumb 287 | endThumbTintColor.setFill() 288 | (isHighlighted == true) ? endThumbStrokeHighlightedColor.setStroke() : endThumbStrokeColor.setStroke() 289 | 290 | drawThumbAt(endAngle, with: endThumbImage, inContext: context) 291 | } 292 | 293 | // MARK: User interaction methods 294 | 295 | /** 296 | See superclass documentation 297 | */ 298 | override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { 299 | sendActions(for: .editingDidBegin) 300 | 301 | return true 302 | } 303 | 304 | /** 305 | See superclass documentation 306 | */ 307 | override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { 308 | // the position of the pan gesture 309 | let touchPosition = touch.location(in: self) 310 | let startPoint = CGPoint(x: bounds.center.x, y: 0) 311 | let value = newValue(from: endPointValue, touch: touchPosition, start: startPoint) 312 | 313 | endPointValue = value 314 | sendActions(for: .valueChanged) 315 | 316 | return true 317 | } 318 | 319 | /** 320 | See superclass documentation 321 | */ 322 | open override func endTracking(_ touch: UITouch?, with event: UIEvent?) { 323 | sendActions(for: .editingDidEnd) 324 | } 325 | 326 | // MARK: Utilities methods 327 | internal func newValue(from oldValue: CGFloat, touch touchPosition: CGPoint, start startPosition: CGPoint) -> CGFloat { 328 | let angle = CircularSliderHelper.angle(betweenFirstPoint: startPosition, secondPoint: touchPosition, inCircleWithCenter: bounds.center) 329 | let interval = Interval(min: minimumValue, max: maximumValue, rounds: numberOfRounds) 330 | let deltaValue = CircularSliderHelper.delta(in: interval, for: angle, oldValue: oldValue) 331 | 332 | var newValue = oldValue + deltaValue - minimumValue 333 | let range = maximumValue - minimumValue 334 | 335 | if !stopThumbAtMinMax { 336 | if newValue > maximumValue { 337 | newValue -= range 338 | } 339 | else if newValue < minimumValue { 340 | newValue += range 341 | } 342 | } 343 | 344 | return newValue 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /HGCircularSlider/Classes/CircularSliderHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularSlider+Math.swift 3 | // Pods 4 | // 5 | // Created by Hamza Ghazouani on 21/10/2016. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: - Internal Structures 12 | internal struct Interval { 13 | var min: CGFloat = 0.0 14 | var max: CGFloat = 0.0 15 | var rounds: Int 16 | 17 | init(min: CGFloat, max: CGFloat, rounds: Int = 1) { 18 | assert(min <= max && rounds > 0, NSLocalizedString("Illegal interval", comment: "")) 19 | 20 | self.min = min 21 | self.max = max 22 | self.rounds = rounds 23 | } 24 | } 25 | 26 | internal struct Circle { 27 | var origin = CGPoint.zero 28 | var radius: CGFloat = 0 29 | 30 | init(origin: CGPoint, radius: CGFloat) { 31 | assert(radius >= 0, NSLocalizedString("Illegal radius value", comment: "")) 32 | 33 | self.origin = origin 34 | self.radius = radius 35 | } 36 | } 37 | 38 | internal struct Arc { 39 | 40 | var circle = Circle(origin: CGPoint.zero, radius: 0) 41 | var startAngle: CGFloat = 0.0 42 | var endAngle: CGFloat = 0.0 43 | 44 | init(circle: Circle, startAngle: CGFloat, endAngle: CGFloat) { 45 | 46 | self.circle = circle 47 | self.startAngle = startAngle 48 | self.endAngle = endAngle 49 | } 50 | } 51 | 52 | // MARK: - Internal Extensions 53 | internal extension CGVector { 54 | 55 | /** 56 | Calculate the vector between two points 57 | 58 | - parameter source: the source point 59 | - parameter end: the destination point 60 | 61 | - returns: returns the vector between source and the end point 62 | */ 63 | init(sourcePoint source: CGPoint, endPoint end: CGPoint) { 64 | let dx = end.x - source.x 65 | let dy = end.y - source.y 66 | self.init(dx: dx, dy: dy) 67 | } 68 | 69 | func dotProduct(_ v: CGVector) -> CGFloat { 70 | let dotProduct = (dx * v.dx) + (dy * v.dy) 71 | return dotProduct 72 | } 73 | 74 | func determinant(_ v: CGVector) -> CGFloat { 75 | let determinant = (v.dx * dy) - (dx * v.dy) 76 | return determinant 77 | } 78 | 79 | static func dotProductAndDeterminant(fromSourcePoint source: CGPoint, firstPoint first: CGPoint, secondPoint second: CGPoint) -> (dotProduct: Float, determinant: Float) { 80 | let u = CGVector(sourcePoint: source, endPoint: first) 81 | let v = CGVector(sourcePoint: source, endPoint: second) 82 | 83 | let dotProduct = u.dotProduct(v) 84 | let determinant = u.determinant(v) 85 | return (Float(dotProduct), Float(determinant)) 86 | } 87 | } 88 | 89 | internal extension CGRect { 90 | 91 | // get the center of rect (bounds or frame) 92 | var center: CGPoint { 93 | get { 94 | let center = CGPoint(x: midX, y: midY) 95 | return center 96 | } 97 | } 98 | } 99 | 100 | // MARK: - Internal Helper 101 | internal class CircularSliderHelper { 102 | 103 | @nonobjc static let circleMinValue: CGFloat = 0 104 | @nonobjc static let circleMaxValue: CGFloat = CGFloat(2 * Double.pi) 105 | @nonobjc static let circleInitialAngle: CGFloat = -CGFloat(Double.pi / 2) 106 | 107 | /** 108 | Convert angle from radians to degrees 109 | 110 | - parameter value: radians value 111 | 112 | - returns: degree value 113 | */ 114 | internal static func degrees(fromRadians value: CGFloat) -> CGFloat { 115 | return value * 180.0 / CGFloat(Double.pi) 116 | } 117 | 118 | /** 119 | Returns the angle AÔB of an circle 120 | 121 | - parameter firstPoint: the first point 122 | - parameter secondPoint: the second point 123 | - parameter center: the center of the circle 124 | 125 | - returns: Returns the angle AÔB of an circle 126 | */ 127 | internal static func angle(betweenFirstPoint firstPoint: CGPoint, secondPoint: CGPoint, inCircleWithCenter center: CGPoint) -> CGFloat { 128 | /* 129 | we get the angle by using two vectors 130 | http://www.vitutor.com/geometry/vec/angle_vectors.html 131 | https://www.mathsisfun.com/geometry/unit-circle.html 132 | https://en.wikipedia.org/wiki/Dot_product 133 | https://en.wikipedia.org/wiki/Determinant 134 | */ 135 | 136 | let uv = CGVector.dotProductAndDeterminant(fromSourcePoint: center, firstPoint: firstPoint, secondPoint: secondPoint) 137 | let angle = atan2(uv.determinant, uv.dotProduct) 138 | 139 | // change the angle interval 140 | let newAngle = (angle < 0) ? -angle : Float(Double.pi * 2) - angle 141 | 142 | return CGFloat(newAngle) 143 | } 144 | 145 | /** 146 | Given a specific angle, returns the coordinates of the end point in the circle 147 | 148 | - parameter circle: the circle 149 | - parameter angle: the angle value 150 | 151 | - returns: the coordinates of the end point 152 | */ 153 | internal static func endPoint(fromCircle circle: Circle, angle: CGFloat) -> CGPoint { 154 | /* 155 | to get coordinate from angle of circle 156 | https://www.mathsisfun.com/polar-cartesian-coordinates.html 157 | */ 158 | 159 | let x = circle.radius * cos(angle) + circle.origin.x // cos(α) = x / radius 160 | let y = circle.radius * sin(angle) + circle.origin.y // sin(α) = y / radius 161 | let point = CGPoint(x: x, y: y) 162 | 163 | return point 164 | } 165 | 166 | /** 167 | Scale the value from an interval to another 168 | 169 | For example if the value is 0.5 and the interval is [0, 1] 170 | the new value is equal to 4 in the new interval [0, 8] 171 | 172 | - parameter value: the value 173 | - parameter source: the old interval 174 | - parameter destination: the new interval 175 | 176 | - returns: the value in the new interval 177 | */ 178 | internal static func scaleValue(_ value: CGFloat, fromInterval source: Interval, toInterval destination: Interval) -> CGFloat { 179 | // If the value is equal to the min or the max no need to calculate 180 | switch value { 181 | case source.min: 182 | return destination.min 183 | case source.max: 184 | return destination.max 185 | default: 186 | let sourceRange = (source.max - source.min) / CGFloat(source.rounds) 187 | let destinationRange = (destination.max - destination.min) / CGFloat(destination.rounds) 188 | let scaledValue = source.min + (value - source.min).truncatingRemainder(dividingBy: sourceRange) 189 | let newValue = (((scaledValue - source.min) * destinationRange) / sourceRange) + destination.min 190 | 191 | return newValue 192 | } 193 | } 194 | 195 | /** 196 | Scale the value from the initial interval to circle interval 197 | The angle interval is [0, 2π] 198 | 199 | For example if the value is 0.5 and the interval is [0, 1] 200 | the angle value is equal to π 201 | 202 | @see value(inInterval: fromAngle:) 203 | 204 | - parameter aValue: the original value 205 | - parameter oldIntreval: the original interval 206 | 207 | - returns: the angle value 208 | */ 209 | internal static func scaleToAngle(value aValue: CGFloat, inInterval oldInterval: Interval) -> CGFloat { 210 | let angleInterval = Interval(min: circleMinValue , max: circleMaxValue) 211 | 212 | let angle = scaleValue(aValue, fromInterval: oldInterval, toInterval: angleInterval) 213 | return angle 214 | } 215 | 216 | /** 217 | Scale the value from the circle interval to the new interval 218 | The angle interval is [0, 2π] 219 | 220 | For example if the value is π and the interval is [0, 2π] 221 | the new value is equal to 1 in the interval [0, 2] 222 | 223 | - parameter newInterval: the new interval 224 | - parameter angle: the angle value 225 | 226 | - returns: the value in the new interval 227 | */ 228 | internal static func value(inInterval newInterval: Interval, fromAngle angle: CGFloat) -> CGFloat { 229 | let angleIntreval = Interval(min: circleMinValue , max: circleMaxValue) 230 | let value = scaleValue(angle, fromInterval: angleIntreval, toInterval: newInterval) 231 | 232 | return value 233 | } 234 | 235 | internal static func delta(in interval: Interval, for angle: CGFloat, oldValue: CGFloat) -> CGFloat { 236 | let angleIntreval = Interval(min: circleMinValue , max: circleMaxValue) 237 | 238 | let oldAngle = scaleToAngle(value: oldValue, inInterval: interval) 239 | let deltaAngle = self.angle(from: oldAngle, to: angle) 240 | 241 | return scaleValue(deltaAngle, fromInterval: angleIntreval, toInterval: interval) 242 | } 243 | 244 | /** 245 | * Length (angular) of a shortest way between two angles. 246 | * It will be in range [-π/2, π/2], where sign means dir (+ for clockwise, - for counter clockwise). 247 | */ 248 | private static func angle(from alpha: CGFloat, to beta: CGFloat) -> CGFloat { 249 | let halfValue = circleMaxValue/2 250 | // Rotate right 251 | let offset = alpha >= halfValue ? circleMaxValue - alpha : -alpha 252 | let offsetBeta = beta + offset 253 | 254 | if offsetBeta > halfValue { 255 | return offsetBeta - circleMaxValue 256 | } 257 | else { 258 | return offsetBeta 259 | } 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /HGCircularSlider/Classes/MidPointCircularSlider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MidPointCircularSlider.swift 3 | // Pods 4 | // 5 | // Created by Hamza Ghazouani on 04/11/2016. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | A visual control used to select a fixed range of values from a continuous range of values. 13 | MidPointCircularSlider use the target-action mechanism to report changes made during the course of editing: 14 | ValueChanged, EditingDidBegin and EditingDidEnd 15 | */ 16 | open class MidPointCircularSlider: RangeCircularSlider { 17 | 18 | // MARK: properties 19 | 20 | /** 21 | * The color used to tint thumb 22 | * Ignored if the midThumbImage != nil 23 | * 24 | * The default value of this property is the groupTableViewBackgroundColor. 25 | */ 26 | @IBInspectable 27 | open var midThumbTintColor: UIColor = UIColor.groupTableViewBackground 28 | 29 | /** 30 | * The stroke highlighted color of end thumb 31 | * The default value of this property is blue color 32 | */ 33 | @IBInspectable 34 | open var midThumbStrokeHighlightedColor: UIColor = UIColor.blue 35 | 36 | /** 37 | * The color used to tint the stroke of the mid thumb 38 | * Ignored if the midThumbImage != nil 39 | * 40 | * The default value of this property is the red color. 41 | */ 42 | @IBInspectable 43 | open var midThumbStrokeColor: UIColor = UIColor.red 44 | 45 | 46 | /** 47 | * The image of the mid thumb 48 | * Clears any custom color you may have provided for mid thumb. 49 | * 50 | * The default value of this property is nil 51 | */ 52 | open var midThumbImage: UIImage? 53 | 54 | 55 | /** 56 | * The fixed range distance 57 | * 58 | * The value of this property should be >= 0 59 | * The default value of this property is 0.2 60 | */ 61 | override open var distance: CGFloat { 62 | didSet { 63 | assert(distance >= 0, "The MidPointCircularSlider works only with fixed distance between start and end points, so distance property should be > 0") 64 | endPointValue = startPointValue + distance 65 | } 66 | } 67 | 68 | /** 69 | * The value of the mid point (between the start and end points) 70 | */ 71 | open var midPointValue: CGFloat { 72 | get { 73 | return (endPointValue + startPointValue) / 2 74 | } 75 | set { 76 | let value = newValue 77 | 78 | let interval = (endPointValue - startPointValue) / 2 79 | startPointValue = value - interval 80 | endPointValue = value + interval 81 | } 82 | } 83 | 84 | // MARK: init methods 85 | 86 | /** 87 | See superclass documentation 88 | */ 89 | required public init?(coder aDecoder: NSCoder) { 90 | super.init(coder: aDecoder) 91 | distance = 0.2 92 | } 93 | 94 | override init(frame: CGRect) { 95 | super.init(frame: frame) 96 | distance = 0.2 97 | } 98 | 99 | /** 100 | See superclass documentation 101 | */ 102 | override open func draw(_ rect: CGRect) { 103 | guard let context = UIGraphicsGetCurrentContext() else { return } 104 | 105 | drawCircularSlider(inContext: context) 106 | 107 | let valuesInterval = Interval(min: minimumValue, max: maximumValue, rounds: numberOfRounds) 108 | 109 | // get start angle from start value 110 | let startAngle = CircularSliderHelper.scaleToAngle(value: startPointValue, inInterval: valuesInterval) + CircularSliderHelper.circleInitialAngle 111 | // get end angle from end value 112 | let endAngle = CircularSliderHelper.scaleToAngle(value: endPointValue, inInterval: valuesInterval) + CircularSliderHelper.circleInitialAngle 113 | 114 | let midAngle = CircularSliderHelper.scaleToAngle(value: midPointValue, inInterval: valuesInterval) + CircularSliderHelper.circleInitialAngle 115 | 116 | drawFilledArc(fromAngle: startAngle, toAngle: endAngle, inContext: context) 117 | 118 | // draw mid thumb 119 | midThumbTintColor.setFill() 120 | (isHighlighted == true) ? midThumbStrokeHighlightedColor.setStroke() : midThumbStrokeColor.setStroke() 121 | 122 | drawThumbAt(midAngle, with: midThumbImage, inContext: context) 123 | } 124 | 125 | // MARK: User interaction methods 126 | 127 | /** 128 | See superclass documentation 129 | */ 130 | override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { 131 | sendActions(for: .editingDidBegin) 132 | 133 | return true 134 | } 135 | 136 | /** 137 | See superclass documentation 138 | */ 139 | override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { 140 | let touchPosition = touch.location(in: self) 141 | 142 | let center = CGPoint(x: bounds.midX, y: bounds.midY) 143 | let startPoint = CGPoint(x: center.x, y: 0) 144 | let value = newValue(from: midPointValue, touch: touchPosition, start: startPoint) 145 | 146 | midPointValue = value 147 | sendActions(for: .valueChanged) 148 | 149 | return true 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /HGCircularSlider/Classes/RangeCircularSlider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RangeCircularSlider.swift 3 | // Pods 4 | // 5 | // Created by Hamza Ghazouani on 25/10/2016. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | A visual control used to select a range of values (between start point and the end point) from a continuous range of values. 13 | RangeCircularSlider use the target-action mechanism to report changes made during the course of editing: 14 | ValueChanged, EditingDidBegin and EditingDidEnd 15 | */ 16 | open class RangeCircularSlider: CircularSlider { 17 | 18 | public enum SelectedThumb { 19 | case startThumb 20 | case endThumb 21 | case none 22 | 23 | var isStart: Bool { 24 | return self == SelectedThumb.startThumb 25 | } 26 | var isEnd: Bool { 27 | return self == SelectedThumb.endThumb 28 | } 29 | } 30 | 31 | // MARK: Changing the Slider’s Appearance 32 | 33 | /** 34 | * The color used to tint start thumb 35 | * Ignored if the startThumbImage != nil 36 | * 37 | * The default value of this property is the groupTableViewBackgroundColor. 38 | */ 39 | @IBInspectable 40 | open var startThumbTintColor: UIColor = UIColor.groupTableViewBackground 41 | 42 | /** 43 | * The color used to tint the stroke of the start thumb 44 | * Ignored if the startThumbImage != nil 45 | * 46 | * The default value of this property is the green color. 47 | */ 48 | @IBInspectable 49 | open var startThumbStrokeColor: UIColor = UIColor.green 50 | 51 | /** 52 | * The stroke highlighted color of start thumb 53 | * The default value of this property is blue color 54 | */ 55 | @IBInspectable 56 | open var startThumbStrokeHighlightedColor: UIColor = UIColor.purple 57 | 58 | 59 | /** 60 | * The image of the end thumb 61 | * Clears any custom color you may have provided for end thumb. 62 | * 63 | * The default value of this property is nil 64 | */ 65 | open var startThumbImage: UIImage? 66 | 67 | 68 | // MARK: Accessing the Slider’s Value Limits 69 | 70 | /** 71 | * The minimum value of the receiver. 72 | * 73 | * If you change the value of this property, and the start value of the receiver is below the new minimum, the start value is adjusted to match the new minimum value automatically. 74 | * The end value is also adjusted to match (startPointValue + distance) automatically if the distance is different to -1 (SeeAlso: startPointValue, distance) 75 | * The default value of this property is 0.0. 76 | */ 77 | override open var minimumValue: CGFloat { 78 | didSet { 79 | if startPointValue < minimumValue { 80 | startPointValue = minimumValue 81 | } 82 | } 83 | } 84 | 85 | /** 86 | * The maximum value of the receiver. 87 | * 88 | * If you change the value of this property, and the end value of the receiver is above the new maximum, the end value is adjusted to match the new maximum value automatically. 89 | * The start value is also adjusted to match (endPointValue - distance) automatically if the distance is different to -1 (see endPointValue, distance) 90 | * The default value of this property is 1.0. 91 | */ 92 | @IBInspectable 93 | override open var maximumValue: CGFloat { 94 | didSet { 95 | if endPointValue > maximumValue { 96 | endPointValue = maximumValue 97 | } 98 | } 99 | } 100 | 101 | /** 102 | * The fixed distance between the start value and the end value 103 | * 104 | * If you change the value of this property, the end value is adjusted to match (startPointValue + distance) 105 | * If the end value is above the maximum value, the end value is adjusted to match the maximum value and the start value is adjusted to match (endPointValue - distance) 106 | * To disable distance use -1 (by default) 107 | * 108 | * The default value of this property is -1 109 | */ 110 | @IBInspectable 111 | open var distance: CGFloat = -1 { 112 | didSet { 113 | assert(distance <= maximumValue - minimumValue, "The distance value is greater than distance between max and min value") 114 | endPointValue = startPointValue + distance 115 | } 116 | } 117 | 118 | 119 | /** 120 | * The value in the start thumb. 121 | * 122 | * If you try to set a value that is below the minimum value, the minimum value is set instead. 123 | * If you try to set a value that is above the (endPointValue - distance), the (endPointValue - distance) is set instead. 124 | * 125 | * The default value of this property is 0.0. 126 | */ 127 | open var startPointValue: CGFloat = 0.0 { 128 | didSet { 129 | guard oldValue != startPointValue else { return } 130 | 131 | if startPointValue < minimumValue { 132 | startPointValue = minimumValue 133 | } 134 | 135 | if distance > 0 { 136 | endPointValue = startPointValue + distance 137 | } 138 | 139 | setNeedsDisplay() 140 | } 141 | } 142 | 143 | /** 144 | * The value in the end thumb. 145 | * 146 | * If you try to set a value that is above the maximum value, the maximum value is set instead. 147 | * If you try to set a value that is below the (startPointValue + distance), the (startPointValue + distance) is set instead. 148 | * 149 | * The default value of this property is 0.5 150 | */ 151 | override open var endPointValue: CGFloat { 152 | didSet { 153 | if oldValue == endPointValue && distance <= 0 { 154 | return 155 | } 156 | 157 | if endPointValue > maximumValue { 158 | endPointValue = maximumValue 159 | } 160 | 161 | if distance > 0 { 162 | startPointValue = endPointValue - distance 163 | } 164 | 165 | setNeedsDisplay() 166 | } 167 | } 168 | 169 | // MARK: private properties / methods 170 | 171 | /** 172 | * The center of the start thumb 173 | * Used to know in which thumb is the user gesture 174 | */ 175 | fileprivate var startThumbCenter: CGPoint = CGPoint.zero 176 | 177 | /** 178 | * The center of the end thumb 179 | * Used to know in which thumb is the user gesture 180 | */ 181 | fileprivate var endThumbCenter: CGPoint = CGPoint.zero 182 | 183 | /** 184 | * The last touched thumb 185 | * By default the value is none 186 | */ 187 | fileprivate var selectedThumb: SelectedThumb = .none 188 | 189 | /** 190 | Checks if the touched point affect the thumb 191 | 192 | The point affect the thumb if : 193 | The thumb rect contains this point 194 | Or the angle between the touched point and the center of the thumb less than 15° 195 | 196 | - parameter thumbCenter: the center of the thumb 197 | - parameter touchPoint: the touched point 198 | 199 | - returns: true if the touched point affect the thumb, false if not. 200 | */ 201 | internal func isThumb(withCenter thumbCenter: CGPoint, containsPoint touchPoint: CGPoint) -> Bool { 202 | // the coordinates of thumb from its center 203 | let rect = CGRect(x: thumbCenter.x - thumbRadius, y: thumbCenter.y - thumbRadius, width: thumbRadius * 2, height: thumbRadius * 2) 204 | if rect.contains(touchPoint) { 205 | return true 206 | } 207 | 208 | let angle = CircularSliderHelper.angle(betweenFirstPoint: thumbCenter, secondPoint: touchPoint, inCircleWithCenter: bounds.center) 209 | let degree = CircularSliderHelper.degrees(fromRadians: angle) 210 | 211 | // tolerance 15° 212 | let isInside = degree < 15 || degree > 345 213 | return isInside 214 | } 215 | 216 | // MARK: Drawing 217 | 218 | /** 219 | See superclass documentation 220 | */ 221 | override open func draw(_ rect: CGRect) { 222 | guard let context = UIGraphicsGetCurrentContext() else { return } 223 | 224 | drawCircularSlider(inContext: context) 225 | 226 | let interval = Interval(min: minimumValue, max: maximumValue, rounds: numberOfRounds) 227 | // get start angle from start value 228 | let startAngle = CircularSliderHelper.scaleToAngle(value: startPointValue, inInterval: interval) + CircularSliderHelper.circleInitialAngle 229 | // get end angle from end value 230 | let endAngle = CircularSliderHelper.scaleToAngle(value: endPointValue, inInterval: interval) + CircularSliderHelper.circleInitialAngle 231 | 232 | drawShadowArc(fromAngle: startAngle, toAngle: endAngle, inContext: context) 233 | drawFilledArc(fromAngle: startAngle, toAngle: endAngle, inContext: context) 234 | 235 | // end thumb 236 | endThumbTintColor.setFill() 237 | (isHighlighted == true && selectedThumb == .endThumb) ? endThumbStrokeHighlightedColor.setStroke() : endThumbStrokeColor.setStroke() 238 | endThumbCenter = drawThumbAt(endAngle, with: endThumbImage, inContext: context) 239 | 240 | // start thumb 241 | startThumbTintColor.setFill() 242 | (isHighlighted == true && selectedThumb == .startThumb) ? startThumbStrokeHighlightedColor.setStroke() : startThumbStrokeColor.setStroke() 243 | 244 | startThumbCenter = drawThumbAt(startAngle, with: startThumbImage, inContext: context) 245 | } 246 | 247 | // MARK: User interaction methods 248 | 249 | /** 250 | See superclass documentation 251 | */ 252 | override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { 253 | sendActions(for: .editingDidBegin) 254 | // the position of the pan gesture 255 | let touchPosition = touch.location(in: self) 256 | selectedThumb = thumb(for: touchPosition) 257 | 258 | return selectedThumb != .none 259 | } 260 | 261 | /** 262 | See superclass documentation 263 | */ 264 | override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { 265 | guard selectedThumb != .none else { 266 | return false 267 | } 268 | 269 | // the position of the pan gesture 270 | let touchPosition = touch.location(in: self) 271 | let startPoint = CGPoint(x: bounds.center.x, y: 0) 272 | 273 | let oldValue: CGFloat = selectedThumb.isStart ? startPointValue : endPointValue 274 | let value = newValue(from: oldValue, touch: touchPosition, start: startPoint) 275 | 276 | if selectedThumb.isStart { 277 | startPointValue = value 278 | } else { 279 | endPointValue = value 280 | } 281 | sendActions(for: .valueChanged) 282 | 283 | return true 284 | } 285 | 286 | override open func endTracking(_ touch: UITouch?, with event: UIEvent?) { 287 | super.endTracking(touch, with: event) 288 | } 289 | 290 | 291 | // MARK: - Helpers 292 | open func thumb(for touchPosition: CGPoint) -> SelectedThumb { 293 | if isThumb(withCenter: startThumbCenter, containsPoint: touchPosition) { 294 | return .startThumb 295 | } 296 | else if isThumb(withCenter: endThumbCenter, containsPoint: touchPosition) { 297 | return .endThumb 298 | } else { 299 | return .none 300 | } 301 | } 302 | 303 | } 304 | -------------------------------------------------------------------------------- /HGCircularSlider/HGCircularSlider.h: -------------------------------------------------------------------------------- 1 | // 2 | // HGCircularSlider.h 3 | // HGCircularSlider 4 | // 5 | // Created by Andrzej Michnia on 02.02.2017. 6 | // Copyright © 2017 intive. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for HGCircularSlider. 12 | FOUNDATION_EXPORT double HGCircularSliderVersionNumber; 13 | 14 | //! Project version string for HGCircularSlider. 15 | FOUNDATION_EXPORT const unsigned char HGCircularSliderVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /HGCircularSlider/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 | FMWK 17 | CFBundleShortVersionString 18 | 2.0.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /HGCircularSliderTests/HGCircularSliderTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HGCircularSliderTests.swift 3 | // HGCircularSliderTests 4 | // 5 | // Created by Hamza on 20/10/2019. 6 | // Copyright © 2019 intive. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class HGCircularSliderTests: XCTestCase { 12 | 13 | override func setUp() { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDown() { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() { 22 | // This is an example of a functional test case. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | } 25 | 26 | func testPerformanceExample() { 27 | // This is an example of a performance test case. 28 | measure { 29 | // Put the code you want to measure the time of here. 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /HGCircularSliderTests/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Hamza Ghazouani 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "HGCircularSlider", 7 | platforms: [.iOS(.v8)], 8 | products: [ 9 | .library( 10 | name: "HGCircularSlider", 11 | targets: ["HGCircularSlider"] 12 | ) 13 | ], 14 | targets: [ 15 | .target(name: "HGCircularSlider", path: "HGCircularSlider/Classes") 16 | ] 17 | ) 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HGCircularSlider 2 | 3 | [![Backers on Open Collective](https://opencollective.com/HGCircularSlider/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/HGCircularSlider/sponsors/badge.svg)](#sponsors) [![Twitter: @GhazouaniHamza](https://img.shields.io/badge/contact-@GhazouaniHamza-blue.svg?style=flat)](https://twitter.com/GhazouaniHamza) 4 | [![CI Status](http://img.shields.io/travis/HamzaGhazouani/HGCircularSlider.svg?style=flat)](https://travis-ci.org/HamzaGhazouani/HGCircularSlider) 5 | [![Version](https://img.shields.io/cocoapods/v/HGCircularSlider.svg?style=flat)](http://cocoapods.org/pods/HGCircularSlider) 6 | [![License](https://img.shields.io/cocoapods/l/HGCircularSlider.svg?style=flat)](http://cocoapods.org/pods/HGCircularSlider) 7 | [![Language](https://img.shields.io/badge/language-Swift-orange.svg?style=flat)]() 8 | [![Platform](https://img.shields.io/cocoapods/p/HGCircularSlider.svg?style=flat)](http://cocoapods.org/pods/HGCircularSlider) 9 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 10 |
11 | 12 | [![codebeat badge](https://codebeat.co/badges/c4db03f5-903a-4b0e-84bb-98362fc5bd7a)](https://codebeat.co/projects/github-com-hamzaghazouani-hgcircularslider) 13 | [![Documentation](https://img.shields.io/cocoapods/metrics/doc-percent/HGCircularSlider.svg)](http://cocoadocs.org/docsets/HGCircularSlider/) 14 | [![Readme Score](http://readme-score-api.herokuapp.com/score.svg?url=https://github.com/hamzaghazouani/hgcircularslider/)](http://clayallsopp.github.io/readme-score?url=https://github.com/hamzaghazouani/hgcircularslider/tree/develop) 15 | 16 | ## Example 17 | 18 | ![](/Screenshots/Bedtime.gif) ![](/Screenshots/Player.gif) ![](/Screenshots/OClock.gif) ![](/Screenshots/Other.gif) ![](/Screenshots/Circular.gif) 19 | 20 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 21 | 22 | ## You also may like 23 | 24 | * **[HGPlaceholders](https://github.com/HamzaGhazouani/HGPlaceholders)** - Nice library to show placeholders for any UITableView in your project 25 | * **[HGRippleRadarView](https://github.com/HamzaGhazouani/HGRippleRadarView)** - A beautiful radar view to show nearby users with ripple animation, fully customizable 26 | 27 | ## Requirements 28 | 29 | - iOS 9.0+ 30 | - Xcode 11.4 31 | 32 | ## Installation 33 | 34 | HGCircularSlider is also available through [Swift Package Manager](https://swift.org/package-manager/) 35 | 36 | Follow this [doc](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app?language=swift). 37 | 38 | HGCircularSlider is also available through [CocoaPods](http://cocoapods.org). To install 39 | it, simply add the following line to your Podfile: 40 | 41 | ``` ruby 42 | pod 'HGCircularSlider', '~> 2.2.1' 43 | ``` 44 | 45 | HGCircularSlider is also available through [Carthage](https://github.com/Carthage/Carthage). To install 46 | it, simply add the following line to your Cartfile: 47 | 48 | 49 | ``` ruby 50 | github "HamzaGhazouani/HGCircularSlider" 51 | ``` 52 | 53 | ## Usage 54 | 55 | 1. Change the class of a view from UIView to CircularSlider, RangeCircularSlider or MidPointCircularSlider 56 | 2. Programmatically: 57 | 58 | ```swift 59 | let circularSlider = CircularSlider(frame: myFrame) 60 | circularSlider.minimumValue = 0.0 61 | circularSlider.maximumValue = 1.0 62 | circularSlider.endPointValue = 0.2 63 | ``` 64 | OR 65 | ```swift 66 | let circularSlider = RangeCircularSlider(frame: myFrame) 67 | circularSlider.startThumbImage = UIImage(named: "Bedtime") 68 | circularSlider.endThumbImage = UIImage(named: "Wake") 69 | 70 | let dayInSeconds = 24 * 60 * 60 71 | circularSlider.maximumValue = CGFloat(dayInSeconds) 72 | 73 | circularSlider.startPointValue = 1 * 60 * 60 74 | circularSlider.endPointValue = 8 * 60 * 60 75 | circularSlider.numberOfRounds = 2 // Two rotations for full 24h range 76 | ``` 77 | OR 78 | ```swift 79 | let circularSlider = MidPointCircularSlider(frame: myFrame) 80 | circularSlider.minimumValue = 0.0 81 | circularSlider.maximumValue = 10.0 82 | circularSlider.distance = 1.0 83 | circularSlider.midPointValue = 5.0 84 | ``` 85 | ##### If you would like to use it like a progress view 86 | ``` 87 | let progressView = CircularSlider(frame: myFrame) 88 | progressView.minimumValue = 0.0 89 | progressView.maximumValue = 1.0 90 | progressView.endPointValue = 0.2 // the progress 91 | progressView.userInteractionEnabled = false 92 | // to remove padding, for more details see issue #25 93 | progressView.thumbLineWidth = 0.0 94 | progressView.thumbRadius = 0.0 95 | ``` 96 | 97 | ## Documentation 98 | Full documentation is available on [CocoaDocs](http://cocoadocs.org/docsets/HGCircularSlider/).
99 | You can also install documentation locally using [jazzy](https://github.com/realm/jazzy). 100 | 101 | ## References 102 | The UI examples of the demo project inspired from [Dribbble](https://dribbble.com). 103 | 104 | [Player](https://dribbble.com/shots/3062636-Countdown-Timer-Daily-UI-014)
105 | [BasicExample](https://dribbble.com/shots/2153963-Dompet-Wallet-App)
106 | [OClock](https://dribbble.com/shots/2671286-Clock-Alarm-app)
107 | 108 | The project is Inspired by [UICircularSlider](https://github.com/Zedenem/UICircularSlider) 109 | 110 | ## Author 111 | 112 | Hamza Ghazouani, hamza.ghazouani@gmail.com 113 | 114 | ## License 115 | 116 | HGCircularSlider is available under the MIT license. See the LICENSE file for more info. 117 | -------------------------------------------------------------------------------- /Screenshots/Bedtime.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Screenshots/Bedtime.gif -------------------------------------------------------------------------------- /Screenshots/Circular.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Screenshots/Circular.gif -------------------------------------------------------------------------------- /Screenshots/OClock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Screenshots/OClock.gif -------------------------------------------------------------------------------- /Screenshots/Other.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Screenshots/Other.gif -------------------------------------------------------------------------------- /Screenshots/Player.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HamzaGhazouani/HGCircularSlider/2906c33e3101468a892f274c689ea0679f792037/Screenshots/Player.gif --------------------------------------------------------------------------------