├── .gitignore
├── Screenshot.png
├── Example
├── Assets.xcassets
│ ├── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── AppDelegate.swift
├── SceneDelegate.swift
├── Info.plist
├── ViewController.swift
└── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Example.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── Package.swift
├── WARangeSlider.podspec
├── LICENSE
├── README.md
└── Sources
└── WARangeSlider
└── RangeSlider.swift
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | Carthage/*
3 |
--------------------------------------------------------------------------------
/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/warchimede/RangeSlider/HEAD/Screenshot.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.7
2 |
3 | import PackageDescription
4 |
5 | let name = "WARangeSlider"
6 | let platforms: [SupportedPlatform] = [.iOS(.v12)]
7 | let products: [Product] = [.library(name: name, targets: [name])]
8 | let targets: [Target] = [.target(name: name)]
9 | let package = Package(name: name,
10 | platforms: platforms,
11 | products: products,
12 | targets: targets,
13 | swiftLanguageVersions: [.v5])
14 |
--------------------------------------------------------------------------------
/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | @main
4 | class AppDelegate: UIResponder, UIApplicationDelegate {
5 |
6 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { true }
7 |
8 | // MARK: UISceneSession Lifecycle
9 |
10 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
11 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/WARangeSlider.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "WARangeSlider"
3 | s.version = "1.2.0"
4 | s.summary = "A simple range slider made in Swift"
5 | s.description = "This pod provides a simple range slider."
6 | s.homepage = "https://github.com/warchimede/RangeSlider"
7 | s.license = "MIT"
8 | s.author = { "William Archimede" => "william.archimede@gmail.com" }
9 | s.source = {
10 | :git => "https://github.com/warchimede/RangeSlider.git",
11 | :tag => s.version.to_s
12 | }
13 | s.swift_version = '5.7'
14 | s.platform = :ios, '12.0'
15 | s.source_files = "Sources/WARangeSlider/RangeSlider.swift"
16 | end
17 |
--------------------------------------------------------------------------------
/Example/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
4 |
5 | var window: UIWindow?
6 |
7 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
8 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
9 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
10 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
11 | guard let _ = (scene as? UIWindowScene) else { return }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 William Archimede
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Example/ViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class ViewController: UIViewController {
4 | let rangeSlider1 = RangeSlider(frame: CGRect.zero)
5 | let rangeSlider2 = RangeSlider(frame: CGRect.zero)
6 |
7 | override func viewDidLoad() {
8 | super.viewDidLoad()
9 | // Do any additional setup after loading the view, typically from a nib.
10 | rangeSlider2.trackHighlightTintColor = UIColor.red
11 | rangeSlider2.curvaceousness = 0.0
12 |
13 | view.addSubview(rangeSlider1)
14 | view.addSubview(rangeSlider2)
15 |
16 | rangeSlider1.addTarget(self, action: #selector(ViewController.rangeSliderValueChanged(_:)), for: .valueChanged)
17 | }
18 |
19 | override func viewDidLayoutSubviews() {
20 | let margin: CGFloat = 20.0
21 | let width = view.bounds.width - 2.0 * margin
22 | rangeSlider1.frame = CGRect(x: margin, y: margin + 100, width: width, height: 31.0)
23 | rangeSlider2.frame = CGRect(x: margin + 20, y: 5 * margin + 100,
24 | width: width - 40, height: 40)
25 | }
26 |
27 | @objc func rangeSliderValueChanged(_ rangeSlider: RangeSlider) {
28 | print("Range slider value changed: (\(rangeSlider.lowerValue) , \(rangeSlider.upperValue))")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RangeSlider
2 |
3 | [](http://cocoapods.org/pods/WARangeSlider)
4 | [](http://cocoapods.org/pods/WARangeSlider)
5 | [](http://cocoapods.org/pods/WARangeSlider)
6 |
7 | ## Summary
8 |
9 | A simple range slider made in Swift.
10 |
11 | ## Screenshot
12 |
13 | 
14 |
15 | ## Use
16 |
17 | This control is **IBDesignable** and uses the **target-action** pattern for change notifications.
18 |
19 | In order to be notified when either thumb value changes, register for **.valueChanged**:
20 |
21 | ```swift
22 | let rangeSlider = RangeSlider(frame: frame)
23 | view.addSubView(rangeSlider)
24 | rangeSlider.addTarget(self, action: #selector(viewController.rangeSliderValueChanged(_:)), for: .valueChanged)
25 | ```
26 |
27 | ## Configuration
28 |
29 | The range slider can be customized and information can be accessed through these properties :
30 |
31 | - `minimumValue` : The minimum possible value of the range
32 | - `maximumValue` : The maximum possible value of the range
33 | - `lowerValue` : The value corresponding to the left thumb current position
34 | - `upperValue` : The value corresponding to the right thumb current position
35 | - `trackTintColor` : The track color
36 | - `trackHighlightTintColor` : The color of the section of the track located between the two thumbs
37 | - `thumbTintColor`: The thumb color
38 | - `thumbBorderColor`: The thumb border color
39 | - `thumbBorderWidth`: The width of the thumb border
40 | - `curvaceousness` : From 0.0 for square thumbs to 1.0 for circle thumbs
41 |
42 | ## Installation
43 |
44 | RangeSlider is available through Swift Package Manager and [CocoaPods](http://cocoapods.org).
45 |
46 | ### Cocoapods
47 |
48 | To install it, simply add the following line to your Podfile :
49 |
50 | ```ruby
51 | pod "WARangeSlider"
52 | ```
53 |
54 | ## Author
55 |
56 | [William Archimede](https://github.com/warchimede)
57 |
58 | ## License
59 |
60 | RangeSlider is available under the MIT License
61 |
--------------------------------------------------------------------------------
/Example/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/Sources/WARangeSlider/RangeSlider.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import QuartzCore
3 |
4 | class RangeSliderTrackLayer: CALayer {
5 | weak var rangeSlider: RangeSlider?
6 |
7 | override func draw(in ctx: CGContext) {
8 | guard let slider = rangeSlider else {
9 | return
10 | }
11 |
12 | // Clip
13 | let cornerRadius = bounds.height * slider.curvaceousness / 2.0
14 | let path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
15 | ctx.addPath(path.cgPath)
16 |
17 | // Fill the track
18 | ctx.setFillColor(slider.trackTintColor.cgColor)
19 | ctx.addPath(path.cgPath)
20 | ctx.fillPath()
21 |
22 | // Fill the highlighted range
23 | ctx.setFillColor(slider.trackHighlightTintColor.cgColor)
24 | let lowerValuePosition = CGFloat(slider.positionForValue(slider.lowerValue))
25 | let upperValuePosition = CGFloat(slider.positionForValue(slider.upperValue))
26 | let rect = CGRect(x: lowerValuePosition, y: 0.0, width: upperValuePosition - lowerValuePosition, height: bounds.height)
27 | ctx.fill(rect)
28 | }
29 | }
30 |
31 | class RangeSliderThumbLayer: CALayer {
32 |
33 | var highlighted: Bool = false {
34 | didSet {
35 | setNeedsDisplay()
36 | }
37 | }
38 | weak var rangeSlider: RangeSlider?
39 |
40 | var strokeColor: UIColor = UIColor.gray {
41 | didSet {
42 | setNeedsDisplay()
43 | }
44 | }
45 | var lineWidth: CGFloat = 0.5 {
46 | didSet {
47 | setNeedsDisplay()
48 | }
49 | }
50 |
51 | override func draw(in ctx: CGContext) {
52 | guard let slider = rangeSlider else {
53 | return
54 | }
55 |
56 | let thumbFrame = bounds.insetBy(dx: 2.0, dy: 2.0)
57 | let cornerRadius = thumbFrame.height * slider.curvaceousness / 2.0
58 | let thumbPath = UIBezierPath(roundedRect: thumbFrame, cornerRadius: cornerRadius)
59 |
60 | // Fill
61 | ctx.setFillColor(slider.thumbTintColor.cgColor)
62 | ctx.addPath(thumbPath.cgPath)
63 | ctx.fillPath()
64 |
65 | // Outline
66 | ctx.setStrokeColor(strokeColor.cgColor)
67 | ctx.setLineWidth(lineWidth)
68 | ctx.addPath(thumbPath.cgPath)
69 | ctx.strokePath()
70 |
71 | if highlighted {
72 | ctx.setFillColor(UIColor(white: 0.0, alpha: 0.1).cgColor)
73 | ctx.addPath(thumbPath.cgPath)
74 | ctx.fillPath()
75 | }
76 | }
77 | }
78 |
79 | @IBDesignable
80 | public class RangeSlider: UIControl {
81 | @IBInspectable public var minimumValue: Double = 0.0 {
82 | willSet(newValue) {
83 | assert(newValue < maximumValue, "RangeSlider: minimumValue should be lower than maximumValue")
84 | }
85 | didSet {
86 | updateLayerFrames()
87 | }
88 | }
89 |
90 | @IBInspectable public var maximumValue: Double = 1.0 {
91 | willSet(newValue) {
92 | assert(newValue > minimumValue, "RangeSlider: maximumValue should be greater than minimumValue")
93 | }
94 | didSet {
95 | updateLayerFrames()
96 | }
97 | }
98 |
99 | @IBInspectable public var lowerValue: Double = 0.2 {
100 | didSet {
101 | if lowerValue < minimumValue {
102 | lowerValue = minimumValue
103 | }
104 | updateLayerFrames()
105 | }
106 | }
107 |
108 | @IBInspectable public var upperValue: Double = 0.8 {
109 | didSet {
110 | if upperValue > maximumValue {
111 | upperValue = maximumValue
112 | }
113 | updateLayerFrames()
114 | }
115 | }
116 |
117 | var gapBetweenThumbs: Double {
118 | return 0.5 * Double(thumbWidth) * (maximumValue - minimumValue) / Double(bounds.width)
119 | }
120 |
121 | @IBInspectable public var trackTintColor: UIColor = UIColor(white: 0.9, alpha: 1.0) {
122 | didSet {
123 | trackLayer.setNeedsDisplay()
124 | }
125 | }
126 |
127 | @IBInspectable public var trackHighlightTintColor: UIColor = UIColor(red: 0.0, green: 0.45, blue: 0.94, alpha: 1.0) {
128 | didSet {
129 | trackLayer.setNeedsDisplay()
130 | }
131 | }
132 |
133 | @IBInspectable public var thumbTintColor: UIColor = UIColor.white {
134 | didSet {
135 | lowerThumbLayer.setNeedsDisplay()
136 | upperThumbLayer.setNeedsDisplay()
137 | }
138 | }
139 |
140 | @IBInspectable public var thumbBorderColor: UIColor = UIColor.gray {
141 | didSet {
142 | lowerThumbLayer.strokeColor = thumbBorderColor
143 | upperThumbLayer.strokeColor = thumbBorderColor
144 | }
145 | }
146 |
147 | @IBInspectable public var thumbBorderWidth: CGFloat = 0.5 {
148 | didSet {
149 | lowerThumbLayer.lineWidth = thumbBorderWidth
150 | upperThumbLayer.lineWidth = thumbBorderWidth
151 | }
152 | }
153 |
154 | @IBInspectable public var curvaceousness: CGFloat = 1.0 {
155 | didSet {
156 | if curvaceousness < 0.0 {
157 | curvaceousness = 0.0
158 | }
159 |
160 | if curvaceousness > 1.0 {
161 | curvaceousness = 1.0
162 | }
163 |
164 | trackLayer.setNeedsDisplay()
165 | lowerThumbLayer.setNeedsDisplay()
166 | upperThumbLayer.setNeedsDisplay()
167 | }
168 | }
169 |
170 | fileprivate var previouslocation = CGPoint()
171 |
172 | fileprivate let trackLayer = RangeSliderTrackLayer()
173 | fileprivate let lowerThumbLayer = RangeSliderThumbLayer()
174 | fileprivate let upperThumbLayer = RangeSliderThumbLayer()
175 |
176 | fileprivate var thumbWidth: CGFloat {
177 | return CGFloat(bounds.height)
178 | }
179 |
180 | override public var frame: CGRect {
181 | didSet {
182 | updateLayerFrames()
183 | }
184 | }
185 |
186 | override public init(frame: CGRect) {
187 | super.init(frame: frame)
188 | initializeLayers()
189 | }
190 |
191 | required public init?(coder: NSCoder) {
192 | super.init(coder: coder)
193 | initializeLayers()
194 | }
195 |
196 | override public func layoutSublayers(of: CALayer) {
197 | super.layoutSublayers(of:layer)
198 | updateLayerFrames()
199 | }
200 |
201 | fileprivate func initializeLayers() {
202 | layer.backgroundColor = UIColor.clear.cgColor
203 |
204 | trackLayer.rangeSlider = self
205 | trackLayer.contentsScale = UIScreen.main.scale
206 | layer.addSublayer(trackLayer)
207 |
208 | lowerThumbLayer.rangeSlider = self
209 | lowerThumbLayer.contentsScale = UIScreen.main.scale
210 | layer.addSublayer(lowerThumbLayer)
211 |
212 | upperThumbLayer.rangeSlider = self
213 | upperThumbLayer.contentsScale = UIScreen.main.scale
214 | layer.addSublayer(upperThumbLayer)
215 | }
216 |
217 | func updateLayerFrames() {
218 | CATransaction.begin()
219 | CATransaction.setDisableActions(true)
220 |
221 | trackLayer.frame = bounds.insetBy(dx: 0.0, dy: bounds.height/3)
222 | trackLayer.setNeedsDisplay()
223 |
224 | let lowerThumbCenter = CGFloat(positionForValue(lowerValue))
225 | lowerThumbLayer.frame = CGRect(x: lowerThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth)
226 | lowerThumbLayer.setNeedsDisplay()
227 |
228 | let upperThumbCenter = CGFloat(positionForValue(upperValue))
229 | upperThumbLayer.frame = CGRect(x: upperThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth)
230 | upperThumbLayer.setNeedsDisplay()
231 |
232 | CATransaction.commit()
233 | }
234 |
235 | func positionForValue(_ value: Double) -> Double {
236 | return Double(bounds.width - thumbWidth) * (value - minimumValue) /
237 | (maximumValue - minimumValue) + Double(thumbWidth/2.0)
238 | }
239 |
240 | func boundValue(_ value: Double, toLowerValue lowerValue: Double, upperValue: Double) -> Double {
241 | return min(max(value, lowerValue), upperValue)
242 | }
243 |
244 |
245 | // MARK: - Touches
246 |
247 | override public func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
248 | previouslocation = touch.location(in: self)
249 |
250 | // Hit test the thumb layers
251 | if lowerThumbLayer.frame.contains(previouslocation) {
252 | lowerThumbLayer.highlighted = true
253 | } else if upperThumbLayer.frame.contains(previouslocation) {
254 | upperThumbLayer.highlighted = true
255 | }
256 |
257 | return lowerThumbLayer.highlighted || upperThumbLayer.highlighted
258 | }
259 |
260 | override public func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
261 | let location = touch.location(in: self)
262 |
263 | // Determine by how much the user has dragged
264 | let deltaLocation = Double(location.x - previouslocation.x)
265 | let deltaValue = (maximumValue - minimumValue) * deltaLocation / Double(bounds.width - bounds.height)
266 |
267 | previouslocation = location
268 |
269 | // Update the values
270 | if lowerThumbLayer.highlighted {
271 | lowerValue = boundValue(lowerValue + deltaValue, toLowerValue: minimumValue, upperValue: upperValue - gapBetweenThumbs)
272 | } else if upperThumbLayer.highlighted {
273 | upperValue = boundValue(upperValue + deltaValue, toLowerValue: lowerValue + gapBetweenThumbs, upperValue: maximumValue)
274 | }
275 |
276 | sendActions(for: .valueChanged)
277 |
278 | return true
279 | }
280 |
281 | override public func endTracking(_ touch: UITouch?, with event: UIEvent?) {
282 | lowerThumbLayer.highlighted = false
283 | upperThumbLayer.highlighted = false
284 | }
285 | }
286 |
--------------------------------------------------------------------------------
/Example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 93360D122AB0C3DC003C0669 /* RangeSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93360D112AB0C3DC003C0669 /* RangeSlider.swift */; };
11 | 93C8129D2AAA3F3C005CEA65 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93C8129C2AAA3F3C005CEA65 /* AppDelegate.swift */; };
12 | 93C8129F2AAA3F3C005CEA65 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93C8129E2AAA3F3C005CEA65 /* SceneDelegate.swift */; };
13 | 93C812A12AAA3F3C005CEA65 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93C812A02AAA3F3C005CEA65 /* ViewController.swift */; };
14 | 93C812A42AAA3F3C005CEA65 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 93C812A22AAA3F3C005CEA65 /* Main.storyboard */; };
15 | 93C812A62AAA3F3C005CEA65 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 93C812A52AAA3F3C005CEA65 /* Assets.xcassets */; };
16 | 93C812A92AAA3F3C005CEA65 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 93C812A72AAA3F3C005CEA65 /* LaunchScreen.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXFileReference section */
20 | 93360D112AB0C3DC003C0669 /* RangeSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RangeSlider.swift; path = Sources/WARangeSlider/RangeSlider.swift; sourceTree = SOURCE_ROOT; };
21 | 93C812992AAA3F3C005CEA65 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
22 | 93C8129C2AAA3F3C005CEA65 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
23 | 93C8129E2AAA3F3C005CEA65 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
24 | 93C812A02AAA3F3C005CEA65 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
25 | 93C812A32AAA3F3C005CEA65 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
26 | 93C812A52AAA3F3C005CEA65 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | 93C812A82AAA3F3C005CEA65 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | 93C812AA2AAA3F3C005CEA65 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 93C812962AAA3F3C005CEA65 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 93C812902AAA3F3C005CEA65 = {
43 | isa = PBXGroup;
44 | children = (
45 | 93C8129B2AAA3F3C005CEA65 /* Example */,
46 | 93C8129A2AAA3F3C005CEA65 /* Products */,
47 | 93C812B42AAA41F4005CEA65 /* Frameworks */,
48 | );
49 | sourceTree = "";
50 | };
51 | 93C8129A2AAA3F3C005CEA65 /* Products */ = {
52 | isa = PBXGroup;
53 | children = (
54 | 93C812992AAA3F3C005CEA65 /* Example.app */,
55 | );
56 | name = Products;
57 | sourceTree = "";
58 | };
59 | 93C8129B2AAA3F3C005CEA65 /* Example */ = {
60 | isa = PBXGroup;
61 | children = (
62 | 93360D112AB0C3DC003C0669 /* RangeSlider.swift */,
63 | 93C8129C2AAA3F3C005CEA65 /* AppDelegate.swift */,
64 | 93C8129E2AAA3F3C005CEA65 /* SceneDelegate.swift */,
65 | 93C812A02AAA3F3C005CEA65 /* ViewController.swift */,
66 | 93C812A22AAA3F3C005CEA65 /* Main.storyboard */,
67 | 93C812A52AAA3F3C005CEA65 /* Assets.xcassets */,
68 | 93C812A72AAA3F3C005CEA65 /* LaunchScreen.storyboard */,
69 | 93C812AA2AAA3F3C005CEA65 /* Info.plist */,
70 | );
71 | path = Example;
72 | sourceTree = "";
73 | };
74 | 93C812B42AAA41F4005CEA65 /* Frameworks */ = {
75 | isa = PBXGroup;
76 | children = (
77 | );
78 | name = Frameworks;
79 | sourceTree = "";
80 | };
81 | /* End PBXGroup section */
82 |
83 | /* Begin PBXNativeTarget section */
84 | 93C812982AAA3F3C005CEA65 /* Example */ = {
85 | isa = PBXNativeTarget;
86 | buildConfigurationList = 93C812AD2AAA3F3C005CEA65 /* Build configuration list for PBXNativeTarget "Example" */;
87 | buildPhases = (
88 | 93C812952AAA3F3C005CEA65 /* Sources */,
89 | 93C812962AAA3F3C005CEA65 /* Frameworks */,
90 | 93C812972AAA3F3C005CEA65 /* Resources */,
91 | );
92 | buildRules = (
93 | );
94 | dependencies = (
95 | );
96 | name = Example;
97 | packageProductDependencies = (
98 | );
99 | productName = Example;
100 | productReference = 93C812992AAA3F3C005CEA65 /* Example.app */;
101 | productType = "com.apple.product-type.application";
102 | };
103 | /* End PBXNativeTarget section */
104 |
105 | /* Begin PBXProject section */
106 | 93C812912AAA3F3C005CEA65 /* Project object */ = {
107 | isa = PBXProject;
108 | attributes = {
109 | BuildIndependentTargetsInParallel = 1;
110 | LastSwiftUpdateCheck = 1430;
111 | LastUpgradeCheck = 1430;
112 | TargetAttributes = {
113 | 93C812982AAA3F3C005CEA65 = {
114 | CreatedOnToolsVersion = 14.3.1;
115 | };
116 | };
117 | };
118 | buildConfigurationList = 93C812942AAA3F3C005CEA65 /* Build configuration list for PBXProject "Example" */;
119 | compatibilityVersion = "Xcode 14.0";
120 | developmentRegion = en;
121 | hasScannedForEncodings = 0;
122 | knownRegions = (
123 | en,
124 | Base,
125 | );
126 | mainGroup = 93C812902AAA3F3C005CEA65;
127 | productRefGroup = 93C8129A2AAA3F3C005CEA65 /* Products */;
128 | projectDirPath = "";
129 | projectRoot = "";
130 | targets = (
131 | 93C812982AAA3F3C005CEA65 /* Example */,
132 | );
133 | };
134 | /* End PBXProject section */
135 |
136 | /* Begin PBXResourcesBuildPhase section */
137 | 93C812972AAA3F3C005CEA65 /* Resources */ = {
138 | isa = PBXResourcesBuildPhase;
139 | buildActionMask = 2147483647;
140 | files = (
141 | 93C812A92AAA3F3C005CEA65 /* LaunchScreen.storyboard in Resources */,
142 | 93C812A62AAA3F3C005CEA65 /* Assets.xcassets in Resources */,
143 | 93C812A42AAA3F3C005CEA65 /* Main.storyboard in Resources */,
144 | );
145 | runOnlyForDeploymentPostprocessing = 0;
146 | };
147 | /* End PBXResourcesBuildPhase section */
148 |
149 | /* Begin PBXSourcesBuildPhase section */
150 | 93C812952AAA3F3C005CEA65 /* Sources */ = {
151 | isa = PBXSourcesBuildPhase;
152 | buildActionMask = 2147483647;
153 | files = (
154 | 93360D122AB0C3DC003C0669 /* RangeSlider.swift in Sources */,
155 | 93C812A12AAA3F3C005CEA65 /* ViewController.swift in Sources */,
156 | 93C8129D2AAA3F3C005CEA65 /* AppDelegate.swift in Sources */,
157 | 93C8129F2AAA3F3C005CEA65 /* SceneDelegate.swift in Sources */,
158 | );
159 | runOnlyForDeploymentPostprocessing = 0;
160 | };
161 | /* End PBXSourcesBuildPhase section */
162 |
163 | /* Begin PBXVariantGroup section */
164 | 93C812A22AAA3F3C005CEA65 /* Main.storyboard */ = {
165 | isa = PBXVariantGroup;
166 | children = (
167 | 93C812A32AAA3F3C005CEA65 /* Base */,
168 | );
169 | name = Main.storyboard;
170 | sourceTree = "";
171 | };
172 | 93C812A72AAA3F3C005CEA65 /* LaunchScreen.storyboard */ = {
173 | isa = PBXVariantGroup;
174 | children = (
175 | 93C812A82AAA3F3C005CEA65 /* Base */,
176 | );
177 | name = LaunchScreen.storyboard;
178 | sourceTree = "";
179 | };
180 | /* End PBXVariantGroup section */
181 |
182 | /* Begin XCBuildConfiguration section */
183 | 93C812AB2AAA3F3C005CEA65 /* Debug */ = {
184 | isa = XCBuildConfiguration;
185 | buildSettings = {
186 | ALWAYS_SEARCH_USER_PATHS = NO;
187 | CLANG_ANALYZER_NONNULL = YES;
188 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
189 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
190 | CLANG_ENABLE_MODULES = YES;
191 | CLANG_ENABLE_OBJC_ARC = YES;
192 | CLANG_ENABLE_OBJC_WEAK = YES;
193 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
194 | CLANG_WARN_BOOL_CONVERSION = YES;
195 | CLANG_WARN_COMMA = YES;
196 | CLANG_WARN_CONSTANT_CONVERSION = YES;
197 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
200 | CLANG_WARN_EMPTY_BODY = YES;
201 | CLANG_WARN_ENUM_CONVERSION = YES;
202 | CLANG_WARN_INFINITE_RECURSION = YES;
203 | CLANG_WARN_INT_CONVERSION = YES;
204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
205 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
206 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
207 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
208 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
209 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
210 | CLANG_WARN_STRICT_PROTOTYPES = YES;
211 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
212 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
213 | CLANG_WARN_UNREACHABLE_CODE = YES;
214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
215 | COPY_PHASE_STRIP = NO;
216 | DEBUG_INFORMATION_FORMAT = dwarf;
217 | ENABLE_STRICT_OBJC_MSGSEND = YES;
218 | ENABLE_TESTABILITY = YES;
219 | GCC_C_LANGUAGE_STANDARD = gnu11;
220 | GCC_DYNAMIC_NO_PIC = NO;
221 | GCC_NO_COMMON_BLOCKS = YES;
222 | GCC_OPTIMIZATION_LEVEL = 0;
223 | GCC_PREPROCESSOR_DEFINITIONS = (
224 | "DEBUG=1",
225 | "$(inherited)",
226 | );
227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
229 | GCC_WARN_UNDECLARED_SELECTOR = YES;
230 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
231 | GCC_WARN_UNUSED_FUNCTION = YES;
232 | GCC_WARN_UNUSED_VARIABLE = YES;
233 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
234 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
235 | MTL_FAST_MATH = YES;
236 | ONLY_ACTIVE_ARCH = YES;
237 | SDKROOT = iphoneos;
238 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
239 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
240 | };
241 | name = Debug;
242 | };
243 | 93C812AC2AAA3F3C005CEA65 /* Release */ = {
244 | isa = XCBuildConfiguration;
245 | buildSettings = {
246 | ALWAYS_SEARCH_USER_PATHS = NO;
247 | CLANG_ANALYZER_NONNULL = YES;
248 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
249 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
250 | CLANG_ENABLE_MODULES = YES;
251 | CLANG_ENABLE_OBJC_ARC = YES;
252 | CLANG_ENABLE_OBJC_WEAK = YES;
253 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
254 | CLANG_WARN_BOOL_CONVERSION = YES;
255 | CLANG_WARN_COMMA = YES;
256 | CLANG_WARN_CONSTANT_CONVERSION = YES;
257 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
258 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
259 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
260 | CLANG_WARN_EMPTY_BODY = YES;
261 | CLANG_WARN_ENUM_CONVERSION = YES;
262 | CLANG_WARN_INFINITE_RECURSION = YES;
263 | CLANG_WARN_INT_CONVERSION = YES;
264 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
265 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
266 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
267 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
268 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
269 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
270 | CLANG_WARN_STRICT_PROTOTYPES = YES;
271 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
272 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
273 | CLANG_WARN_UNREACHABLE_CODE = YES;
274 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
275 | COPY_PHASE_STRIP = NO;
276 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
277 | ENABLE_NS_ASSERTIONS = NO;
278 | ENABLE_STRICT_OBJC_MSGSEND = YES;
279 | GCC_C_LANGUAGE_STANDARD = gnu11;
280 | GCC_NO_COMMON_BLOCKS = YES;
281 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
282 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
283 | GCC_WARN_UNDECLARED_SELECTOR = YES;
284 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
285 | GCC_WARN_UNUSED_FUNCTION = YES;
286 | GCC_WARN_UNUSED_VARIABLE = YES;
287 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
288 | MTL_ENABLE_DEBUG_INFO = NO;
289 | MTL_FAST_MATH = YES;
290 | SDKROOT = iphoneos;
291 | SWIFT_COMPILATION_MODE = wholemodule;
292 | SWIFT_OPTIMIZATION_LEVEL = "-O";
293 | VALIDATE_PRODUCT = YES;
294 | };
295 | name = Release;
296 | };
297 | 93C812AE2AAA3F3C005CEA65 /* Debug */ = {
298 | isa = XCBuildConfiguration;
299 | buildSettings = {
300 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
301 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
302 | CODE_SIGN_STYLE = Automatic;
303 | CURRENT_PROJECT_VERSION = 1;
304 | GENERATE_INFOPLIST_FILE = YES;
305 | INFOPLIST_FILE = Example/Info.plist;
306 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
307 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
308 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
309 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
310 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
311 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
312 | LD_RUNPATH_SEARCH_PATHS = (
313 | "$(inherited)",
314 | "@executable_path/Frameworks",
315 | );
316 | MARKETING_VERSION = 1.0;
317 | PRODUCT_BUNDLE_IDENTIFIER = wa.Example;
318 | PRODUCT_NAME = "$(TARGET_NAME)";
319 | SWIFT_EMIT_LOC_STRINGS = YES;
320 | SWIFT_VERSION = 5.0;
321 | TARGETED_DEVICE_FAMILY = "1,2";
322 | };
323 | name = Debug;
324 | };
325 | 93C812AF2AAA3F3C005CEA65 /* Release */ = {
326 | isa = XCBuildConfiguration;
327 | buildSettings = {
328 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
329 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
330 | CODE_SIGN_STYLE = Automatic;
331 | CURRENT_PROJECT_VERSION = 1;
332 | GENERATE_INFOPLIST_FILE = YES;
333 | INFOPLIST_FILE = Example/Info.plist;
334 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
335 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
336 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
337 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
338 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
339 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
340 | LD_RUNPATH_SEARCH_PATHS = (
341 | "$(inherited)",
342 | "@executable_path/Frameworks",
343 | );
344 | MARKETING_VERSION = 1.0;
345 | PRODUCT_BUNDLE_IDENTIFIER = wa.Example;
346 | PRODUCT_NAME = "$(TARGET_NAME)";
347 | SWIFT_EMIT_LOC_STRINGS = YES;
348 | SWIFT_VERSION = 5.0;
349 | TARGETED_DEVICE_FAMILY = "1,2";
350 | };
351 | name = Release;
352 | };
353 | /* End XCBuildConfiguration section */
354 |
355 | /* Begin XCConfigurationList section */
356 | 93C812942AAA3F3C005CEA65 /* Build configuration list for PBXProject "Example" */ = {
357 | isa = XCConfigurationList;
358 | buildConfigurations = (
359 | 93C812AB2AAA3F3C005CEA65 /* Debug */,
360 | 93C812AC2AAA3F3C005CEA65 /* Release */,
361 | );
362 | defaultConfigurationIsVisible = 0;
363 | defaultConfigurationName = Release;
364 | };
365 | 93C812AD2AAA3F3C005CEA65 /* Build configuration list for PBXNativeTarget "Example" */ = {
366 | isa = XCConfigurationList;
367 | buildConfigurations = (
368 | 93C812AE2AAA3F3C005CEA65 /* Debug */,
369 | 93C812AF2AAA3F3C005CEA65 /* Release */,
370 | );
371 | defaultConfigurationIsVisible = 0;
372 | defaultConfigurationName = Release;
373 | };
374 | /* End XCConfigurationList section */
375 | };
376 | rootObject = 93C812912AAA3F3C005CEA65 /* Project object */;
377 | }
378 |
--------------------------------------------------------------------------------