@@ -11,79 +11,72 @@ 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
5952 /// 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
6154
62− /// Text on the left button. Be sure that it fits in the button. Defaults to "−".
63− @objc @IBInspectable public var leftButtonText: String = "−" {
55+ /// Text on the left button. Be sure that it fits in the button. Defaults to "-".
56+ @IBInspectable public var leftButtonText: String = "-" {
6457 didSet {
65− leftButton.setTitle(leftButtonText, for: .normal)
58+ leftButton.setTitle(leftButtonText, forState: .Normal)
6659 }
6760 }
6861
6962 /// 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 = "+" {
7164 didSet {
72− rightButton.setTitle(rightButtonText, for: .normal)
65+ rightButton.setTitle(rightButtonText, forState: .Normal)
7366 }
7467 }
7568
7669 /// 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() {
7871 didSet {
7972 for button in [leftButton, rightButton] {
80− button.setTitleColor(buttonsTextColor, for: .normal)
73+ button.setTitleColor(buttonsTextColor, forState: .Normal)
8174 }
8275 }
8376 }
8477
8578 /// 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) {
8780 didSet {
8881 for button in [leftButton, rightButton] {
8982 button.backgroundColor = buttonsBackgroundColor
@@ -93,7 +86,7 @@ import UIKit
9386 }
9487
9588 /// 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)! {
9790 didSet {
9891 for button in [leftButton, rightButton] {
9992 button.titleLabel?.font = buttonsFont
@@ -102,59 +95,36 @@ import UIKit
10295 }
10396
10497 /// 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() {
10699 didSet {
107100 label.textColor = labelTextColor
108101 }
109102 }
110103
111104 /// 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) {
113106 didSet {
114107 label.backgroundColor = labelBackgroundColor
115108 }
116109 }
117110
118111 /// 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)! {
120113 didSet {
121114 label.font = labelFont
122115 }
123116 }
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− }
131117
132118 /// 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 {
134120 didSet {
135121 layer.cornerRadius = cornerRadius
136122 clipsToBounds = true
137123 }
138124 }
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− }
155125
156126 /// 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 {
127+ @IBInspectable public var labelWidthWeight: CGFloat = 0.5 {
158128 didSet {
159129 labelWidthWeight = min(1, max(0, labelWidthWeight))
160130 setNeedsLayout()
@@ -162,7 +132,7 @@ import UIKit
162132 }
163133
164134 /// 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)
135+ @IBInspectable public var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
166136
167137 /**
168138 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 +140,38 @@ import UIKit
170140 let labelSlideLength: CGFloat = 5
171141
172142 /// Duration of the sliding animation
173− let labelSlideDuration = TimeInterval(0.1)
143+ let labelSlideDuration = NSTimeInterval(0.1)
174144
175145 /// Duration of the animation when the value hits the limit.
176− let limitHitAnimationDuration = TimeInterval(0.1)
146+ let limitHitAnimationDuration = NSTimeInterval(0.1)
177147
178148 lazy var leftButton: UIButton = {
179149 let button = UIButton()
180− button.setTitle(self.leftButtonText, for: .normal)
181− button.setTitleColor(self.buttonsTextColor, for: .normal)
150+ button.setTitle(self.leftButtonText, forState: .Normal)
151+ button.setTitleColor(self.buttonsTextColor, forState: .Normal)
182152 button.backgroundColor = self.buttonsBackgroundColor
183153 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)
154+ button.addTarget(self, action: "leftButtonTouchDown:", forControlEvents: .TouchDown)
155+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
156+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
188157 return button
189158 }()
190159
191160 lazy var rightButton: UIButton = {
192161 let button = UIButton()
193− button.setTitle(self.rightButtonText, for: .normal)
194− button.setTitleColor(self.buttonsTextColor, for: .normal)
162+ button.setTitle(self.rightButtonText, forState: .Normal)
163+ button.setTitleColor(self.buttonsTextColor, forState: .Normal)
195164 button.backgroundColor = self.buttonsBackgroundColor
196165 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)
166+ button.addTarget(self, action: "rightButtonTouchDown:", forControlEvents: .TouchDown)
167+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
168+ button.addTarget(self, action: "buttonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
201169 return button
202170 }()
203171
204172 lazy var label: UILabel = {
205173 let label = UILabel()
206− label.textAlignment = .center
174+ label.textAlignment = .Center
207175 if self.showIntegerIfDoubleIsInteger && floor(self.value) == self.value {
208176 label.text = String(stringInterpolationSegment: Int(self.value))
209177 } else {
@@ -212,10 +180,8 @@ import UIKit
212180 label.textColor = self.labelTextColor
213181 label.backgroundColor = self.labelBackgroundColor
214182 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))
183+ label.userInteractionEnabled = true
184+ let panRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
219185 panRecognizer.maximumNumberOfTouches = 1
220186 label.addGestureRecognizer(panRecognizer)
221187 return label
@@ -243,33 +209,9 @@ import UIKit
243209 }
244210 }
245211 }
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− }
270212
271213 /// Timer used for autorepeat option
272− var timer: Timer?
214+ var timer: NSTimer?
273215
274216 /** When UIStepper reaches its top speed, it alters the value with a time interval of ~0.05 sec.
275217 The user pressing and holding on the stepper repeatedly:
@@ -277,7 +219,7 @@ import UIKit
277219 - For the next 1.5 sec, it changes the value every 0.1 sec.
278220 - Then, every 0.05 sec.
279221 */
280− let timerInterval = TimeInterval(0.05)
222+ let timerInterval = NSTimeInterval(0.05)
281223
282224 /// 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.
283225 var timerFireCount = 0
@@ -291,12 +233,25 @@ import UIKit
291233 }
292234 }
293235
294− @objc required public init?(coder aDecoder: NSCoder) {
236+ /// Useful for logging the timer interval. You can call this in the timer handler to test the autorepeat option.
237+ lazy var printTimerGaps: () -> () = {
238+ var prevTime: CFAbsoluteTime?
239+
240+ return { _ in
241+ var now = CFAbsoluteTimeGetCurrent()
242+ if let prevTime = prevTime {
243+ println(now - prevTime)
244+ }
245+ prevTime = now
246+ }
247+ }()
248+
249+ required public init(coder aDecoder: NSCoder) {
295250 super.init(coder: aDecoder)
296251 setup()
297252 }
298253
299− @objc public override init(frame: CGRect) {
254+ public override init(frame: CGRect) {
300255 super.init(frame: frame)
301256 setup()
302257 }
@@ -309,9 +264,6 @@ import UIKit
309264 backgroundColor = buttonsBackgroundColor
310265 layer.cornerRadius = cornerRadius
311266 clipsToBounds = true
312− labelOriginalCenter = label.center
313−
314− NotificationCenter.default.addObserver(self, selector: #selector(GMStepper.reset), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
315267 }
316268
317269 public override func layoutSubviews() {
@@ -334,39 +286,21 @@ import UIKit
334286 value -= stepValue
335287 }
336288 }
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−// }()
355289}
356290
357291// MARK: Pan Gesture
358292extension GMStepper {
359− @objc func handlePan(gesture: UIPanGestureRecognizer) {
293+ func handlePan(gesture: UIPanGestureRecognizer) {
294+ leftButton.enabled = false
295+ rightButton.enabled = false
296+
360297 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)
298+ case .Changed:
299+ var translation = gesture.translationInView(label)
300+ gesture.setTranslation(CGPointZero, inView: label)
367301
368− let slidingRight = gesture.velocity(in: label).x > 0
369− let slidingLeft = gesture.velocity(in: label).x < 0
302+ var slidingRight = gesture.velocityInView(label).x > 0
303+ var slidingLeft = gesture.velocityInView(label).x < 0
370304
371305 // Move the label with pan
372306 if slidingRight {
@@ -399,23 +333,22 @@ extension GMStepper {
399333 self.rightButton.backgroundColor = self.buttonsBackgroundColor
400334 self.leftButton.backgroundColor = self.buttonsBackgroundColor
401335 }
402− case .ended, .cancelled, .failed:
336+
337+ case .Ended:
403338 reset()
404339 default:
405340 break
406341 }
407342 }
408343
409− @objc func reset() {
344+ func reset() {
410345 panState = .Stable
411346 stepperState = .Stable
412347 resetTimer()
348+ leftButton.enabled = true
349+ rightButton.enabled = true
413350
414− leftButton.isEnabled = true
415− rightButton.isEnabled = true
416− label.isUserInteractionEnabled = true
417−
418− UIView.animate(withDuration: self.labelSlideDuration, animations: {
351+ UIView.animateWithDuration(self.labelSlideDuration, animations: {
419352 self.label.center = self.labelOriginalCenter
420353 self.rightButton.backgroundColor = self.buttonsBackgroundColor
421354 self.leftButton.backgroundColor = self.buttonsBackgroundColor
@@ -425,9 +358,9 @@ extension GMStepper {
425358
426359// MARK: Button Events
427360extension GMStepper {
428− @objc func leftButtonTouchDown(button: UIButton) {
429− rightButton.isEnabled = false
430− label.isUserInteractionEnabled = false
361+ func leftButtonTouchDown(button: UIButton) {
362+ rightButton.enabled = false
363+ label.userInteractionEnabled = false
431364 resetTimer()
432365
433366 if value == minimumValue {
@@ -439,9 +372,9 @@ extension GMStepper {
439372
440373 }
441374
442− @objc func rightButtonTouchDown(button: UIButton) {
443− leftButton.isEnabled = false
444− label.isUserInteractionEnabled = false
375+ func rightButtonTouchDown(button: UIButton) {
376+ leftButton.enabled = false
377+ label.userInteractionEnabled = false
445378 resetTimer()
446379
447380 if value == maximumValue {
@@ -452,8 +385,9 @@ extension GMStepper {
452385 }
453386 }
454387
455− @objc func buttonTouchUp(button: UIButton) {
388+ func buttonTouchUp(button: UIButton) {
456389 reset()
390+ label.userInteractionEnabled = true
457391 }
458392}
459393
@@ -461,20 +395,20 @@ extension GMStepper {
461395extension GMStepper {
462396
463397 func animateSlideLeft() {
464− UIView.animate(withDuration: labelSlideDuration) {
398+ UIView.animateWithDuration(labelSlideDuration) {
465399 self.label.center.x -= self.labelSlideLength
466400 }
467401 }
468402
469403 func animateSlideRight() {
470− UIView.animate(withDuration: labelSlideDuration) {
404+ UIView.animateWithDuration(labelSlideDuration) {
471405 self.label.center.x += self.labelSlideLength
472406 }
473407 }
474408
475409 func animateToOriginalPosition() {
476410 if self.label.center != self.labelOriginalCenter {
477− UIView.animate(withDuration: labelSlideDuration) {
411+ UIView.animateWithDuration(labelSlideDuration) {
478412 self.label.center = self.labelOriginalCenter
479413 }
480414 }
@@ -482,14 +416,14 @@ extension GMStepper {
482416
483417 func animateLimitHitIfNeeded() {
484418 if value == minimumValue {
485− animateLimitHitForButton(button: leftButton)
419+ animateLimitHitForButton(leftButton)
486420 } else if value == maximumValue {
487− animateLimitHitForButton(button: rightButton)
421+ animateLimitHitForButton(rightButton)
488422 }
489423 }
490424
491425 func animateLimitHitForButton(button: UIButton){
492− UIView.animate(withDuration: limitHitAnimationDuration) {
426+ UIView.animateWithDuration(limitHitAnimationDuration) {
493427 button.backgroundColor = self.limitHitAnimationColor
494428 }
495429 }
@@ -497,7 +431,7 @@ extension GMStepper {
497431
498432// MARK: Timer
499433extension GMStepper {
500− @objc func handleTimerFire(timer: Timer) {
434+ func handleTimerFire(timer: NSTimer) {
501435 timerFireCount += 1
502436
503437 if timerFireCount % timerFireCountModulo == 0 {
@@ -506,7 +440,7 @@ extension GMStepper {
506440 }
507441
508442 func scheduleTimer() {
509− timer = Timer.scheduledTimer(timeInterval: timerInterval, target: self, selector: #selector(GMStepper.handleTimerFire), userInfo: nil, repeats: true)
443+ timer = NSTimer.scheduledTimerWithTimeInterval(timerInterval, target: self, selector: "handleTimerFire:", userInfo: nil, repeats: true)
510444 }
511445
512446 func resetTimer() {
@@ -518,4 +452,4 @@ extension GMStepper {
518452 }
519453
520454
521−}
455+}