on 8789187 help sign in
16 files changed+334−533
since splitsnapshots
unifiedsplit
.gitignore−2 .swift-version−1 GMStepper.podspec+2−2 GMStepper/GMStepper.swift+147−266 GMStepperExample/GMStepperExample.xcodeproj/project.pbxproj+109−136 GMStepperExample/GMStepperExample/AppDelegate.swift+10−10 GMStepperExample/GMStepperExample/Base.lproj/LaunchScreen.xib+2−6 GMStepperExample/GMStepperExample/Base.lproj/Main.storyboard+43−71 GMStepperExample/GMStepperExample/Info.plist+1−1 GMStepperExample/GMStepperExample/ViewController.swift+3−3 GMStepperExample/GMStepperExampleTests/GMStepperExampleTests.swift+4−4 GMStepperExample/GMStepperExampleTests/Info.plist+3−1 README.md+10−30 Screenshots/screenshot_0.gif Screenshots/screenshot_0.png Screenshots/screenshot_1.gif
.gitignore−2
@@ -31,5 +31,3 @@ DerivedData
3131# Carthage/Checkouts
3232
3333Carthage/Build
34−
35−.DS_Store
.swift-versiondeleted−1
@@ -1 +0,0 @@
1−4.0
GMStepper.podspec+2−2
@@ -1,9 +1,9 @@
11Pod::Spec.new do |s|
22 s.name = "GMStepper"
3− s.version = "2.1"
3+ s.version = "0.2.0"
44 s.summary = "A stepper with a sliding label in the middle."
55 s.homepage = "https://github.com/gmertk/GMStepper"
6− s.screenshots = "https://raw.githubusercontent.com/gmertk/GMStepper/master/Screenshots/screenshot_1.gif"
6+ s.screenshots = "https://dl.dropboxusercontent.com/u/4397140/pod-screenshots/screenshot_1.png"
77 s.license = 'MIT'
88 s.author = { "Gunay Mert Karadogan" => "mertkaradogan@gmail.com" }
99 s.source = { :git => "https://github.com/gmertk/GMStepper.git", :tag => s.version.to_s }
GMStepper/GMStepper.swift+147−266
@@ -11,79 +11,59 @@ 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+ public var value = 0 {
1515 didSet {
1616 value = min(maximumValue, max(minimumValue, value))
17−
18− 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 {
28− label.text = String(stringInterpolationSegment: Int(value))
29− } else {
30− label.text = String(stringInterpolationSegment: value)
31− }
17+ label.text = String(value)
3218
3319 if oldValue != value {
34− sendActions(for: .valueChanged)
20+ sendActionsForControlEvents(.ValueChanged)
3521 }
3622 }
3723 }
3824
3925 /// Minimum value. Must be less than maximumValue. Defaults to 0.
40− @objc @IBInspectable public var minimumValue: Double = 0 {
26+ @IBInspectable public var minimumValue: Int = 0 {
4127 didSet {
42− value = min(maximumValue, max(minimumValue, value))
28+ value = 0
4329 }
4430 }
4531
46− /// Maximum value. Must be more than minimumValue. Defaults to 100.
47− @objc @IBInspectable public var maximumValue: Double = 100 {
32+ /// Maximum value. Must be more than minimumValue. Defaults to 10.
33+ @IBInspectable public var maximumValue: Int = 10 {
4834 didSet {
49− value = min(maximumValue, max(minimumValue, value))
35+ value = 0
5036 }
5137 }
5238
53− /// Step/Increment value as in UIStepper. Defaults to 1.
54− @objc @IBInspectable public var stepValue: Double = 1
55−
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.
57− @objc @IBInspectable public var autorepeat: Bool = true
58−
59− /// If the value is integer, it is shown without floating point.
60− @objc @IBInspectable public var showIntegerIfDoubleIsInteger: Bool = true
39+ /// The same as UIStepper's autorepeat. If true, holding on the buttons or the pan gesture repeatedly alters value. Defaults to true.
40+ @IBInspectable public var autorepeat: Bool = true
6141
62− /// Text on the left button. Be sure that it fits in the button. Defaults to "−".
63− @objc @IBInspectable public var leftButtonText: String = "−" {
42+ /// Text on the left button. Be sure that it fits in the button. Defaults to "-".
43+ @IBInspectable public var leftButtonText: String = "-" {
6444 didSet {
65− leftButton.setTitle(leftButtonText, for: .normal)
45+ leftButton.setTitle(leftButtonText, forState: .Normal)
6646 }
6747 }
6848
6949 /// Text on the right button. Be sure that it fits in the button. Defaults to "+".
70− @objc @IBInspectable public var rightButtonText: String = "+" {
50+ @IBInspectable public var rightButtonText: String = "+" {
7151 didSet {
72− rightButton.setTitle(rightButtonText, for: .normal)
52+ rightButton.setTitle(rightButtonText, forState: .Normal)
7353 }
7454 }
7555
7656 /// Text color of the buttons. Defaults to white.
77− @objc @IBInspectable public var buttonsTextColor: UIColor = UIColor.white {
57+ @IBInspectable public var buttonsTextColor: UIColor = UIColor.whiteColor() {
7858 didSet {
7959 for button in [leftButton, rightButton] {
80− button.setTitleColor(buttonsTextColor, for: .normal)
60+ button.setTitleColor(buttonsTextColor, forState: .Normal)
8161 }
8262 }
8363 }
8464
8565 /// 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) {
66+ @IBInspectable public var buttonsBackgroundColor: UIColor = UIColor(red:0.21, green:0.5, blue:0.74, alpha:1) {
8767 didSet {
8868 for button in [leftButton, rightButton] {
8969 button.backgroundColor = buttonsBackgroundColor
@@ -93,7 +73,7 @@ import UIKit
9373 }
9474
9575 /// 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)! {
76+ public var buttonsFont = UIFont(name: "AvenirNext-Bold", size: 20.0)! {
9777 didSet {
9878 for button in [leftButton, rightButton] {
9979 button.titleLabel?.font = buttonsFont
@@ -102,174 +82,70 @@ import UIKit
10282 }
10383
10484 /// Text color of the middle label. Defaults to white.
105− @objc @IBInspectable public var labelTextColor: UIColor = UIColor.white {
85+ @IBInspectable public var labelTextColor: UIColor = UIColor.whiteColor() {
10686 didSet {
10787 label.textColor = labelTextColor
10888 }
10989 }
11090
11191 /// 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) {
92+ @IBInspectable public var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1) {
11393 didSet {
11494 label.backgroundColor = labelBackgroundColor
11595 }
11696 }
11797
11898 /// 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)! {
99+ public var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)! {
120100 didSet {
121101 label.font = labelFont
122102 }
123103 }
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− }
131104
132105 /// Corner radius of the stepper's layer. Defaults to 4.0.
133− @objc @IBInspectable public var cornerRadius: CGFloat = 4.0 {
106+ @IBInspectable public var cornerRadius: CGFloat = 4.0 {
134107 didSet {
135108 layer.cornerRadius = cornerRadius
136109 clipsToBounds = true
137110 }
138111 }
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− }
155112
156113 /// 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 {
114+ @IBInspectable public var labelWidthWeight: CGFloat = 0.5 {
158115 didSet {
159116 labelWidthWeight = min(1, max(0, labelWidthWeight))
160117 setNeedsLayout()
161118 }
162119 }
163120
164− /// 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)
166−
167121 /**
168122 Width of the sliding animation. When buttons clicked, the middle label does a slide animation towards to the clicked button. Defaults to 5.
169123 */
170− let labelSlideLength: CGFloat = 5
124+ private let labelSlideLength: CGFloat = 5
171125
172126 /// Duration of the sliding animation
173− let labelSlideDuration = TimeInterval(0.1)
174−
175− /// Duration of the animation when the value hits the limit.
176− let limitHitAnimationDuration = TimeInterval(0.1)
177−
178− lazy var leftButton: UIButton = {
179− let button = UIButton()
180− button.setTitle(self.leftButtonText, for: .normal)
181− button.setTitleColor(self.buttonsTextColor, for: .normal)
182− button.backgroundColor = self.buttonsBackgroundColor
183− 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)
188− return button
189− }()
127+ private let labelSlideDuration = NSTimeInterval(0.1)
190128
191− lazy var rightButton: UIButton = {
192− let button = UIButton()
193− button.setTitle(self.rightButtonText, for: .normal)
194− button.setTitleColor(self.buttonsTextColor, for: .normal)
195− button.backgroundColor = self.buttonsBackgroundColor
196− 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)
201− return button
202− }()
129+ /// Duration of the flashing animation when the value hits the limit.
130+ private let limitHitAnimationDuration = NSTimeInterval(0.1)
203131
204− lazy var label: UILabel = {
205− let label = UILabel()
206− label.textAlignment = .center
207− if self.showIntegerIfDoubleIsInteger && floor(self.value) == self.value {
208− label.text = String(stringInterpolationSegment: Int(self.value))
209− } else {
210− label.text = String(stringInterpolationSegment: self.value)
211− }
212− label.textColor = self.labelTextColor
213− label.backgroundColor = self.labelBackgroundColor
214− 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))
219− panRecognizer.maximumNumberOfTouches = 1
220− label.addGestureRecognizer(panRecognizer)
221− return label
222− }()
132+ /// Color of the flashing animation on the buttons in case the value hit the limit.
133+ @IBInspectable public var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
223134
224− var labelOriginalCenter: CGPoint!
225− var labelMaximumCenterX: CGFloat!
226− var labelMinimumCenterX: CGFloat!
135+ private let leftButton = UIButton()
136+ private let rightButton = UIButton()
137+ private let label = UILabel()
227138
228− enum LabelPanState {
229− case Stable, HitRightEdge, HitLeftEdge
230− }
231− var panState = LabelPanState.Stable
139+ private var labelOriginalCenter: CGPoint!
140+ private var labelMaximumCenterX: CGFloat!
141+ private var labelMinimumCenterX: CGFloat!
232142
233− enum StepperState {
234− case Stable, ShouldIncrease, ShouldDecrease
235− }
236− var stepperState = StepperState.Stable {
237− didSet {
238− if stepperState != .Stable {
239− updateValue()
240− if autorepeat {
241− scheduleTimer()
242− }
243− }
244− }
245− }
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− }
143+ private enum LabelPanState {
144+ case Stale, HitRightEdge, HitLeftEdge
269145 }
146+ private var panState = LabelPanState.Stale
270147
271− /// Timer used for autorepeat option
272− var timer: Timer?
148+ private var timer: NSTimer?
273149
274150 /** When UIStepper reaches its top speed, it alters the value with a time interval of ~0.05 sec.
275151 The user pressing and holding on the stepper repeatedly:
@@ -277,11 +153,11 @@ import UIKit
277153 - For the next 1.5 sec, it changes the value every 0.1 sec.
278154 - Then, every 0.05 sec.
279155 */
280− let timerInterval = TimeInterval(0.05)
156+ private let timerInterval = NSTimeInterval(0.05)
281157
282158 /// 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
284− var timerFireCountModulo: Int {
159+ private var timerFireCount = 0
160+ private var timerFireCountModulo: Int {
285161 if timerFireCount > 80 {
286162 return 1 // 0.05 sec * 1 = 0.05 sec
287163 } else if timerFireCount > 50 {
@@ -291,27 +167,61 @@ import UIKit
291167 }
292168 }
293169
294− @objc required public init?(coder aDecoder: NSCoder) {
170+ lazy var printTimerGaps: () -> () = {
171+ var prevTime: CFAbsoluteTime?
172+
173+ return { _ in
174+ var now = CFAbsoluteTimeGetCurrent()
175+ if let prevTime = prevTime {
176+ println(now - prevTime)
177+ }
178+ prevTime = now
179+ }
180+ }()
181+
182+ required public init(coder aDecoder: NSCoder) {
295183 super.init(coder: aDecoder)
296184 setup()
297185 }
298186
299− @objc public override init(frame: CGRect) {
187+ public override init(frame: CGRect) {
300188 super.init(frame: frame)
301189 setup()
302190 }
303191
304− func setup() {
192+ private func setup() {
193+ leftButton.setTitle(leftButtonText, forState: .Normal)
194+ leftButton.setTitleColor(buttonsTextColor, forState: .Normal)
195+ leftButton.backgroundColor = buttonsBackgroundColor
196+ leftButton.titleLabel?.font = buttonsFont
197+ leftButton.addTarget(self, action: "leftButtonTouchDown:", forControlEvents: .TouchDown)
198+ leftButton.addTarget(self, action: "leftButtonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
199+ leftButton.addTarget(self, action: "leftButtonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
305200 addSubview(leftButton)
201+
202+ rightButton.setTitle(rightButtonText, forState: .Normal)
203+ rightButton.setTitleColor(buttonsTextColor, forState: .Normal)
204+ rightButton.backgroundColor = buttonsBackgroundColor
205+ rightButton.titleLabel?.font = buttonsFont
206+ rightButton.addTarget(self, action: "rightButtonTapped:", forControlEvents: .TouchDown)
207+ rightButton.addTarget(self, action: "rightButtonTouchUp:", forControlEvents: UIControlEvents.TouchUpInside)
208+ rightButton.addTarget(self, action: "rightButtonTouchUp:", forControlEvents: UIControlEvents.TouchUpOutside)
306209 addSubview(rightButton)
210+
211+ label.textAlignment = .Center
212+ label.text = String(value)
213+ label.textColor = labelTextColor
214+ label.backgroundColor = labelBackgroundColor
215+ label.font = labelFont
307216 addSubview(label)
308217
309218 backgroundColor = buttonsBackgroundColor
310219 layer.cornerRadius = cornerRadius
311220 clipsToBounds = true
312− labelOriginalCenter = label.center
313221
314− NotificationCenter.default.addObserver(self, selector: #selector(GMStepper.reset), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
222+ let panRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
223+ label.userInteractionEnabled = true
224+ label.addGestureRecognizer(panRecognizer)
315225 }
316226
317227 public override func layoutSubviews() {
@@ -327,46 +237,16 @@ import UIKit
327237 labelOriginalCenter = label.center
328238 }
329239
330− func updateValue() {
331− if stepperState == .ShouldIncrease {
332− value += stepValue
333− } else if stepperState == .ShouldDecrease {
334− value -= stepValue
335− }
336− }
337−
338− deinit {
339− resetTimer()
340− NotificationCenter.default.removeObserver(self)
341− }
342240
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−// }()
355−}
356241
357−// MARK: Pan Gesture
358−extension GMStepper {
359− @objc func handlePan(gesture: UIPanGestureRecognizer) {
242+ @objc private func handlePan(gesture: UIPanGestureRecognizer) {
360243 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)
244+ case .Changed:
245+ var translation = gesture.translationInView(label)
246+ gesture.setTranslation(CGPointZero, inView: label)
367247
368− let slidingRight = gesture.velocity(in: label).x > 0
369− let slidingLeft = gesture.velocity(in: label).x < 0
248+ var slidingRight = gesture.velocityInView(label).x > 0
249+ var slidingLeft = gesture.velocityInView(label).x < 0
370250
371251 // Move the label with pan
372252 if slidingRight {
@@ -377,45 +257,44 @@ extension GMStepper {
377257
378258 // When the label hits the edges, increase/decrease value and change button backgrounds
379259 if label.center.x == labelMaximumCenterX {
380− // If not hit the right edge before, increase the value and start the timer. If already hit the edge, do nothing. Timer will handle it.
260+
261+ // Increase only once for each pan gesture
381262 if panState != .HitRightEdge {
382− stepperState = .ShouldIncrease
263+ value += 1
264+ scheduleTimerWithUserInfo(rightButton)
383265 panState = .HitRightEdge
384266 }
385−
386− animateLimitHitIfNeeded()
267+
268+ if value == maximumValue {
269+ animateLimitHitForButton(rightButton)
270+ }
387271 } else if label.center.x == labelMinimumCenterX {
272+
388273 if panState != .HitLeftEdge {
389− stepperState = .ShouldDecrease
274+ value -= 1
275+ scheduleTimerWithUserInfo(leftButton)
390276 panState = .HitLeftEdge
391277 }
392278
393− animateLimitHitIfNeeded()
279+ if value == minimumValue {
280+ animateLimitHitForButton(leftButton)
281+ }
394282 } else {
395− panState = .Stable
396− stepperState = .Stable
397− resetTimer()
398−
399− self.rightButton.backgroundColor = self.buttonsBackgroundColor
400− self.leftButton.backgroundColor = self.buttonsBackgroundColor
283+ reset()
401284 }
402− case .ended, .cancelled, .failed:
285+
286+ case .Ended:
403287 reset()
404288 default:
405289 break
406290 }
407291 }
408292
409− @objc func reset() {
410− panState = .Stable
411− stepperState = .Stable
293+ private func reset() {
294+ panState = .Stale
412295 resetTimer()
413296
414− leftButton.isEnabled = true
415− rightButton.isEnabled = true
416− label.isUserInteractionEnabled = true
417−
418− UIView.animate(withDuration: self.labelSlideDuration, animations: {
297+ UIView.animateWithDuration(self.labelSlideDuration, animations: {
419298 self.label.center = self.labelOriginalCenter
420299 self.rightButton.backgroundColor = self.buttonsBackgroundColor
421300 self.leftButton.backgroundColor = self.buttonsBackgroundColor
@@ -425,88 +304,90 @@ extension GMStepper {
425304
426305// MARK: Button Events
427306extension GMStepper {
428− @objc func leftButtonTouchDown(button: UIButton) {
429− rightButton.isEnabled = false
430− label.isUserInteractionEnabled = false
431− resetTimer()
432−
307+ @objc private func leftButtonTouchDown(button: UIButton) {
433308 if value == minimumValue {
434− animateLimitHitIfNeeded()
309+ animateLimitHitForButton(leftButton)
435310 } else {
436− stepperState = .ShouldDecrease
311+ value -= 1
312+ if autorepeat {
313+ scheduleTimerWithUserInfo(leftButton)
314+ }
437315 animateSlideLeft()
438316 }
439−
440317 }
441318
442− @objc func rightButtonTouchDown(button: UIButton) {
443− leftButton.isEnabled = false
444− label.isUserInteractionEnabled = false
445− resetTimer()
319+ @objc private func leftButtonTouchUp(button: UIButton) {
320+ reset()
321+ stopTimer()
322+ }
446323
324+ @objc private func rightButtonTapped(button: UIButton) {
447325 if value == maximumValue {
448− animateLimitHitIfNeeded()
326+ animateLimitHitForButton(rightButton)
449327 } else {
450− stepperState = .ShouldIncrease
328+ value += 1
329+ if autorepeat {
330+ scheduleTimerWithUserInfo(rightButton)
331+ }
451332 animateSlideRight()
452333 }
453334 }
454335
455− @objc func buttonTouchUp(button: UIButton) {
336+ @objc private func rightButtonTouchUp(button: UIButton) {
456337 reset()
338+ stopTimer()
457339 }
458340}
459341
460342// MARK: Animations
461343extension GMStepper {
462344
463− func animateSlideLeft() {
464− UIView.animate(withDuration: labelSlideDuration) {
345+ private func animateSlideLeft() {
346+ UIView.animateWithDuration(labelSlideDuration) {
465347 self.label.center.x -= self.labelSlideLength
466348 }
467349 }
468350
469− func animateSlideRight() {
470− UIView.animate(withDuration: labelSlideDuration) {
351+ private func animateSlideRight() {
352+ UIView.animateWithDuration(labelSlideDuration) {
471353 self.label.center.x += self.labelSlideLength
472354 }
473355 }
474356
475− func animateToOriginalPosition() {
357+ private func animateToOriginalPosition() {
476358 if self.label.center != self.labelOriginalCenter {
477− UIView.animate(withDuration: labelSlideDuration) {
359+ UIView.animateWithDuration(labelSlideDuration) {
478360 self.label.center = self.labelOriginalCenter
479361 }
480362 }
481363 }
482364
483− func animateLimitHitIfNeeded() {
484− if value == minimumValue {
485− animateLimitHitForButton(button: leftButton)
486− } else if value == maximumValue {
487− animateLimitHitForButton(button: rightButton)
488− }
489− }
490−
491− func animateLimitHitForButton(button: UIButton){
492− UIView.animate(withDuration: limitHitAnimationDuration) {
365+ private func animateLimitHitForButton(button: UIButton){
366+ UIView.animateWithDuration(limitHitAnimationDuration) {
493367 button.backgroundColor = self.limitHitAnimationColor
494368 }
495369 }
370+
496371}
497372
498373// MARK: Timer
499374extension GMStepper {
500− @objc func handleTimerFire(timer: Timer) {
375+ func handleTimerFire(timer: NSTimer) {
501376 timerFireCount += 1
502−
503377 if timerFireCount % timerFireCountModulo == 0 {
504− updateValue()
378+
379+ if let button = timer.userInfo as? UIButton {
380+ if button == leftButton {
381+ value -= 1
382+ } else {
383+ value += 1
384+ }
385+ }
505386 }
506387 }
507388
508− func scheduleTimer() {
509− timer = Timer.scheduledTimer(timeInterval: timerInterval, target: self, selector: #selector(GMStepper.handleTimerFire), userInfo: nil, repeats: true)
389+ func scheduleTimerWithUserInfo(userInfo: AnyObject?) {
390+ timer = NSTimer.scheduledTimerWithTimeInterval(timerInterval, target: self, selector: "handleTimerFire:", userInfo: userInfo, repeats: true)
510391 }
511392
512393 func resetTimer() {
@@ -518,4 +399,4 @@ extension GMStepper {
518399 }
519400
520401
521−}
402+}
GMStepperExample/GMStepperExample.xcodeproj/project.pbxproj+109−136
@@ -7,18 +7,18 @@
77 objects = {
88
99/* Begin PBXBuildFile section */
10− 3116C0DB1DA4DD360015AC69 /* GMStepperExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3116C0DA1DA4DD360015AC69 /* GMStepperExampleTests.swift */; };
11− 3198AC771DA4DEE500311FB3 /* GMStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C195B1B48445E005EFEE5 /* GMStepper.swift */; };
10+ 3169DD3E1B496C33009791D1 /* GMStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C195B1B48445E005EFEE5 /* GMStepper.swift */; };
1211 319C19381B4843EB005EFEE5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C19371B4843EB005EFEE5 /* AppDelegate.swift */; };
1312 319C193A1B4843EB005EFEE5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C19391B4843EB005EFEE5 /* ViewController.swift */; };
1413 319C193D1B4843EB005EFEE5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 319C193B1B4843EB005EFEE5 /* Main.storyboard */; };
1514 319C193F1B4843EB005EFEE5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 319C193E1B4843EB005EFEE5 /* Images.xcassets */; };
1615 319C19421B4843EB005EFEE5 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 319C19401B4843EB005EFEE5 /* LaunchScreen.xib */; };
16+ 319C194E1B4843EB005EFEE5 /* GMStepperExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C194D1B4843EB005EFEE5 /* GMStepperExampleTests.swift */; };
1717 319C195C1B48445E005EFEE5 /* GMStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C195B1B48445E005EFEE5 /* GMStepper.swift */; };
1818/* End PBXBuildFile section */
1919
2020/* Begin PBXContainerItemProxy section */
21− 3116C0DD1DA4DD360015AC69 /* PBXContainerItemProxy */ = {
21+ 319C19481B4843EB005EFEE5 /* PBXContainerItemProxy */ = {
2222 isa = PBXContainerItemProxy;
2323 containerPortal = 319C192A1B4843EB005EFEE5 /* Project object */;
2424 proxyType = 1;
@@ -28,9 +28,6 @@
2828/* End PBXContainerItemProxy section */
2929
3030/* Begin PBXFileReference section */
31− 3116C0D81DA4DD360015AC69 /* GMStepperExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GMStepperExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
32− 3116C0DA1DA4DD360015AC69 /* GMStepperExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GMStepperExampleTests.swift; sourceTree = "<group>"; };
33− 3116C0DC1DA4DD360015AC69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3431 319C19321B4843EB005EFEE5 /* GMStepperExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GMStepperExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
3532 319C19361B4843EB005EFEE5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3633 319C19371B4843EB005EFEE5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -38,18 +35,21 @@
3835 319C193C1B4843EB005EFEE5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
3936 319C193E1B4843EB005EFEE5 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
4037 319C19411B4843EB005EFEE5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
38+ 319C19471B4843EB005EFEE5 /* GMStepperExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GMStepperExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
39+ 319C194C1B4843EB005EFEE5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
40+ 319C194D1B4843EB005EFEE5 /* GMStepperExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GMStepperExampleTests.swift; sourceTree = "<group>"; };
4141 319C195B1B48445E005EFEE5 /* GMStepper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GMStepper.swift; sourceTree = "<group>"; };
4242/* End PBXFileReference section */
4343
4444/* Begin PBXFrameworksBuildPhase section */
45− 3116C0D51DA4DD360015AC69 /* Frameworks */ = {
45+ 319C192F1B4843EB005EFEE5 /* Frameworks */ = {
4646 isa = PBXFrameworksBuildPhase;
4747 buildActionMask = 2147483647;
4848 files = (
4949 );
5050 runOnlyForDeploymentPostprocessing = 0;
5151 };
52− 319C192F1B4843EB005EFEE5 /* Frameworks */ = {
52+ 319C19441B4843EB005EFEE5 /* Frameworks */ = {
5353 isa = PBXFrameworksBuildPhase;
5454 buildActionMask = 2147483647;
5555 files = (
@@ -59,21 +59,12 @@
5959/* End PBXFrameworksBuildPhase section */
6060
6161/* Begin PBXGroup section */
62− 3116C0D91DA4DD360015AC69 /* GMStepperExampleTests */ = {
63− isa = PBXGroup;
64− children = (
65− 3116C0DA1DA4DD360015AC69 /* GMStepperExampleTests.swift */,
66− 3116C0DC1DA4DD360015AC69 /* Info.plist */,
67− );
68− path = GMStepperExampleTests;
69− sourceTree = "<group>";
70− };
7162 319C19291B4843EB005EFEE5 = {
7263 isa = PBXGroup;
7364 children = (
7465 319C195A1B48445E005EFEE5 /* GMStepper */,
7566 319C19341B4843EB005EFEE5 /* GMStepperExample */,
76− 3116C0D91DA4DD360015AC69 /* GMStepperExampleTests */,
67+ 319C194A1B4843EB005EFEE5 /* GMStepperExampleTests */,
7768 319C19331B4843EB005EFEE5 /* Products */,
7869 );
7970 sourceTree = "<group>";
@@ -82,7 +73,7 @@
8273 isa = PBXGroup;
8374 children = (
8475 319C19321B4843EB005EFEE5 /* GMStepperExample.app */,
85− 3116C0D81DA4DD360015AC69 /* GMStepperExampleTests.xctest */,
76+ 319C19471B4843EB005EFEE5 /* GMStepperExampleTests.xctest */,
8677 );
8778 name = Products;
8879 sourceTree = "<group>";
@@ -108,6 +99,23 @@
10899 name = "Supporting Files";
109100 sourceTree = "<group>";
110101 };
102+ 319C194A1B4843EB005EFEE5 /* GMStepperExampleTests */ = {
103+ isa = PBXGroup;
104+ children = (
105+ 319C194D1B4843EB005EFEE5 /* GMStepperExampleTests.swift */,
106+ 319C194B1B4843EB005EFEE5 /* Supporting Files */,
107+ );
108+ path = GMStepperExampleTests;
109+ sourceTree = "<group>";
110+ };
111+ 319C194B1B4843EB005EFEE5 /* Supporting Files */ = {
112+ isa = PBXGroup;
113+ children = (
114+ 319C194C1B4843EB005EFEE5 /* Info.plist */,
115+ );
116+ name = "Supporting Files";
117+ sourceTree = "<group>";
118+ };
111119 319C195A1B48445E005EFEE5 /* GMStepper */ = {
112120 isa = PBXGroup;
113121 children = (
@@ -120,24 +128,6 @@
120128/* End PBXGroup section */
121129
122130/* Begin PBXNativeTarget section */
123− 3116C0D71DA4DD360015AC69 /* GMStepperExampleTests */ = {
124− isa = PBXNativeTarget;
125− buildConfigurationList = 3116C0DF1DA4DD360015AC69 /* Build configuration list for PBXNativeTarget "GMStepperExampleTests" */;
126− buildPhases = (
127− 3116C0D41DA4DD360015AC69 /* Sources */,
128− 3116C0D51DA4DD360015AC69 /* Frameworks */,
129− 3116C0D61DA4DD360015AC69 /* Resources */,
130− );
131− buildRules = (
132− );
133− dependencies = (
134− 3116C0DE1DA4DD360015AC69 /* PBXTargetDependency */,
135− );
136− name = GMStepperExampleTests;
137− productName = GMStepperExampleTests;
138− productReference = 3116C0D81DA4DD360015AC69 /* GMStepperExampleTests.xctest */;
139− productType = "com.apple.product-type.bundle.unit-test";
140− };
141131 319C19311B4843EB005EFEE5 /* GMStepperExample */ = {
142132 isa = PBXNativeTarget;
143133 buildConfigurationList = 319C19511B4843EB005EFEE5 /* Build configuration list for PBXNativeTarget "GMStepperExample" */;
@@ -155,27 +145,40 @@
155145 productReference = 319C19321B4843EB005EFEE5 /* GMStepperExample.app */;
156146 productType = "com.apple.product-type.application";
157147 };
148+ 319C19461B4843EB005EFEE5 /* GMStepperExampleTests */ = {
149+ isa = PBXNativeTarget;
150+ buildConfigurationList = 319C19541B4843EB005EFEE5 /* Build configuration list for PBXNativeTarget "GMStepperExampleTests" */;
151+ buildPhases = (
152+ 319C19431B4843EB005EFEE5 /* Sources */,
153+ 319C19441B4843EB005EFEE5 /* Frameworks */,
154+ 319C19451B4843EB005EFEE5 /* Resources */,
155+ );
156+ buildRules = (
157+ );
158+ dependencies = (
159+ 319C19491B4843EB005EFEE5 /* PBXTargetDependency */,
160+ );
161+ name = GMStepperExampleTests;
162+ productName = GMStepperExampleTests;
163+ productReference = 319C19471B4843EB005EFEE5 /* GMStepperExampleTests.xctest */;
164+ productType = "com.apple.product-type.bundle.unit-test";
165+ };
158166/* End PBXNativeTarget section */
159167
160168/* Begin PBXProject section */
161169 319C192A1B4843EB005EFEE5 /* Project object */ = {
162170 isa = PBXProject;
163171 attributes = {
164− LastSwiftMigration = 0700;
165− LastSwiftUpdateCheck = 0800;
166− LastUpgradeCheck = 0900;
172+ LastSwiftUpdateCheck = 0700;
173+ LastUpgradeCheck = 0640;
167174 ORGANIZATIONNAME = "Gunay Mert Karadogan";
168175 TargetAttributes = {
169− 3116C0D71DA4DD360015AC69 = {
170− CreatedOnToolsVersion = 8.0;
171− LastSwiftMigration = 0900;
172− ProvisioningStyle = Automatic;
173− TestTargetID = 319C19311B4843EB005EFEE5;
174− };
175176 319C19311B4843EB005EFEE5 = {
176177 CreatedOnToolsVersion = 6.4;
177− DevelopmentTeam = 289M6XEDV4;
178− LastSwiftMigration = 0900;
178+ };
179+ 319C19461B4843EB005EFEE5 = {
180+ CreatedOnToolsVersion = 6.4;
181+ TestTargetID = 319C19311B4843EB005EFEE5;
179182 };
180183 };
181184 };
@@ -193,58 +196,58 @@
193196 projectRoot = "";
194197 targets = (
195198 319C19311B4843EB005EFEE5 /* GMStepperExample */,
196− 3116C0D71DA4DD360015AC69 /* GMStepperExampleTests */,
199+ 319C19461B4843EB005EFEE5 /* GMStepperExampleTests */,
197200 );
198201 };
199202/* End PBXProject section */
200203
201204/* Begin PBXResourcesBuildPhase section */
202− 3116C0D61DA4DD360015AC69 /* Resources */ = {
205+ 319C19301B4843EB005EFEE5 /* Resources */ = {
203206 isa = PBXResourcesBuildPhase;
204207 buildActionMask = 2147483647;
205208 files = (
209+ 319C193D1B4843EB005EFEE5 /* Main.storyboard in Resources */,
210+ 319C19421B4843EB005EFEE5 /* LaunchScreen.xib in Resources */,
211+ 319C193F1B4843EB005EFEE5 /* Images.xcassets in Resources */,
206212 );
207213 runOnlyForDeploymentPostprocessing = 0;
208214 };
209− 319C19301B4843EB005EFEE5 /* Resources */ = {
215+ 319C19451B4843EB005EFEE5 /* Resources */ = {
210216 isa = PBXResourcesBuildPhase;
211217 buildActionMask = 2147483647;
212218 files = (
213− 319C193D1B4843EB005EFEE5 /* Main.storyboard in Resources */,
214− 319C19421B4843EB005EFEE5 /* LaunchScreen.xib in Resources */,
215− 319C193F1B4843EB005EFEE5 /* Images.xcassets in Resources */,
216219 );
217220 runOnlyForDeploymentPostprocessing = 0;
218221 };
219222/* End PBXResourcesBuildPhase section */
220223
221224/* Begin PBXSourcesBuildPhase section */
222− 3116C0D41DA4DD360015AC69 /* Sources */ = {
225+ 319C192E1B4843EB005EFEE5 /* Sources */ = {
223226 isa = PBXSourcesBuildPhase;
224227 buildActionMask = 2147483647;
225228 files = (
226− 3116C0DB1DA4DD360015AC69 /* GMStepperExampleTests.swift in Sources */,
227− 3198AC771DA4DEE500311FB3 /* GMStepper.swift in Sources */,
229+ 319C193A1B4843EB005EFEE5 /* ViewController.swift in Sources */,
230+ 319C195C1B48445E005EFEE5 /* GMStepper.swift in Sources */,
231+ 319C19381B4843EB005EFEE5 /* AppDelegate.swift in Sources */,
228232 );
229233 runOnlyForDeploymentPostprocessing = 0;
230234 };
231− 319C192E1B4843EB005EFEE5 /* Sources */ = {
235+ 319C19431B4843EB005EFEE5 /* Sources */ = {
232236 isa = PBXSourcesBuildPhase;
233237 buildActionMask = 2147483647;
234238 files = (
235− 319C193A1B4843EB005EFEE5 /* ViewController.swift in Sources */,
236− 319C195C1B48445E005EFEE5 /* GMStepper.swift in Sources */,
237− 319C19381B4843EB005EFEE5 /* AppDelegate.swift in Sources */,
239+ 319C194E1B4843EB005EFEE5 /* GMStepperExampleTests.swift in Sources */,
240+ 3169DD3E1B496C33009791D1 /* GMStepper.swift in Sources */,
238241 );
239242 runOnlyForDeploymentPostprocessing = 0;
240243 };
241244/* End PBXSourcesBuildPhase section */
242245
243246/* Begin PBXTargetDependency section */
244− 3116C0DE1DA4DD360015AC69 /* PBXTargetDependency */ = {
247+ 319C19491B4843EB005EFEE5 /* PBXTargetDependency */ = {
245248 isa = PBXTargetDependency;
246249 target = 319C19311B4843EB005EFEE5 /* GMStepperExample */;
247− targetProxy = 3116C0DD1DA4DD360015AC69 /* PBXContainerItemProxy */;
250+ targetProxy = 319C19481B4843EB005EFEE5 /* PBXContainerItemProxy */;
248251 };
249252/* End PBXTargetDependency section */
250253
@@ -268,44 +271,6 @@
268271/* End PBXVariantGroup section */
269272
270273/* Begin XCBuildConfiguration section */
271− 3116C0E01DA4DD360015AC69 /* Debug */ = {
272− isa = XCBuildConfiguration;
273− buildSettings = {
274− BUNDLE_LOADER = "$(TEST_HOST)";
275− CLANG_ANALYZER_NONNULL = YES;
276− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
277− CLANG_WARN_SUSPICIOUS_MOVES = YES;
278− DEBUG_INFORMATION_FORMAT = dwarf;
279− INFOPLIST_FILE = GMStepperExampleTests/Info.plist;
280− IPHONEOS_DEPLOYMENT_TARGET = 10.0;
281− LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
282− PRODUCT_BUNDLE_IDENTIFIER = com.gmertk.GMStepperExampleTests;
283− PRODUCT_NAME = "$(TARGET_NAME)";
284− SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
285− SWIFT_SWIFT3_OBJC_INFERENCE = On;
286− SWIFT_VERSION = 4.0;
287− TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
288− };
289− name = Debug;
290− };
291− 3116C0E11DA4DD360015AC69 /* Release */ = {
292− isa = XCBuildConfiguration;
293− buildSettings = {
294− BUNDLE_LOADER = "$(TEST_HOST)";
295− CLANG_ANALYZER_NONNULL = YES;
296− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
297− CLANG_WARN_SUSPICIOUS_MOVES = YES;
298− INFOPLIST_FILE = GMStepperExampleTests/Info.plist;
299− IPHONEOS_DEPLOYMENT_TARGET = 10.0;
300− LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
301− PRODUCT_BUNDLE_IDENTIFIER = com.gmertk.GMStepperExampleTests;
302− PRODUCT_NAME = "$(TARGET_NAME)";
303− SWIFT_SWIFT3_OBJC_INFERENCE = On;
304− SWIFT_VERSION = 4.0;
305− TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
306− };
307− name = Release;
308− };
309274 319C194F1B4843EB005EFEE5 /* Debug */ = {
310275 isa = XCBuildConfiguration;
311276 buildSettings = {
@@ -314,28 +279,19 @@
314279 CLANG_CXX_LIBRARY = "libc++";
315280 CLANG_ENABLE_MODULES = YES;
316281 CLANG_ENABLE_OBJC_ARC = YES;
317− CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
318282 CLANG_WARN_BOOL_CONVERSION = YES;
319− CLANG_WARN_COMMA = YES;
320283 CLANG_WARN_CONSTANT_CONVERSION = YES;
321284 CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
322285 CLANG_WARN_EMPTY_BODY = YES;
323286 CLANG_WARN_ENUM_CONVERSION = YES;
324− CLANG_WARN_INFINITE_RECURSION = YES;
325287 CLANG_WARN_INT_CONVERSION = YES;
326− CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
327− CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
328288 CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
329− CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
330− CLANG_WARN_STRICT_PROTOTYPES = YES;
331− CLANG_WARN_SUSPICIOUS_MOVE = YES;
332289 CLANG_WARN_UNREACHABLE_CODE = YES;
333290 CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
334291 "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
335292 COPY_PHASE_STRIP = NO;
336293 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
337294 ENABLE_STRICT_OBJC_MSGSEND = YES;
338− ENABLE_TESTABILITY = YES;
339295 GCC_C_LANGUAGE_STANDARD = gnu99;
340296 GCC_DYNAMIC_NO_PIC = NO;
341297 GCC_NO_COMMON_BLOCKS = YES;
@@ -367,21 +323,13 @@
367323 CLANG_CXX_LIBRARY = "libc++";
368324 CLANG_ENABLE_MODULES = YES;
369325 CLANG_ENABLE_OBJC_ARC = YES;
370− CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
371326 CLANG_WARN_BOOL_CONVERSION = YES;
372− CLANG_WARN_COMMA = YES;
373327 CLANG_WARN_CONSTANT_CONVERSION = YES;
374328 CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
375329 CLANG_WARN_EMPTY_BODY = YES;
376330 CLANG_WARN_ENUM_CONVERSION = YES;
377− CLANG_WARN_INFINITE_RECURSION = YES;
378331 CLANG_WARN_INT_CONVERSION = YES;
379− CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
380− CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
381332 CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
382− CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
383− CLANG_WARN_STRICT_PROTOTYPES = YES;
384− CLANG_WARN_SUSPICIOUS_MOVE = YES;
385333 CLANG_WARN_UNREACHABLE_CODE = YES;
386334 CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
387335 "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -400,7 +348,6 @@
400348 IPHONEOS_DEPLOYMENT_TARGET = 8.4;
401349 MTL_ENABLE_DEBUG_INFO = NO;
402350 SDKROOT = iphoneos;
403− SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
404351 VALIDATE_PRODUCT = YES;
405352 };
406353 name = Release;
@@ -409,13 +356,9 @@
409356 isa = XCBuildConfiguration;
410357 buildSettings = {
411358 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
412− DEVELOPMENT_TEAM = 289M6XEDV4;
413359 INFOPLIST_FILE = GMStepperExample/Info.plist;
414360 LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
415− PRODUCT_BUNDLE_IDENTIFIER = "com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)";
416361 PRODUCT_NAME = "$(TARGET_NAME)";
417− SWIFT_SWIFT3_OBJC_INFERENCE = Default;
418− SWIFT_VERSION = 4.0;
419362 };
420363 name = Debug;
421364 };
@@ -423,28 +366,49 @@
423366 isa = XCBuildConfiguration;
424367 buildSettings = {
425368 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
426− DEVELOPMENT_TEAM = 289M6XEDV4;
427369 INFOPLIST_FILE = GMStepperExample/Info.plist;
428370 LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
429− PRODUCT_BUNDLE_IDENTIFIER = "com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)";
430371 PRODUCT_NAME = "$(TARGET_NAME)";
431− SWIFT_SWIFT3_OBJC_INFERENCE = Default;
432− SWIFT_VERSION = 4.0;
372+ };
373+ name = Release;
374+ };
375+ 319C19551B4843EB005EFEE5 /* Debug */ = {
376+ isa = XCBuildConfiguration;
377+ buildSettings = {
378+ BUNDLE_LOADER = "$(TEST_HOST)";
379+ FRAMEWORK_SEARCH_PATHS = (
380+ "$(SDKROOT)/Developer/Library/Frameworks",
381+ "$(inherited)",
382+ );
383+ GCC_PREPROCESSOR_DEFINITIONS = (
384+ "DEBUG=1",
385+ "$(inherited)",
386+ );
387+ INFOPLIST_FILE = GMStepperExampleTests/Info.plist;
388+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
389+ PRODUCT_NAME = "$(TARGET_NAME)";
390+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
391+ };
392+ name = Debug;
393+ };
394+ 319C19561B4843EB005EFEE5 /* Release */ = {
395+ isa = XCBuildConfiguration;
396+ buildSettings = {
397+ BUNDLE_LOADER = "$(TEST_HOST)";
398+ FRAMEWORK_SEARCH_PATHS = (
399+ "$(SDKROOT)/Developer/Library/Frameworks",
400+ "$(inherited)",
401+ );
402+ INFOPLIST_FILE = GMStepperExampleTests/Info.plist;
403+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
404+ PRODUCT_NAME = "$(TARGET_NAME)";
405+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
433406 };
434407 name = Release;
435408 };
436409/* End XCBuildConfiguration section */
437410
438411/* Begin XCConfigurationList section */
439− 3116C0DF1DA4DD360015AC69 /* Build configuration list for PBXNativeTarget "GMStepperExampleTests" */ = {
440− isa = XCConfigurationList;
441− buildConfigurations = (
442− 3116C0E01DA4DD360015AC69 /* Debug */,
443− 3116C0E11DA4DD360015AC69 /* Release */,
444− );
445− defaultConfigurationIsVisible = 0;
446− defaultConfigurationName = Release;
447− };
448412 319C192D1B4843EB005EFEE5 /* Build configuration list for PBXProject "GMStepperExample" */ = {
449413 isa = XCConfigurationList;
450414 buildConfigurations = (
@@ -463,6 +427,15 @@
463427 defaultConfigurationIsVisible = 0;
464428 defaultConfigurationName = Release;
465429 };
430+ 319C19541B4843EB005EFEE5 /* Build configuration list for PBXNativeTarget "GMStepperExampleTests" */ = {
431+ isa = XCConfigurationList;
432+ buildConfigurations = (
433+ 319C19551B4843EB005EFEE5 /* Debug */,
434+ 319C19561B4843EB005EFEE5 /* Release */,
435+ );
436+ defaultConfigurationIsVisible = 0;
437+ defaultConfigurationName = Release;
438+ };
466439/* End XCConfigurationList section */
467440 };
468441 rootObject = 319C192A1B4843EB005EFEE5 /* Project object */;
GMStepperExample/GMStepperExample/AppDelegate.swift+10−10
@@ -14,33 +14,33 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1414 var window: UIWindow?
1515
1616
17− func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
17+ func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
1818 // Override point for customization after application launch.
1919 return true
2020 }
2121
22− func applicationWillResignActive(_ application: UIApplication) {
22+ func applicationWillResignActive(application: UIApplication) {
2323 // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24− // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
24+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
2525 }
2626
27− func applicationDidEnterBackground(_ application: UIApplication) {
27+ func applicationDidEnterBackground(application: UIApplication) {
2828 // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
2929 // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
3030 }
3131
32− func applicationWillEnterForeground(_ application: UIApplication) {
33− // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
32+ func applicationWillEnterForeground(application: UIApplication) {
33+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
3434 }
3535
36− func applicationDidBecomeActive(_ application: UIApplication) {
36+ func applicationDidBecomeActive(application: UIApplication) {
3737 // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
3838 }
3939
40− func applicationWillTerminate(_ application: UIApplication) {
40+ func applicationWillTerminate(application: UIApplication) {
4141 // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
4242 }
43−
44−
43+
44+
4545}
4646
GMStepperExample/GMStepperExample/Base.lproj/LaunchScreen.xib+2−6
@@ -1,8 +1,7 @@
11<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2−<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="15A279b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
2+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
33 <dependencies>
4− <deployment identifier="iOS"/>
5− <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
4+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207"/>
65 <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
76 </dependencies>
87 <objects>
@@ -14,20 +13,17 @@
1413 <subviews>
1514 <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Gunay Mert Karadogan. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
1615 <rect key="frame" x="20" y="439" width="441" height="21"/>
17− <animations/>
1816 <fontDescription key="fontDescription" type="system" pointSize="17"/>
1917 <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
2018 <nil key="highlightedColor"/>
2119 </label>
2220 <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="GMStepperExample" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
2321 <rect key="frame" x="20" y="140" width="441" height="43"/>
24− <animations/>
2522 <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
2623 <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
2724 <nil key="highlightedColor"/>
2825 </label>
2926 </subviews>
30− <animations/>
3127 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
3228 <constraints>
3329 <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
GMStepperExample/GMStepperExample/Base.lproj/Main.storyboard+43−71
@@ -1,10 +1,8 @@
11<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2−<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="vXZ-lx-hvc">
2+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="vXZ-lx-hvc">
33 <dependencies>
4− <deployment identifier="iOS"/>
5− <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
4+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
65 <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
7− <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
86 </dependencies>
97 <scenes>
108 <!--View Controller-->
@@ -16,92 +14,105 @@
1614 <viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
1715 </layoutGuides>
1816 <view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
19− <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
17+ <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
2018 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
2119 <subviews>
2220 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AU6-4C-B2F" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
23− <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
21+ <rect key="frame" x="24" y="28" width="552" height="44"/>
22+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
2423 <constraints>
2524 <constraint firstAttribute="height" constant="44" id="6mC-hP-wFD"/>
2625 </constraints>
2726 <userDefinedRuntimeAttributes>
28− <userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
29− <real key="value" value="25"/>
27+ <userDefinedRuntimeAttribute type="number" keyPath="minimumValue">
28+ <integer key="value" value="0"/>
3029 </userDefinedRuntimeAttribute>
31− <userDefinedRuntimeAttribute type="number" keyPath="stepValue">
32− <real key="value" value="5"/>
30+ <userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
31+ <integer key="value" value="100"/>
3332 </userDefinedRuntimeAttribute>
3433 </userDefinedRuntimeAttributes>
3534 </view>
3635 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="if7-U5-bAM" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
37− <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
36+ <rect key="frame" x="140" y="116" width="320" height="66"/>
37+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
3838 <constraints>
3939 <constraint firstAttribute="height" constant="66" id="iQi-6P-vt9"/>
4040 <constraint firstAttribute="width" constant="320" id="ji4-Pf-1fZ"/>
4141 </constraints>
4242 <userDefinedRuntimeAttributes>
43+ <userDefinedRuntimeAttribute type="number" keyPath="minimumValue">
44+ <integer key="value" value="0"/>
45+ </userDefinedRuntimeAttribute>
46+ <userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
47+ <integer key="value" value="100"/>
48+ </userDefinedRuntimeAttribute>
4349 <userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
44− <color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
50+ <color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="calibratedRGB"/>
4551 </userDefinedRuntimeAttribute>
4652 <userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
47− <color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
53+ <color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="calibratedRGB"/>
4854 </userDefinedRuntimeAttribute>
4955 <userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
50− <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
56+ <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
5157 </userDefinedRuntimeAttribute>
5258 <userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
53− <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
59+ <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
5460 </userDefinedRuntimeAttribute>
5561 <userDefinedRuntimeAttribute type="color" keyPath="limitHitAnimationColor">
56− <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
57− </userDefinedRuntimeAttribute>
58− <userDefinedRuntimeAttribute type="number" keyPath="stepValue">
59− <real key="value" value="0.5"/>
62+ <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
6063 </userDefinedRuntimeAttribute>
6164 </userDefinedRuntimeAttributes>
6265 </view>
6366 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="R9n-I0-fq7" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
64− <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
67+ <rect key="frame" x="200" y="226" width="200" height="66"/>
68+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
6569 <constraints>
6670 <constraint firstAttribute="width" constant="200" id="dVu-w0-mf0"/>
6771 <constraint firstAttribute="height" constant="66" id="ie8-vl-NAV"/>
6872 </constraints>
6973 <userDefinedRuntimeAttributes>
7074 <userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
71− <color key="value" red="0.1819814891" green="0.69426733259999995" blue="0.53024792669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
75+ <color key="value" red="0.1819814891" green="0.69426733259999995" blue="0.53024792669999998" alpha="1" colorSpace="calibratedRGB"/>
7276 </userDefinedRuntimeAttribute>
7377 <userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
74− <color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
78+ <color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
7579 </userDefinedRuntimeAttribute>
7680 <userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
77− <color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
81+ <color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="calibratedRGB"/>
7882 </userDefinedRuntimeAttribute>
7983 <userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
80− <color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
84+ <color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
85+ </userDefinedRuntimeAttribute>
86+ <userDefinedRuntimeAttribute type="number" keyPath="minimumValue">
87+ <integer key="value" value="0"/>
88+ </userDefinedRuntimeAttribute>
89+ <userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
90+ <integer key="value" value="100"/>
8191 </userDefinedRuntimeAttribute>
8292 <userDefinedRuntimeAttribute type="color" keyPath="limitHitAnimationColor">
83− <color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
93+ <color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="calibratedRGB"/>
8494 </userDefinedRuntimeAttribute>
8595 </userDefinedRuntimeAttributes>
8696 </view>
8797 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="U8X-8Z-7Mo" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
88− <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
98+ <rect key="frame" x="24" y="336" width="552" height="44"/>
99+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
89100 <constraints>
90101 <constraint firstAttribute="height" constant="44" id="aF3-T7-dIP"/>
91102 <constraint firstAttribute="width" constant="200" id="vhP-7K-vOu"/>
92103 </constraints>
93104 <userDefinedRuntimeAttributes>
94105 <userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
95− <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
106+ <color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
96107 </userDefinedRuntimeAttribute>
97108 <userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
98− <color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
109+ <color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
99110 </userDefinedRuntimeAttribute>
100111 <userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
101− <color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
112+ <color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
102113 </userDefinedRuntimeAttribute>
103114 <userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
104− <color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
115+ <color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
105116 </userDefinedRuntimeAttribute>
106117 <userDefinedRuntimeAttribute type="number" keyPath="labelWidthWeight">
107118 <real key="value" value="0.69999999999999996"/>
@@ -112,7 +123,7 @@
112123 <integer key="value" value="0"/>
113124 </userDefinedRuntimeAttribute>
114125 <userDefinedRuntimeAttribute type="color" keyPath="limitHitAnimationColor">
115− <color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
126+ <color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
116127 </userDefinedRuntimeAttribute>
117128 <userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
118129 <integer key="value" value="100"/>
@@ -124,44 +135,8 @@
124135 </mask>
125136 </variation>
126137 </view>
127− <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9Ri-Yr-sRs" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
128− <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
129− <constraints>
130− <constraint firstAttribute="width" constant="180" id="dhO-Nd-SFk"/>
131− <constraint firstAttribute="height" constant="50" id="xPS-vU-cZc"/>
132− </constraints>
133− <userDefinedRuntimeAttributes>
134− <userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
135− <real key="value" value="10"/>
136− </userDefinedRuntimeAttribute>
137− <userDefinedRuntimeAttribute type="number" keyPath="stepValue">
138− <real key="value" value="1"/>
139− </userDefinedRuntimeAttribute>
140− <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
141− <real key="value" value="2"/>
142− </userDefinedRuntimeAttribute>
143− <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
144− <real key="value" value="4"/>
145− </userDefinedRuntimeAttribute>
146− <userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
147− <color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
148− </userDefinedRuntimeAttribute>
149− <userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
150− <color key="value" red="1" green="0.47058823529999999" blue="0.15686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
151− </userDefinedRuntimeAttribute>
152− <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
153− <color key="value" red="1" green="0.47058823529999999" blue="0.15686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
154− </userDefinedRuntimeAttribute>
155− <userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
156− <color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
157− </userDefinedRuntimeAttribute>
158− <userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
159− <color key="value" red="1" green="0.47058823529999999" blue="0.15686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
160− </userDefinedRuntimeAttribute>
161− </userDefinedRuntimeAttributes>
162− </view>
163138 </subviews>
164− <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
139+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
165140 <constraints>
166141 <constraint firstItem="R9n-I0-fq7" firstAttribute="centerX" secondItem="U8X-8Z-7Mo" secondAttribute="centerX" id="3cD-WW-Qg4"/>
167142 <constraint firstItem="if7-U5-bAM" firstAttribute="top" secondItem="AU6-4C-B2F" secondAttribute="bottom" constant="44" id="662-W9-CUn"/>
@@ -171,9 +146,7 @@
171146 <constraint firstItem="if7-U5-bAM" firstAttribute="centerX" secondItem="R9n-I0-fq7" secondAttribute="centerX" id="K7g-rC-ehJ"/>
172147 <constraint firstItem="U8X-8Z-7Mo" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" constant="8" id="S1b-pD-UXA"/>
173148 <constraint firstItem="U8X-8Z-7Mo" firstAttribute="top" secondItem="R9n-I0-fq7" secondAttribute="bottom" constant="44" id="fBW-Xx-pa0"/>
174− <constraint firstItem="9Ri-Yr-sRs" firstAttribute="centerX" secondItem="kh9-bI-dsS" secondAttribute="centerX" id="fay-qT-jKR"/>
175149 <constraint firstItem="AU6-4C-B2F" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" constant="8" id="iIM-b2-jzV"/>
176− <constraint firstItem="9Ri-Yr-sRs" firstAttribute="top" secondItem="U8X-8Z-7Mo" secondAttribute="bottom" constant="44" id="nKi-Fp-8B7"/>
177150 <constraint firstAttribute="trailingMargin" secondItem="U8X-8Z-7Mo" secondAttribute="trailing" constant="8" id="ppd-nb-fL8"/>
178151 <constraint firstItem="AU6-4C-B2F" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" constant="8" symbolic="YES" id="zDK-gF-kms"/>
179152 </constraints>
@@ -184,7 +157,6 @@
184157 </viewController>
185158 <placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
186159 </objects>
187− <point key="canvasLocation" x="274" y="363"/>
188160 </scene>
189161 </scenes>
190162</document>
GMStepperExample/GMStepperExample/Info.plist+1−1
@@ -7,7 +7,7 @@
77 <key>CFBundleExecutable</key>
88 <string>$(EXECUTABLE_NAME)</string>
99 <key>CFBundleIdentifier</key>
10− <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
10+ <string>com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)</string>
1111 <key>CFBundleInfoDictionaryVersion</key>
1212 <string>6.0</string>
1313 <key>CFBundleName</key>
GMStepperExample/GMStepperExample/ViewController.swift+3−3
@@ -13,10 +13,10 @@ class ViewController: UIViewController {
1313 @IBOutlet weak var stepper: GMStepper!
1414 override func viewDidLoad() {
1515 super.viewDidLoad()
16− stepper.addTarget(self, action: #selector(ViewController.stepperValueChanged), for: .valueChanged)
16+ stepper.addTarget(self, action: "stepperValueChanged:", forControlEvents: .ValueChanged)
1717 }
1818
19− @objc func stepperValueChanged(stepper: GMStepper) {
20− print(stepper.value, terminator: "")
19+ func stepperValueChanged(stepper: GMStepper) {
20+ println(stepper.value)
2121 }
2222}
GMStepperExample/GMStepperExampleTests/GMStepperExampleTests.swift+4−4
@@ -6,8 +6,8 @@
66// Copyright (c) 2015 Gunay Mert Karadogan. All rights reserved.
77//
88
9−import XCTest
109import UIKit
10+import XCTest
1111
1212class GMStepperExampleTests: XCTestCase {
1313 var stepper: GMStepper!
@@ -19,7 +19,7 @@ class GMStepperExampleTests: XCTestCase {
1919
2020 func testDefaults() {
2121 XCTAssert(stepper.minimumValue == 0, "minimumValue defaults 0")
22− XCTAssert(stepper.maximumValue == 100, "maximumValue defaults to 100")
22+ XCTAssert(stepper.maximumValue == 10, "maximumValue defaults to 10")
2323 XCTAssert(stepper.value == 0, "value defaults to 0")
2424 }
2525
@@ -37,6 +37,6 @@ class GMStepperExampleTests: XCTestCase {
3737
3838 XCTAssert(stepper.value == stepper.maximumValue, "Pass")
3939 }
40−
41−
40+
41+
4242}
GMStepperExample/GMStepperExampleTests/Info.plist+3−1
@@ -7,7 +7,7 @@
77 <key>CFBundleExecutable</key>
88 <string>$(EXECUTABLE_NAME)</string>
99 <key>CFBundleIdentifier</key>
10− <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
10+ <string>com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)</string>
1111 <key>CFBundleInfoDictionaryVersion</key>
1212 <string>6.0</string>
1313 <key>CFBundleName</key>
@@ -16,6 +16,8 @@
1616 <string>BNDL</string>
1717 <key>CFBundleShortVersionString</key>
1818 <string>1.0</string>
19+ <key>CFBundleSignature</key>
20+ <string>????</string>
1921 <key>CFBundleVersion</key>
2022 <string>1</string>
2123</dict>
README.md+10−30
@@ -3,12 +3,11 @@
33[![License](https://img.shields.io/cocoapods/l/GMStepper.svg?style=flat)](http://cocoapods.org/pods/GMStepper)
44[![Platform](https://img.shields.io/cocoapods/p/GMStepper.svg?style=flat)](http://cocoapods.org/pods/GMStepper)
55
6−A stepper with a sliding label in the middle. Pan the label or tap the buttons. Check out the tutorial, [How to Build a Custom Stepper - Part 1](http://gmertk.github.io/custom-stepper-part-1/).
7−
6+A stepper with a sliding label in the middle. Pan the label or tap the buttons.
87
98## Screenshot
109
11−![Screenshot_1.gif](https://raw.githubusercontent.com/gmertk/GMStepper/master/Screenshots/screenshot_1.gif)
10+![Screenshot_0.gif](https://raw.githubusercontent.com/gmertk/GMStepper/master/Screenshots/screenshot_0.gif)
1211
1312
1413## Usage
@@ -20,7 +19,7 @@ it, simply add the following lines to your Podfile:
2019use_frameworks!
2120pod "GMStepper"
2221```
23−
22+
2423## Setup
2524
2625If you want to use storyboards, just drop a UIView into your storyboard and set its class to `GMStepper`. Then customize through the attributes inspector. Otherwise, you can write the code to initialize with frame and set the properties.
@@ -28,22 +27,13 @@ If you want to use storyboards, just drop a UIView into your storyboard and set
2827## Properties
2928```swift
3029/// Current value of the stepper. Defaults to 0.
31−var value: Double = 0
30+var value: Int = 0
3231
3332/// Minimum value. Must be less than maximumValue. Defaults to 0.
34−var minimumValue: Double = 0
35−
36−/// Maximum value. Must be more than minimumValue. Defaults to 100.
37−var maximumValue: Double = 100
38−
39−/// Step/Increment value as in UIStepper. Defaults to 1.
40−var stepValue: Double = 1
33+var minimumValue: Int = 0
4134
42−/// The same as UIStepper's autorepeat. If true, holding on the buttons or keeping the pan gesture alters the value repeatedly. Defaults to true.
43−var autorepeat: Bool = true
44−
45−/// If the value is integer, it is shown without floating point.
46−var showIntegerIfDoubleIsInteger: Bool = true
35+/// Maximum value. Must be more than minimumValue. Defaults to 10.
36+var maximumValue: Int = 10
4737
4838/// Text on the left button. Be sure that it fits in the button. Defaults to "-".
4939var leftButtonText: String = "-"
@@ -69,30 +59,20 @@ var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alph
6959/// Font of the middle label. Defaults to AvenirNext-Bold, 25.0 points in size.
7060var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)
7161
72−/// Corner radius of the middle label's layer. Defaults to 0.0.
73−var labelCornerRadius: CGFloat = 0.0
74−
7562/// Corner radius of the stepper's layer. Defaults to 4.0.
7663var cornerRadius: CGFloat = 4.0
7764
78−/// Border width of the stepper and middle label's layer. Defaults to 0.0.
79−var borderWidth: CGFloat = 0.0
80−
81−/// Color of the border of the stepper and middle label's layer. Defaults to clear color.
82−var borderColor: UIColor = UIColor.clearColor()
83−
8465/// 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.
85−var labelWidthWeight: CGFloat = 0.5
66+var labelWidthWeight: CGFloat = 0.5
8667
8768/// Color of the flashing animation on the buttons in case the value hit the limit.
8869var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
8970```
9071
9172
92−## Authors
73+## Author
9374
94−* [Brent Whitman](https://github.com/bwhtmn) - Maintainer
95−* [Günay Mert Karadoğan](https://github.com/gmertk) - Creator
75+Günay Mert Karadoğan, mertkaradogan@gmail.com
9676
9777## License
9878
Screenshots/screenshot_0.gifnew file

Binary file not shown.

Screenshots/screenshot_0.pngnew file

Binary file not shown.

Screenshots/screenshot_1.gifdeleted

Binary file not shown.