@@ -11,79 +11,72 @@ import UIKit
11@IBDesignable public class GMStepper: UIControl {
11@IBDesignable public class GMStepper: UIControl {
13 /// Current value of the stepper. Defaults to 0.
13 /// Current value of the stepper. Defaults to 0.
14− @objc @IBInspectable public var value: Double = 0 {
14+ @IBInspectable public var value: Double = 0 {
16 value = min(maximumValue, max(minimumValue, value))
16 value = min(maximumValue, max(minimumValue, value))
18 let isInteger = floor(value) == value
18 let isInteger = floor(value) == value
21− // If we have items, we will display them as steps
24− if isInteger && stepValue == 1.0 && items.count > 0 {
25− label.text = items[Int(value)]
27− else if showIntegerIfDoubleIsInteger && isInteger {
20+ if showIntegerIfDoubleIsInteger && isInteger {
28 label.text = String(stringInterpolationSegment: Int(value))
21 label.text = String(stringInterpolationSegment: Int(value))
30 label.text = String(stringInterpolationSegment: value)
23 label.text = String(stringInterpolationSegment: value)
33 if oldValue != value {
26 if oldValue != value {
34− sendActions(for: .valueChanged)
27+ sendActionsForControlEvents(.ValueChanged)
39 /// Minimum value. Must be less than maximumValue. Defaults to 0.
32 /// Minimum value. Must be less than maximumValue. Defaults to 0.
40− @objc @IBInspectable public var minimumValue: Double = 0 {
33+ @IBInspectable public var minimumValue: Double = 0 {
42 value = min(maximumValue, max(minimumValue, value))
35 value = min(maximumValue, max(minimumValue, value))
46 /// Maximum value. Must be more than minimumValue. Defaults to 100.
39 /// Maximum value. Must be more than minimumValue. Defaults to 100.
47− @objc @IBInspectable public var maximumValue: Double = 100 {
40+ @IBInspectable public var maximumValue: Double = 100 {
49 value = min(maximumValue, max(minimumValue, value))
42 value = min(maximumValue, max(minimumValue, value))
53 /// Step/Increment value as in UIStepper. Defaults to 1.
46 /// Step/Increment value as in UIStepper. Defaults to 1.
54− @objc @IBInspectable public var stepValue: Double = 1
47+ @IBInspectable public var stepValue: Double = 1
56 /// The same as UIStepper's autorepeat. If true, holding on the buttons or keeping the pan gesture alters the value repeatedly. Defaults to true.
49 /// The same as UIStepper's autorepeat. If true, holding on the buttons or keeping the pan gesture alters the value repeatedly. Defaults to true.
57− @objc @IBInspectable public var autorepeat: Bool = true
50+ @IBInspectable public var autorepeat: Bool = true
59 /// If the value is integer, it is shown without floating point.
52 /// If the value is integer, it is shown without floating point.
60− @objc @IBInspectable public var showIntegerIfDoubleIsInteger: Bool = true
53+ @IBInspectable public var showIntegerIfDoubleIsInteger: Bool = true
62 /// Text on the left button. Be sure that it fits in the button. Defaults to "−".
55 /// Text on the left button. Be sure that it fits in the button. Defaults to "−".
63− @objc @IBInspectable public var leftButtonText: String = "−" {
56+ @IBInspectable public var leftButtonText: String = "−" {
65− leftButton.setTitle(leftButtonText, for: .normal)
58+ leftButton.setTitle(leftButtonText, forState: .Normal)
69 /// Text on the right button. Be sure that it fits in the button. Defaults to "+".
62 /// Text on the right button. Be sure that it fits in the button. Defaults to "+".
70− @objc @IBInspectable public var rightButtonText: String = "+" {
63+ @IBInspectable public var rightButtonText: String = "+" {
72− rightButton.setTitle(rightButtonText, for: .normal)
65+ rightButton.setTitle(rightButtonText, forState: .Normal)
76 /// Text color of the buttons. Defaults to white.
69 /// Text color of the buttons. Defaults to white.
77− @objc @IBInspectable public var buttonsTextColor: UIColor = UIColor.white {
70+ @IBInspectable public var buttonsTextColor: UIColor = UIColor.whiteColor() {
79 for button in [leftButton, rightButton] {
72 for button in [leftButton, rightButton] {
80− button.setTitleColor(buttonsTextColor, for: .normal)
73+ button.setTitleColor(buttonsTextColor, forState: .Normal)
85 /// Background color of the buttons. Defaults to dark blue.
78 /// Background color of the buttons. Defaults to dark blue.
86− @objc @IBInspectable public var buttonsBackgroundColor: UIColor = UIColor(red:0.21, green:0.5, blue:0.74, alpha:1) {
79+ @IBInspectable public var buttonsBackgroundColor: UIColor = UIColor(red:0.21, green:0.5, blue:0.74, alpha:1) {
88 for button in [leftButton, rightButton] {
81 for button in [leftButton, rightButton] {
89 button.backgroundColor = buttonsBackgroundColor
82 button.backgroundColor = buttonsBackgroundColor
@@ -93,7 +86,7 @@ import UIKit
95 /// Font of the buttons. Defaults to AvenirNext-Bold, 20.0 points in size.
88 /// Font of the buttons. Defaults to AvenirNext-Bold, 20.0 points in size.
96− @objc public var buttonsFont = UIFont(name: "AvenirNext-Bold", size: 20.0)! {
89+ public var buttonsFont = UIFont(name: "AvenirNext-Bold", size: 20.0)! {
98 for button in [leftButton, rightButton] {
91 for button in [leftButton, rightButton] {
99 button.titleLabel?.font = buttonsFont
92 button.titleLabel?.font = buttonsFont
@@ -102,35 +95,28 @@ import UIKit
104 /// Text color of the middle label. Defaults to white.
97 /// Text color of the middle label. Defaults to white.
105− @objc @IBInspectable public var labelTextColor: UIColor = UIColor.white {
98+ @IBInspectable public var labelTextColor: UIColor = UIColor.whiteColor() {
107 label.textColor = labelTextColor
100 label.textColor = labelTextColor
111 /// Text color of the middle label. Defaults to lighter blue.
104 /// Text color of the middle label. Defaults to lighter blue.
112− @objc @IBInspectable public var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1) {
105+ @IBInspectable public var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1) {
114 label.backgroundColor = labelBackgroundColor
107 label.backgroundColor = labelBackgroundColor
118 /// Font of the middle label. Defaults to AvenirNext-Bold, 25.0 points in size.
111 /// Font of the middle label. Defaults to AvenirNext-Bold, 25.0 points in size.
119− @objc public var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)! {
112+ public var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)! {
121 label.font = labelFont
114 label.font = labelFont
124− /// Corner radius of the middle label. Defaults to 0.
125− @objc @IBInspectable public var labelCornerRadius: CGFloat = 0 {
127− label.layer.cornerRadius = labelCornerRadius
132 /// Corner radius of the stepper's layer. Defaults to 4.0.
118 /// Corner radius of the stepper's layer. Defaults to 4.0.
133− @objc @IBInspectable public var cornerRadius: CGFloat = 4.0 {
119+ @IBInspectable public var cornerRadius: CGFloat = 4.0 {
135 layer.cornerRadius = cornerRadius
121 layer.cornerRadius = cornerRadius
136 clipsToBounds = true
122 clipsToBounds = true
@@ -138,7 +124,7 @@ import UIKit
140 /// Border width of the stepper and middle label's layer. Defaults to 0.0.
126 /// Border width of the stepper and middle label's layer. Defaults to 0.0.
141− @objc @IBInspectable public var borderWidth: CGFloat = 0.0 {
127+ @IBInspectable public var borderWidth: CGFloat = 0.0 {
143 layer.borderWidth = borderWidth
129 layer.borderWidth = borderWidth
144 label.layer.borderWidth = borderWidth
130 label.layer.borderWidth = borderWidth
@@ -146,15 +132,15 @@ import UIKit
148 /// Color of the border of the stepper and middle label's layer. Defaults to clear color.
134 /// Color of the border of the stepper and middle label's layer. Defaults to clear color.
149− @objc @IBInspectable public var borderColor: UIColor = UIColor.clear {
135+ @IBInspectable public var borderColor: UIColor = UIColor.clearColor() {
151− layer.borderColor = borderColor.cgColor
137+ layer.borderColor = borderColor.CGColor
152− label.layer.borderColor = borderColor.cgColor
138+ label.layer.borderColor = borderColor.CGColor
156 /// Percentage of the middle label's width. Must be between 0 and 1. Defaults to 0.5. Be sure that it is wide enough to show the value.
142 /// Percentage of the middle label's width. Must be between 0 and 1. Defaults to 0.5. Be sure that it is wide enough to show the value.
157− @objc @IBInspectable public var labelWidthWeight: CGFloat = 0.5 {
143+ @IBInspectable public var labelWidthWeight: CGFloat = 0.5 {
159 labelWidthWeight = min(1, max(0, labelWidthWeight))
145 labelWidthWeight = min(1, max(0, labelWidthWeight))
160 setNeedsLayout()
146 setNeedsLayout()
@@ -162,7 +148,7 @@ import UIKit
164 /// Color of the flashing animation on the buttons in case the value hit the limit.
150 /// Color of the flashing animation on the buttons in case the value hit the limit.
165− @objc @IBInspectable public var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
151+ @IBInspectable public var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
168 Width of the sliding animation. When buttons clicked, the middle label does a slide animation towards to the clicked button. Defaults to 5.
154 Width of the sliding animation. When buttons clicked, the middle label does a slide animation towards to the clicked button. Defaults to 5.
@@ -170,40 +156,38 @@ import UIKit
170 let labelSlideLength: CGFloat = 5
156 let labelSlideLength: CGFloat = 5
172 /// Duration of the sliding animation
158 /// Duration of the sliding animation
173− let labelSlideDuration = TimeInterval(0.1)
159+ let labelSlideDuration = NSTimeInterval(0.1)
175 /// Duration of the animation when the value hits the limit.
161 /// Duration of the animation when the value hits the limit.
176− let limitHitAnimationDuration = TimeInterval(0.1)
162+ let limitHitAnimationDuration = NSTimeInterval(0.1)
178 lazy var leftButton: UIButton = {
164 lazy var leftButton: UIButton = {
179 let button = UIButton()
165 let button = UIButton()
180− button.setTitle(self.leftButtonText, for: .normal)
166+ button.setTitle(self.leftButtonText, forState: .Normal)
181− button.setTitleColor(self.buttonsTextColor, for: .normal)
167+ button.setTitleColor(self.buttonsTextColor, forState: .Normal)
182 button.backgroundColor = self.buttonsBackgroundColor
168 button.backgroundColor = self.buttonsBackgroundColor
183 button.titleLabel?.font = self.buttonsFont
169 button.titleLabel?.font = self.buttonsFont
184− button.addTarget(self, action: #selector(GMStepper.leftButtonTouchDown), for: .touchDown)
170+ button.addTarget(self, action: "leftButtonTouchDown:", forControlEvents: .TouchDown)
185− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpInside)
171+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
186− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpOutside)
172+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
187− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchCancel)
188 return button
173 return button
191 lazy var rightButton: UIButton = {
176 lazy var rightButton: UIButton = {
192 let button = UIButton()
177 let button = UIButton()
193− button.setTitle(self.rightButtonText, for: .normal)
178+ button.setTitle(self.rightButtonText, forState: .Normal)
194− button.setTitleColor(self.buttonsTextColor, for: .normal)
179+ button.setTitleColor(self.buttonsTextColor, forState: .Normal)
195 button.backgroundColor = self.buttonsBackgroundColor
180 button.backgroundColor = self.buttonsBackgroundColor
196 button.titleLabel?.font = self.buttonsFont
181 button.titleLabel?.font = self.buttonsFont
197− button.addTarget(self, action: #selector(GMStepper.rightButtonTouchDown), for: .touchDown)
182+ button.addTarget(self, action: "rightButtonTouchDown:", forControlEvents: .TouchDown)
198− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpInside)
183+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
199− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpOutside)
184+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
200− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchCancel)
201 return button
185 return button
204 lazy var label: UILabel = {
188 lazy var label: UILabel = {
205 let label = UILabel()
189 let label = UILabel()
206− label.textAlignment = .center
190+ label.textAlignment = .Center
207 if self.showIntegerIfDoubleIsInteger && floor(self.value) == self.value {
191 if self.showIntegerIfDoubleIsInteger && floor(self.value) == self.value {
208 label.text = String(stringInterpolationSegment: Int(self.value))
192 label.text = String(stringInterpolationSegment: Int(self.value))
@@ -212,10 +196,8 @@ import UIKit
212 label.textColor = self.labelTextColor
196 label.textColor = self.labelTextColor
213 label.backgroundColor = self.labelBackgroundColor
197 label.backgroundColor = self.labelBackgroundColor
214 label.font = self.labelFont
198 label.font = self.labelFont
215− label.layer.cornerRadius = self.labelCornerRadius
199+ label.userInteractionEnabled = true
216− label.layer.masksToBounds = true
217− label.isUserInteractionEnabled = true
218− let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(GMStepper.handlePan))
200+ let panRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
219 panRecognizer.maximumNumberOfTouches = 1
201 panRecognizer.maximumNumberOfTouches = 1
220 label.addGestureRecognizer(panRecognizer)
202 label.addGestureRecognizer(panRecognizer)
221 return label
203 return label
@@ -243,33 +225,9 @@ import UIKit
248− @objc public var items : [String] = [] {
250− let isInteger = floor(value) == value
253− // If we have items, we will display them as steps
256− if isInteger && stepValue == 1.0 && items.count > 0 {
258− var value = Int(self.value)
260− if value >= items.count {
261− value = items.count - 1
262− self.value = Double(value)
265− label.text = items[value]
271 /// Timer used for autorepeat option
229 /// Timer used for autorepeat option
272− var timer: Timer?
230+ var timer: NSTimer?
274 /** When UIStepper reaches its top speed, it alters the value with a time interval of ~0.05 sec.
232 /** When UIStepper reaches its top speed, it alters the value with a time interval of ~0.05 sec.
275 The user pressing and holding on the stepper repeatedly:
233 The user pressing and holding on the stepper repeatedly:
@@ -277,7 +235,7 @@ import UIKit
277 - For the next 1.5 sec, it changes the value every 0.1 sec.
235 - For the next 1.5 sec, it changes the value every 0.1 sec.
278 - Then, every 0.05 sec.
236 - Then, every 0.05 sec.
280− let timerInterval = TimeInterval(0.05)
238+ let timerInterval = NSTimeInterval(0.05)
282 /// Check the handleTimerFire: function. While it is counting the number of fires, it decreases the mod value so that the value is altered more frequently.
240 /// Check the handleTimerFire: function. While it is counting the number of fires, it decreases the mod value so that the value is altered more frequently.
283 var timerFireCount = 0
241 var timerFireCount = 0
@@ -291,12 +249,12 @@ import UIKit
294− @objc required public init?(coder aDecoder: NSCoder) {
252+ required public init?(coder aDecoder: NSCoder) {
295 super.init(coder: aDecoder)
253 super.init(coder: aDecoder)
299− @objc public override init(frame: CGRect) {
257+ public override init(frame: CGRect) {
300 super.init(frame: frame)
258 super.init(frame: frame)
@@ -309,9 +267,8 @@ import UIKit
309 backgroundColor = buttonsBackgroundColor
267 backgroundColor = buttonsBackgroundColor
310 layer.cornerRadius = cornerRadius
268 layer.cornerRadius = cornerRadius
311 clipsToBounds = true
269 clipsToBounds = true
312− labelOriginalCenter = label.center
314− NotificationCenter.default.addObserver(self, selector: #selector(GMStepper.reset), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
271+ NSNotificationCenter.defaultCenter().addObserver(self, selector: "reset", name: UIApplicationWillResignActiveNotification, object: nil)
317 public override func layoutSubviews() {
274 public override func layoutSubviews() {
@@ -337,7 +294,7 @@ import UIKit
339 resetTimer()
296 resetTimer()
340− NotificationCenter.default.removeObserver(self)
297+ NSNotificationCenter.defaultCenter().removeObserver(self)
343 /// Useful closure for logging the timer interval. You can call this in the timer handler to test the autorepeat option. Not used in the current implementation.
300 /// Useful closure for logging the timer interval. You can call this in the timer handler to test the autorepeat option. Not used in the current implementation.
@@ -356,17 +313,17 @@ import UIKit
357// MARK: Pan Gesture
314// MARK: Pan Gesture
358extension GMStepper {
315extension GMStepper {
359− @objc func handlePan(gesture: UIPanGestureRecognizer) {
316+ func handlePan(gesture: UIPanGestureRecognizer) {
360 switch gesture.state {
317 switch gesture.state {
361− case .began:
318+ case .Began:
362− leftButton.isEnabled = false
319+ leftButton.enabled = false
363− rightButton.isEnabled = false
320+ rightButton.enabled = false
364− case .changed:
321+ case .Changed:
365− let translation = gesture.translation(in: label)
322+ let translation = gesture.translationInView(label)
366− gesture.setTranslation(CGPoint.zero, in: label)
323+ gesture.setTranslation(CGPointZero, inView: label)
368− let slidingRight = gesture.velocity(in: label).x > 0
325+ let slidingRight = gesture.velocityInView(label).x > 0
369− let slidingLeft = gesture.velocity(in: label).x < 0
326+ let slidingLeft = gesture.velocityInView(label).x < 0
371 // Move the label with pan
328 // Move the label with pan
372 if slidingRight {
329 if slidingRight {
@@ -399,23 +356,23 @@ extension GMStepper {
399 self.rightButton.backgroundColor = self.buttonsBackgroundColor
356 self.rightButton.backgroundColor = self.buttonsBackgroundColor
400 self.leftButton.backgroundColor = self.buttonsBackgroundColor
357 self.leftButton.backgroundColor = self.buttonsBackgroundColor
402− case .ended, .cancelled, .failed:
359+ case .Ended, .Cancelled, .Failed:
409− @objc func reset() {
366+ func reset() {
410 panState = .Stable
367 panState = .Stable
411 stepperState = .Stable
368 stepperState = .Stable
412 resetTimer()
369 resetTimer()
414− leftButton.isEnabled = true
371+ leftButton.enabled = true
415− rightButton.isEnabled = true
372+ rightButton.enabled = true
416− label.isUserInteractionEnabled = true
373+ label.userInteractionEnabled = true
418− UIView.animate(withDuration: self.labelSlideDuration, animations: {
375+ UIView.animateWithDuration(self.labelSlideDuration, animations: {
419 self.label.center = self.labelOriginalCenter
376 self.label.center = self.labelOriginalCenter
420 self.rightButton.backgroundColor = self.buttonsBackgroundColor
377 self.rightButton.backgroundColor = self.buttonsBackgroundColor
421 self.leftButton.backgroundColor = self.buttonsBackgroundColor
378 self.leftButton.backgroundColor = self.buttonsBackgroundColor
@@ -425,9 +382,9 @@ extension GMStepper {
426// MARK: Button Events
383// MARK: Button Events
427extension GMStepper {
384extension GMStepper {
428− @objc func leftButtonTouchDown(button: UIButton) {
385+ func leftButtonTouchDown(button: UIButton) {
429− rightButton.isEnabled = false
386+ rightButton.enabled = false
430− label.isUserInteractionEnabled = false
387+ label.userInteractionEnabled = false
431 resetTimer()
388 resetTimer()
433 if value == minimumValue {
390 if value == minimumValue {
@@ -439,9 +396,9 @@ extension GMStepper {
442− @objc func rightButtonTouchDown(button: UIButton) {
399+ func rightButtonTouchDown(button: UIButton) {
443− leftButton.isEnabled = false
400+ leftButton.enabled = false
444− label.isUserInteractionEnabled = false
401+ label.userInteractionEnabled = false
445 resetTimer()
402 resetTimer()
447 if value == maximumValue {
404 if value == maximumValue {
@@ -452,7 +409,7 @@ extension GMStepper {
455− @objc func buttonTouchUp(button: UIButton) {
412+ func buttonTouchUp(button: UIButton) {
@@ -461,20 +418,20 @@ extension GMStepper {
461extension GMStepper {
418extension GMStepper {
463 func animateSlideLeft() {
420 func animateSlideLeft() {
464− UIView.animate(withDuration: labelSlideDuration) {
421+ UIView.animateWithDuration(labelSlideDuration) {
465 self.label.center.x -= self.labelSlideLength
422 self.label.center.x -= self.labelSlideLength
469 func animateSlideRight() {
426 func animateSlideRight() {
470− UIView.animate(withDuration: labelSlideDuration) {
427+ UIView.animateWithDuration(labelSlideDuration) {
471 self.label.center.x += self.labelSlideLength
428 self.label.center.x += self.labelSlideLength
475 func animateToOriginalPosition() {
432 func animateToOriginalPosition() {
476 if self.label.center != self.labelOriginalCenter {
433 if self.label.center != self.labelOriginalCenter {
477− UIView.animate(withDuration: labelSlideDuration) {
434+ UIView.animateWithDuration(labelSlideDuration) {
478 self.label.center = self.labelOriginalCenter
435 self.label.center = self.labelOriginalCenter
@@ -482,14 +439,14 @@ extension GMStepper {
483 func animateLimitHitIfNeeded() {
440 func animateLimitHitIfNeeded() {
484 if value == minimumValue {
441 if value == minimumValue {
485− animateLimitHitForButton(button: leftButton)
442+ animateLimitHitForButton(leftButton)
486 } else if value == maximumValue {
443 } else if value == maximumValue {
487− animateLimitHitForButton(button: rightButton)
444+ animateLimitHitForButton(rightButton)
491 func animateLimitHitForButton(button: UIButton){
448 func animateLimitHitForButton(button: UIButton){
492− UIView.animate(withDuration: limitHitAnimationDuration) {
449+ UIView.animateWithDuration(limitHitAnimationDuration) {
493 button.backgroundColor = self.limitHitAnimationColor
450 button.backgroundColor = self.limitHitAnimationColor
@@ -497,7 +454,7 @@ extension GMStepper {
498// MARK: Timer
455// MARK: Timer
499extension GMStepper {
456extension GMStepper {
500− @objc func handleTimerFire(timer: Timer) {
457+ func handleTimerFire(timer: NSTimer) {
501 timerFireCount += 1
458 timerFireCount += 1
503 if timerFireCount % timerFireCountModulo == 0 {
460 if timerFireCount % timerFireCountModulo == 0 {
@@ -506,7 +463,7 @@ extension GMStepper {
508 func scheduleTimer() {
465 func scheduleTimer() {
509− timer = Timer.scheduledTimer(timeInterval: timerInterval, target: self, selector: #selector(GMStepper.handleTimerFire), userInfo: nil, repeats: true)
466+ timer = NSTimer.scheduledTimerWithTimeInterval(timerInterval, target: self, selector: "handleTimerFire:", userInfo: nil, repeats: true)
512 func resetTimer() {
469 func resetTimer() {