@@ -11,79 +11,71 @@ import UIKit
1111@IBDesignable public class GMStepper: UIControl {
1212
1313 /// Current value of the stepper. Defaults to 0.
14− @objc @IBInspectable public var value: Double = 0 {
14+ @IBInspectable public var value: Double = 0 {
1515 didSet {
1616 value = min(maximumValue, max(minimumValue, value))
1717
1818 let isInteger = floor(value) == value
19−
20− //
21− // If we have items, we will display them as steps
22− //
23−
24− if isInteger && stepValue == 1.0 && items.count > 0 {
25− label.text = items[Int(value)]
26− }
27− else if showIntegerIfDoubleIsInteger && isInteger {
19+
20+ if showIntegerIfDoubleIsInteger && isInteger {
2821 label.text = String(stringInterpolationSegment: Int(value))
2922 } else {
3023 label.text = String(stringInterpolationSegment: value)
3124 }
3225
3326 if oldValue != value {
34− sendActions(for: .valueChanged)
27+ sendActionsForControlEvents(.ValueChanged)
3528 }
3629 }
3730 }
3831
3932 /// 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 {
4134 didSet {
4235 value = min(maximumValue, max(minimumValue, value))
4336 }
4437 }
4538
4639 /// 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 {
4841 didSet {
4942 value = min(maximumValue, max(minimumValue, value))
5043 }
5144 }
5245
5346 /// Step/Increment value as in UIStepper. Defaults to 1.
54− @objc @IBInspectable public var stepValue: Double = 1
47+ @IBInspectable public var stepValue: Double = 1
5548
5649 /// 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
5851
59− /// If the value is integer, it is shown without floating point.
60− @objc @IBInspectable public var showIntegerIfDoubleIsInteger: Bool = true
52+ @IBInspectable public var showIntegerIfDoubleIsInteger: Bool = true
6153
62− /// Text on the left button. Be sure that it fits in the button. Defaults to "−".
63− @objc @IBInspectable public var leftButtonText: String = "−" {
54+ /// Text on the left button. Be sure that it fits in the button. Defaults to "-".
55+ @IBInspectable public var leftButtonText: String = "-" {
6456 didSet {
65− leftButton.setTitle(leftButtonText, for: .normal)
57+ leftButton.setTitle(leftButtonText, forState: .Normal)
6658 }
6759 }
6860
6961 /// Text on the right button. Be sure that it fits in the button. Defaults to "+".
70− @objc @IBInspectable public var rightButtonText: String = "+" {
62+ @IBInspectable public var rightButtonText: String = "+" {
7163 didSet {
72− rightButton.setTitle(rightButtonText, for: .normal)
64+ rightButton.setTitle(rightButtonText, forState: .Normal)
7365 }
7466 }
7567
7668 /// Text color of the buttons. Defaults to white.
77− @objc @IBInspectable public var buttonsTextColor: UIColor = UIColor.white {
69+ @IBInspectable public var buttonsTextColor: UIColor = UIColor.whiteColor() {
7870 didSet {
7971 for button in [leftButton, rightButton] {
80− button.setTitleColor(buttonsTextColor, for: .normal)
72+ button.setTitleColor(buttonsTextColor, forState: .Normal)
8173 }
8274 }
8375 }
8476
8577 /// 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) {
78+ @IBInspectable public var buttonsBackgroundColor: UIColor = UIColor(red:0.21, green:0.5, blue:0.74, alpha:1) {
8779 didSet {
8880 for button in [leftButton, rightButton] {
8981 button.backgroundColor = buttonsBackgroundColor
@@ -93,7 +85,7 @@ import UIKit
9385 }
9486
9587 /// 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)! {
88+ public var buttonsFont = UIFont(name: "AvenirNext-Bold", size: 20.0)! {
9789 didSet {
9890 for button in [leftButton, rightButton] {
9991 button.titleLabel?.font = buttonsFont
@@ -102,59 +94,36 @@ import UIKit
10294 }
10395
10496 /// Text color of the middle label. Defaults to white.
105− @objc @IBInspectable public var labelTextColor: UIColor = UIColor.white {
97+ @IBInspectable public var labelTextColor: UIColor = UIColor.whiteColor() {
10698 didSet {
10799 label.textColor = labelTextColor
108100 }
109101 }
110102
111103 /// 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) {
104+ @IBInspectable public var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1) {
113105 didSet {
114106 label.backgroundColor = labelBackgroundColor
115107 }
116108 }
117109
118110 /// 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)! {
111+ public var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)! {
120112 didSet {
121113 label.font = labelFont
122114 }
123115 }
124− /// Corner radius of the middle label. Defaults to 0.
125− @objc @IBInspectable public var labelCornerRadius: CGFloat = 0 {
126− didSet {
127− label.layer.cornerRadius = labelCornerRadius
128−
129− }
130− }
131116
132117 /// Corner radius of the stepper's layer. Defaults to 4.0.
133− @objc @IBInspectable public var cornerRadius: CGFloat = 4.0 {
118+ @IBInspectable public var cornerRadius: CGFloat = 4.0 {
134119 didSet {
135120 layer.cornerRadius = cornerRadius
136121 clipsToBounds = true
137122 }
138123 }
139−
140− /// Border width of the stepper and middle label's layer. Defaults to 0.0.
141− @objc @IBInspectable public var borderWidth: CGFloat = 0.0 {
142− didSet {
143− layer.borderWidth = borderWidth
144− label.layer.borderWidth = borderWidth
145− }
146− }
147−
148− /// 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 {
150− didSet {
151− layer.borderColor = borderColor.cgColor
152− label.layer.borderColor = borderColor.cgColor
153− }
154− }
155124
156125 /// 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 {
126+ @IBInspectable public var labelWidthWeight: CGFloat = 0.5 {
158127 didSet {
159128 labelWidthWeight = min(1, max(0, labelWidthWeight))
160129 setNeedsLayout()
@@ -162,7 +131,7 @@ import UIKit
162131 }
163132
164133 /// 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)
134+ @IBInspectable public var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
166135
167136 /**
168137 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 +139,38 @@ import UIKit
170139 let labelSlideLength: CGFloat = 5
171140
172141 /// Duration of the sliding animation
173− let labelSlideDuration = TimeInterval(0.1)
142+ let labelSlideDuration = NSTimeInterval(0.1)
174143
175144 /// Duration of the animation when the value hits the limit.
176− let limitHitAnimationDuration = TimeInterval(0.1)
145+ let limitHitAnimationDuration = NSTimeInterval(0.1)
177146
178147 lazy var leftButton: UIButton = {
179148 let button = UIButton()
180− button.setTitle(self.leftButtonText, for: .normal)
181− button.setTitleColor(self.buttonsTextColor, for: .normal)
149+ button.setTitle(self.leftButtonText, forState: .Normal)
150+ button.setTitleColor(self.buttonsTextColor, forState: .Normal)
182151 button.backgroundColor = self.buttonsBackgroundColor
183152 button.titleLabel?.font = self.buttonsFont
184− button.addTarget(self, action: #selector(GMStepper.leftButtonTouchDown), for: .touchDown)
185− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpInside)
186− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpOutside)
187− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchCancel)
153+ button.addTarget(self, action: "leftButtonTouchDown:", forControlEvents: .TouchDown)
154+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
155+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
188156 return button
189157 }()
190158
191159 lazy var rightButton: UIButton = {
192160 let button = UIButton()
193− button.setTitle(self.rightButtonText, for: .normal)
194− button.setTitleColor(self.buttonsTextColor, for: .normal)
161+ button.setTitle(self.rightButtonText, forState: .Normal)
162+ button.setTitleColor(self.buttonsTextColor, forState: .Normal)
195163 button.backgroundColor = self.buttonsBackgroundColor
196164 button.titleLabel?.font = self.buttonsFont
197− button.addTarget(self, action: #selector(GMStepper.rightButtonTouchDown), for: .touchDown)
198− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpInside)
199− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpOutside)
200− button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchCancel)
165+ button.addTarget(self, action: "rightButtonTouchDown:", forControlEvents: .TouchDown)
166+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
167+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
201168 return button
202169 }()
203170
204171 lazy var label: UILabel = {
205172 let label = UILabel()
206− label.textAlignment = .center
173+ label.textAlignment = .Center
207174 if self.showIntegerIfDoubleIsInteger && floor(self.value) == self.value {
208175 label.text = String(stringInterpolationSegment: Int(self.value))
209176 } else {
@@ -212,10 +179,8 @@ import UIKit
212179 label.textColor = self.labelTextColor
213180 label.backgroundColor = self.labelBackgroundColor
214181 label.font = self.labelFont
215− label.layer.cornerRadius = self.labelCornerRadius
216− label.layer.masksToBounds = true
217− label.isUserInteractionEnabled = true
218− let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(GMStepper.handlePan))
182+ label.userInteractionEnabled = true
183+ let panRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
219184 panRecognizer.maximumNumberOfTouches = 1
220185 label.addGestureRecognizer(panRecognizer)
221186 return label
@@ -243,33 +208,9 @@ import UIKit
243208 }
244209 }
245210 }
246−
247−
248− @objc public var items : [String] = [] {
249− didSet {
250− let isInteger = floor(value) == value
251−
252− //
253− // If we have items, we will display them as steps
254− //
255−
256− if isInteger && stepValue == 1.0 && items.count > 0 {
257−
258− var value = Int(self.value)
259−
260− if value >= items.count {
261− value = items.count - 1
262− self.value = Double(value)
263− }
264− else {
265− label.text = items[value]
266− }
267− }
268− }
269− }
270211
271212 /// Timer used for autorepeat option
272− var timer: Timer?
213+ var timer: NSTimer?
273214
274215 /** When UIStepper reaches its top speed, it alters the value with a time interval of ~0.05 sec.
275216 The user pressing and holding on the stepper repeatedly:
@@ -277,7 +218,7 @@ import UIKit
277218 - For the next 1.5 sec, it changes the value every 0.1 sec.
278219 - Then, every 0.05 sec.
279220 */
280− let timerInterval = TimeInterval(0.05)
221+ let timerInterval = NSTimeInterval(0.05)
281222
282223 /// 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.
283224 var timerFireCount = 0
@@ -291,12 +232,25 @@ import UIKit
291232 }
292233 }
293234
294− @objc required public init?(coder aDecoder: NSCoder) {
235+ /// Useful for logging the timer interval. You can call this in the timer handler to test the autorepeat option.
236+ lazy var printTimerGaps: () -> () = {
237+ var prevTime: CFAbsoluteTime?
238+
239+ return { _ in
240+ var now = CFAbsoluteTimeGetCurrent()
241+ if let prevTime = prevTime {
242+ println(now - prevTime)
243+ }
244+ prevTime = now
245+ }
246+ }()
247+
248+ required public init(coder aDecoder: NSCoder) {
295249 super.init(coder: aDecoder)
296250 setup()
297251 }
298252
299− @objc public override init(frame: CGRect) {
253+ public override init(frame: CGRect) {
300254 super.init(frame: frame)
301255 setup()
302256 }
@@ -309,9 +263,6 @@ import UIKit
309263 backgroundColor = buttonsBackgroundColor
310264 layer.cornerRadius = cornerRadius
311265 clipsToBounds = true
312− labelOriginalCenter = label.center
313−
314− NotificationCenter.default.addObserver(self, selector: #selector(GMStepper.reset), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
315266 }
316267
317268 public override func layoutSubviews() {
@@ -334,39 +285,21 @@ import UIKit
334285 value -= stepValue
335286 }
336287 }
337−
338− deinit {
339− resetTimer()
340− NotificationCenter.default.removeObserver(self)
341− }
342−
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.
344−// lazy var printTimerGaps: () -> () = {
345−// var prevTime: CFAbsoluteTime?
346−//
347−// return { _ in
348−// var now = CFAbsoluteTimeGetCurrent()
349−// if let prevTime = prevTime {
350−// print(now - prevTime)
351−// }
352−// prevTime = now
353−// }
354−// }()
355288}
356289
357290// MARK: Pan Gesture
358291extension GMStepper {
359− @objc func handlePan(gesture: UIPanGestureRecognizer) {
292+ func handlePan(gesture: UIPanGestureRecognizer) {
293+ leftButton.enabled = false
294+ rightButton.enabled = false
295+
360296 switch gesture.state {
361− case .began:
362− leftButton.isEnabled = false
363− rightButton.isEnabled = false
364− case .changed:
365− let translation = gesture.translation(in: label)
366− gesture.setTranslation(CGPoint.zero, in: label)
297+ case .Changed:
298+ var translation = gesture.translationInView(label)
299+ gesture.setTranslation(CGPointZero, inView: label)
367300
368− let slidingRight = gesture.velocity(in: label).x > 0
369− let slidingLeft = gesture.velocity(in: label).x < 0
301+ var slidingRight = gesture.velocityInView(label).x > 0
302+ var slidingLeft = gesture.velocityInView(label).x < 0
370303
371304 // Move the label with pan
372305 if slidingRight {
@@ -399,23 +332,22 @@ extension GMStepper {
399332 self.rightButton.backgroundColor = self.buttonsBackgroundColor
400333 self.leftButton.backgroundColor = self.buttonsBackgroundColor
401334 }
402− case .ended, .cancelled, .failed:
335+
336+ case .Ended:
403337 reset()
404338 default:
405339 break
406340 }
407341 }
408342
409− @objc func reset() {
343+ func reset() {
410344 panState = .Stable
411345 stepperState = .Stable
412346 resetTimer()
347+ leftButton.enabled = true
348+ rightButton.enabled = true
413349
414− leftButton.isEnabled = true
415− rightButton.isEnabled = true
416− label.isUserInteractionEnabled = true
417−
418− UIView.animate(withDuration: self.labelSlideDuration, animations: {
350+ UIView.animateWithDuration(self.labelSlideDuration, animations: {
419351 self.label.center = self.labelOriginalCenter
420352 self.rightButton.backgroundColor = self.buttonsBackgroundColor
421353 self.leftButton.backgroundColor = self.buttonsBackgroundColor
@@ -425,9 +357,9 @@ extension GMStepper {
425357
426358// MARK: Button Events
427359extension GMStepper {
428− @objc func leftButtonTouchDown(button: UIButton) {
429− rightButton.isEnabled = false
430− label.isUserInteractionEnabled = false
360+ func leftButtonTouchDown(button: UIButton) {
361+ rightButton.enabled = false
362+ label.userInteractionEnabled = false
431363 resetTimer()
432364
433365 if value == minimumValue {
@@ -439,9 +371,9 @@ extension GMStepper {
439371
440372 }
441373
442− @objc func rightButtonTouchDown(button: UIButton) {
443− leftButton.isEnabled = false
444− label.isUserInteractionEnabled = false
374+ func rightButtonTouchDown(button: UIButton) {
375+ leftButton.enabled = false
376+ label.userInteractionEnabled = false
445377 resetTimer()
446378
447379 if value == maximumValue {
@@ -452,8 +384,9 @@ extension GMStepper {
452384 }
453385 }
454386
455− @objc func buttonTouchUp(button: UIButton) {
387+ func buttonTouchUp(button: UIButton) {
456388 reset()
389+ label.userInteractionEnabled = true
457390 }
458391}
459392
@@ -461,20 +394,20 @@ extension GMStepper {
461394extension GMStepper {
462395
463396 func animateSlideLeft() {
464− UIView.animate(withDuration: labelSlideDuration) {
397+ UIView.animateWithDuration(labelSlideDuration) {
465398 self.label.center.x -= self.labelSlideLength
466399 }
467400 }
468401
469402 func animateSlideRight() {
470− UIView.animate(withDuration: labelSlideDuration) {
403+ UIView.animateWithDuration(labelSlideDuration) {
471404 self.label.center.x += self.labelSlideLength
472405 }
473406 }
474407
475408 func animateToOriginalPosition() {
476409 if self.label.center != self.labelOriginalCenter {
477− UIView.animate(withDuration: labelSlideDuration) {
410+ UIView.animateWithDuration(labelSlideDuration) {
478411 self.label.center = self.labelOriginalCenter
479412 }
480413 }
@@ -482,14 +415,14 @@ extension GMStepper {
482415
483416 func animateLimitHitIfNeeded() {
484417 if value == minimumValue {
485− animateLimitHitForButton(button: leftButton)
418+ animateLimitHitForButton(leftButton)
486419 } else if value == maximumValue {
487− animateLimitHitForButton(button: rightButton)
420+ animateLimitHitForButton(rightButton)
488421 }
489422 }
490423
491424 func animateLimitHitForButton(button: UIButton){
492− UIView.animate(withDuration: limitHitAnimationDuration) {
425+ UIView.animateWithDuration(limitHitAnimationDuration) {
493426 button.backgroundColor = self.limitHitAnimationColor
494427 }
495428 }
@@ -497,7 +430,7 @@ extension GMStepper {
497430
498431// MARK: Timer
499432extension GMStepper {
500− @objc func handleTimerFire(timer: Timer) {
433+ func handleTimerFire(timer: NSTimer) {
501434 timerFireCount += 1
502435
503436 if timerFireCount % timerFireCountModulo == 0 {
@@ -506,7 +439,7 @@ extension GMStepper {
506439 }
507440
508441 func scheduleTimer() {
509− timer = Timer.scheduledTimer(timeInterval: timerInterval, target: self, selector: #selector(GMStepper.handleTimerFire), userInfo: nil, repeats: true)
442+ timer = NSTimer.scheduledTimerWithTimeInterval(timerInterval, target: self, selector: "handleTimerFire:", userInfo: nil, repeats: true)
510443 }
511444
512445 func resetTimer() {
@@ -518,4 +451,4 @@ extension GMStepper {
518451 }
519452
520453
521−}
454+}