Compare commits

..

53 Commits

Author SHA1 Message Date
Даша d7c8bb83b0
Merge pull request #2 from TouchInstinct/block_minimum_reached
Added block call when minimum is reached
2019-03-11 16:14:38 +03:00
DashaGitHub 810fcbefea Some refactoring 2019-03-11 16:10:21 +03:00
DashaGitHub f893371f73 Some refactoring 2019-03-11 16:05:15 +03:00
DashaGitHub 9444b32028 Some refactoring 2019-03-11 14:42:45 +03:00
DashaGitHub dd09a1e0d9 Added block call when minimum is reached. Refactoring 2019-03-11 14:37:33 +03:00
DashaGitHub a02560f7e0 Added block call when minimum is reached 2019-03-11 11:57:02 +03:00
Ivan Zinovyev 3c81fa9ade
Merge pull request #1 from iznv/stepper_customization
Stepper customisation
2018-11-01 23:15:18 +06:00
Ivan Zinovyev 719830b81e Update version in podspec 2018-11-01 19:53:14 +03:00
Ivan Zinovyev 82453c0681 Replace buttons text with images 2018-11-01 18:44:46 +03:00
Ivan Zinovyev 7367554d53 Add leftButtonLimitOpacity, buttonsTextInsets, didTouchLabel 2018-10-31 20:19:59 +03:00
Brent Whitman 4bb23e79aa Add swift_version to podspec 2018-09-18 06:38:08 -07:00
Brent Whitman e91c2577e4 change minimum iOS version back to 8.0 2018-09-15 13:44:56 -07:00
Brent Whitman d81e614d1b Update to Swift 4.2 2018-07-13 13:31:32 -07:00
Brent Whitman 338fa1ebad Improve display to avoid rounding imprecision when using non-integer step values. Fix for issue #36. 2018-07-13 13:23:22 -07:00
Brent Whitman ae98a8c70b Update .swift-version to 4.0 2017-10-26 09:23:32 -07:00
Brent Whitman c2748bb776 Update to Swift 4: add @objc for all public variables and functions 2017-09-08 09:45:44 -07:00
Brent Whitman 4c5bfffbb8 Update podspec for v2.0.1 2017-04-24 10:51:17 -07:00
Brent Whitman 71c1c1b9a6 Update readme - remove maintainer notice 2017-04-24 10:43:29 -07:00
Brent W b470b560b9 Merge pull request #35 from shamsmosowi/master
Adjustable middle label layer corner radius
2017-04-24 10:30:27 -07:00
shamsmosowi a47725de8b Update README.md 2017-04-23 20:03:01 +10:00
shamsmosowi 8af374c283 Update README.md 2017-04-23 20:01:18 +10:00
shamsmosowi 88dd8d76b6 Update GMStepper.swift 2017-04-23 19:55:05 +10:00
Gunay Mert Karadogan 07616aa0ff Update Readme for Brent as a maintainer 2017-03-30 14:34:35 +03:00
Gunay Mert Karadogan 44f1477df1 Merge pull request #33 from bwhtmn/touchCancel
Reset timer when button touches are cancelled
2017-03-27 10:59:46 +01:00
Brent Whitman fae1225e36 Reset timer when button touches are cancelled 2017-03-24 13:26:50 -07:00
Gunay Mert Karadogan ae068ac0fd Update Readme for maintainer notice 2017-02-25 21:11:16 +00:00
Gunay Mert Karadogan 35f3db649a Add .swift-version for cocoapods 2016-10-06 20:24:10 +01:00
Gunay Mert Karadogan 96389e6d75 Fix warnings and storyboard errors 2016-10-05 08:12:16 +01:00
Gunay Mert Karadogan c136918409 Merge pull request #26 from Legoless/Swift3
Swift3 Support
2016-10-04 23:18:32 -07:00
Dal Rupnik f52eb0448b Added ability to set items to display in label 2016-08-18 18:55:44 +02:00
Dal Rupnik 43d38b5973 Converted to Swift3 2016-08-18 17:29:49 +02:00
Gunay Mert Karadogan 5d4d5a4989 Bump up to 1.2.0 2016-04-21 19:34:33 +02:00
Gunay Mert Karadogan 8631f60be1 Update README for borders 2016-04-21 19:33:08 +02:00
Gunay Mert Karadogan 31d50f82f7 Use #selector syntax 2016-04-21 19:28:34 +02:00
Gunay Mert Karadogan 36df74db47 Merge pull request #23 from luugiathuy/master
Add borderWidth and borderColor properties
2016-04-21 15:00:52 +02:00
Luu Gia Thuy bc199530cb Add borderWidth and borderColor properties
This will help creating steppers with transparent background colors, borders and separators between buttons and middle label (similar to default iOS style
2016-04-21 18:24:21 +08:00
Gunay Mert Karadogan b7acb5d479 Merge pull request #21 from vtourraine/patch-1
Update minus sign character
2016-03-11 15:11:45 +01:00
Vincent Tourraine 993b8297e2 Update minus sign character 2016-03-11 14:10:12 +01:00
Gunay Mert Karadogan 39296c9815 Bump up pod version 2015-09-11 13:50:39 +03:00
Gunay Mert Karadogan a3f6ab1441 Merge pull request #15 from lexrus/master
Upgrade to Swift 2.0 and Xcode 7 GM.
2015-09-10 15:46:26 +03:00
Lex Tang 0ee7bfa26c Upgrade to Swift 2.0. 2015-09-10 11:35:55 +08:00
Gunay Mert Karadogan 9bc287a1b5 Remove println 2015-07-17 19:31:59 +02:00
Gunay Mert Karadogan f380fc31d0 Change some vars to let constant 2015-07-17 19:24:18 +02:00
Gunay Mert Karadogan ed34ebf37b Reset timer when the app resigned 2015-07-14 10:52:57 +02:00
Gunay Mert Karadogan 050e495744 Update readme with tutorial-part-1 link 2015-07-13 15:21:05 +02:00
Gunay Mert Karadogan 1c97b27d14 Add gif 2015-07-12 22:37:00 +02:00
Gunay Mert Karadogan 878da616db Update the readme, bump up the version 1.0.0 2015-07-12 16:12:18 +02:00
Gunay Mert Karadogan 1e5a91f90c Add value:Double, stepperValue and showIntegerIfDoubleIsInteger 2015-07-11 14:21:18 +02:00
Gunay Mert Karadogan 9619704a90 Refactoring and bug fixes
- Keep a stepper state
- Disable button or buttons in state of increasing or decreasing
2015-07-10 22:54:23 +02:00
Gunay Mert Karadogan 8789187aac Add autorepeat for pan gesture 2015-07-10 12:42:48 +02:00
Gunay Mert Karadogan 8f3ccfd2d5 Add UIStepper's autorepeat for button taps 2015-07-10 01:07:14 +02:00
Gunay Mert Karadogan 3332ee8a61 Update Readme 2015-07-09 12:54:27 +02:00
Gunay Mert Karadogan 3d6725d1c1 Add pan gesture to label 2015-07-09 12:51:16 +02:00
20 changed files with 705 additions and 592 deletions

2
.gitignore vendored
View File

@ -31,3 +31,5 @@ DerivedData
# Carthage/Checkouts
Carthage/Build
.DS_Store

1
.swift-version Normal file
View File

@ -0,0 +1 @@
4.2

View File

@ -1,14 +1,16 @@
Pod::Spec.new do |s|
s.name = "GMStepper"
s.version = "0.1.2"
s.version = "2.2.1"
s.summary = "A stepper with a sliding label in the middle."
s.homepage = "https://github.com/gmertk/GMStepper"
s.screenshots = "https://dl.dropboxusercontent.com/u/4397140/pod-screenshots/screenshot_1.png"
s.screenshots = "https://raw.githubusercontent.com/gmertk/GMStepper/master/Screenshots/screenshot_1.gif"
s.license = 'MIT'
s.author = { "Gunay Mert Karadogan" => "mertkaradogan@gmail.com" }
s.authors = { "Gunay Mert Karadogan" => "mertkaradogan@gmail.com",
"Brent Whitman" => "brent@pathym.com" }
s.source = { :git => "https://github.com/gmertk/GMStepper.git", :tag => s.version.to_s }
s.social_media_url = 'https://twitter.com/gunaymertk'
s.platform = :ios, '8.0'
s.requires_arc = true
s.source_files = 'GMStepper/*.swift'
s.swift_version = '4.2'
end

View File

@ -11,56 +11,96 @@ import UIKit
@IBDesignable public class GMStepper: UIControl {
/// Current value of the stepper. Defaults to 0.
public var value = 0 {
@objc @IBInspectable public var value: Double = 0 {
didSet {
value = min(maximumValue, max(minimumValue, value))
label.text = String(value)
handleIsLimitReached()
label.text = formattedValue
if oldValue != value {
sendActionsForControlEvents(.ValueChanged)
sendActions(for: .valueChanged)
}
}
}
private var formattedValue: String? {
let isInteger = Decimal(value).exponent >= 0
// If we have items, we will display them as steps
if isInteger && stepValue == 1.0 && items.count > 0 {
return items[Int(value)]
}
else {
return formatter.string(from: NSNumber(value: value))
}
}
/// Minimum value. Must be less than maximumValue. Defaults to 0.
@IBInspectable public var minimumValue: Int = 0 {
@objc @IBInspectable public var minimumValue: Double = 0 {
didSet {
value = 0
value = min(maximumValue, max(minimumValue, value))
}
}
/// Maximum value. Must be more than minimumValue. Defaults to 10.
@IBInspectable public var maximumValue: Int = 10 {
/// Maximum value. Must be more than minimumValue. Defaults to 100.
@objc @IBInspectable public var maximumValue: Double = 100 {
didSet {
value = 0
value = min(maximumValue, max(minimumValue, value))
}
}
/// Text on the left button. Be sure that it fits in the button. Defaults to "-".
@IBInspectable public var leftButtonText: String = "-" {
/// Step/Increment value as in UIStepper. Defaults to 1.
@objc @IBInspectable public var stepValue: Double = 1 {
didSet {
leftButton.setTitle(leftButtonText, forState: .Normal)
setupNumberFormatter()
}
}
/// Text on the right button. Be sure that it fits in the button. Defaults to "+".
@IBInspectable public var rightButtonText: String = "+" {
/// The same as UIStepper's autorepeat. If true, holding on the buttons or keeping the pan gesture alters the value repeatedly. Defaults to true.
@objc @IBInspectable public var autorepeat: Bool = true
/// If the value is integer, it is shown without floating point.
@objc @IBInspectable public var showIntegerIfDoubleIsInteger: Bool = true {
didSet {
rightButton.setTitle(rightButtonText, forState: .Normal)
setupNumberFormatter()
}
}
/// Text color of the buttons. Defaults to white.
@IBInspectable public var buttonsTextColor: UIColor = UIColor.whiteColor() {
/// Image on the left button. Defaults to nil.
@objc @IBInspectable public var leftButtonImage: UIImage? = nil {
didSet {
for button in [leftButton, rightButton] {
button.setTitleColor(buttonsTextColor, forState: .Normal)
}
leftButton.setImage(leftButtonImage, for: .normal)
}
}
/// Image on the right button. Defaults to nil.
@objc @IBInspectable public var rightButtonImage: UIImage? = nil {
didSet {
rightButton.setImage(rightButtonImage, for: .normal)
}
}
/// Left button content insets. Defaults to ".zero".
@objc @IBInspectable public var leftButtonContentInsets: UIEdgeInsets = .zero {
didSet {
leftButton.contentEdgeInsets = leftButtonContentInsets
}
}
/// Right button content insets. Defaults to ".zero".
@objc @IBInspectable public var rightButtonContentInsets: UIEdgeInsets = .zero {
didSet {
rightButton.contentEdgeInsets = rightButtonContentInsets
}
}
/// Left button limit opacity. Defaults to "0.4".
@objc @IBInspectable public var leftButtonLimitOpacity: CGFloat = 0.4
/// Background color of the buttons. Defaults to dark blue.
@IBInspectable public var buttonsBackgroundColor: UIColor = UIColor(red:0.21, green:0.5, blue:0.74, alpha:1) {
@objc @IBInspectable public var buttonsBackgroundColor: UIColor = UIColor(red:0.21, green:0.5, blue:0.74, alpha:1) {
didSet {
for button in [leftButton, rightButton] {
button.backgroundColor = buttonsBackgroundColor
@ -69,105 +109,214 @@ import UIKit
}
}
/// Font of the buttons. Defaults to AvenirNext-Bold, 20.0 points in size.
public var buttonsFont = UIFont(name: "AvenirNext-Bold", size: 20.0)! {
didSet {
for button in [leftButton, rightButton] {
button.titleLabel?.font = buttonsFont
}
}
}
/// Label tap closure
@objc public var didTouchLabel: ((Double) -> Void)?
/// Block is called when the minimum is exceeded
@objc public var minimumExceeded: (() -> Void)?
/// Text color of the middle label. Defaults to white.
@IBInspectable public var labelTextColor: UIColor = UIColor.whiteColor() {
@objc @IBInspectable public var labelTextColor: UIColor = UIColor.white {
didSet {
label.textColor = labelTextColor
}
}
/// Text color of the middle label. Defaults to lighter blue.
@IBInspectable public var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1) {
@objc @IBInspectable public var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1) {
didSet {
label.backgroundColor = labelBackgroundColor
}
}
/// Font of the middle label. Defaults to AvenirNext-Bold, 25.0 points in size.
public var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)! {
@objc public var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)! {
didSet {
label.font = labelFont
}
}
/// Corner radius of the middle label. Defaults to 0.
@objc @IBInspectable public var labelCornerRadius: CGFloat = 0 {
didSet {
label.layer.cornerRadius = labelCornerRadius
}
}
/// Corner radius of the stepper's layer. Defaults to 4.0.
@IBInspectable public var cornerRadius: CGFloat = 4.0 {
@objc @IBInspectable public var cornerRadius: CGFloat = 4.0 {
didSet {
layer.cornerRadius = cornerRadius
clipsToBounds = true
}
}
/// Border width of the stepper and middle label's layer. Defaults to 0.0.
@objc @IBInspectable public var borderWidth: CGFloat = 0.0 {
didSet {
layer.borderWidth = borderWidth
label.layer.borderWidth = borderWidth
}
}
/// Color of the border of the stepper and middle label's layer. Defaults to clear color.
@objc @IBInspectable public var borderColor: UIColor = UIColor.clear {
didSet {
layer.borderColor = borderColor.cgColor
label.layer.borderColor = borderColor.cgColor
}
}
/// 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.
@IBInspectable public var labelWidthWeight: CGFloat = 0.5 {
@objc @IBInspectable public var labelWidthWeight: CGFloat = 0.5 {
didSet {
labelWidthWeight = min(1, max(0, labelWidthWeight))
setNeedsLayout()
}
}
/// Color of the flashing animation on the buttons in case the value hit the limit.
@objc @IBInspectable public var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
/// Formatter for displaying the current value
let formatter = NumberFormatter()
/**
Width of the sliding animation. When buttons clicked, the middle label does a slide animation towards to the clicked button. Defaults to 5.
*/
private let labelSlideLength: CGFloat = 5
let labelSlideLength: CGFloat = 5
/// Duration of the sliding animation
private let labelSlideDuration: NSTimeInterval = 0.1
let labelSlideDuration = TimeInterval(0.1)
/// Duration of the flashing animation when the value hits the limit.
private let limitHitAnimationDuration: NSTimeInterval = 0.1
/// Duration of the animation when the value hits the limit.
let limitHitAnimationDuration = TimeInterval(0.1)
/// Color of the flashing animation on the buttons in case the value hit the limit.
@IBInspectable public var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
lazy var leftButton: UIButton = {
let button = UIButton()
button.setImage(self.leftButtonImage, for: .normal)
button.backgroundColor = self.buttonsBackgroundColor
button.addTarget(self, action: #selector(GMStepper.leftButtonTouchDown), for: .touchDown)
button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpInside)
button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpOutside)
button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchCancel)
return button
}()
private let leftButton = UIButton()
private let rightButton = UIButton()
private let label = UILabel()
lazy var rightButton: UIButton = {
let button = UIButton()
button.setImage(self.rightButtonImage, for: .normal)
button.backgroundColor = self.buttonsBackgroundColor
button.addTarget(self, action: #selector(GMStepper.rightButtonTouchDown), for: .touchDown)
button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpInside)
button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchUpOutside)
button.addTarget(self, action: #selector(GMStepper.buttonTouchUp), for: .touchCancel)
return button
}()
required public init(coder aDecoder: NSCoder) {
lazy var label: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.text = formattedValue
label.textColor = self.labelTextColor
label.backgroundColor = self.labelBackgroundColor
label.font = self.labelFont
label.layer.cornerRadius = self.labelCornerRadius
label.layer.masksToBounds = true
label.isUserInteractionEnabled = true
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(GMStepper.handlePan))
panRecognizer.maximumNumberOfTouches = 1
label.addGestureRecognizer(panRecognizer)
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(GMStepper.handleLabelTap))
label.addGestureRecognizer(tapRecognizer)
return label
}()
var labelOriginalCenter: CGPoint!
var labelMaximumCenterX: CGFloat!
var labelMinimumCenterX: CGFloat!
enum LabelPanState {
case Stable, HitRightEdge, HitLeftEdge
}
var panState = LabelPanState.Stable
enum StepperState {
case Stable, ShouldIncrease, ShouldDecrease
}
var stepperState = StepperState.Stable {
didSet {
if stepperState != .Stable {
updateValue()
if autorepeat {
scheduleTimer()
}
}
}
}
@objc public var items : [String] = [] {
didSet {
label.text = formattedValue
}
}
/// Timer used for autorepeat option
var timer: Timer?
/** When UIStepper reaches its top speed, it alters the value with a time interval of ~0.05 sec.
The user pressing and holding on the stepper repeatedly:
- First 2.5 sec, the stepper changes the value every 0.5 sec.
- For the next 1.5 sec, it changes the value every 0.1 sec.
- Then, every 0.05 sec.
*/
let timerInterval = TimeInterval(0.05)
/// 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.
var timerFireCount = 0
var timerFireCountModulo: Int {
if timerFireCount > 80 {
return 1 // 0.05 sec * 1 = 0.05 sec
} else if timerFireCount > 50 {
return 2 // 0.05 sec * 2 = 0.1 sec
} else {
return 10 // 0.05 sec * 10 = 0.5 sec
}
}
@objc required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
public override init(frame: CGRect) {
@objc public override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
private func setup() {
leftButton.setTitle(leftButtonText, forState: .Normal)
leftButton.setTitleColor(buttonsTextColor, forState: .Normal)
leftButton.backgroundColor = buttonsBackgroundColor
leftButton.titleLabel?.font = buttonsFont
leftButton.addTarget(self, action: "leftButtonTapped:", forControlEvents: .TouchDown)
fileprivate func setup() {
addSubview(leftButton)
rightButton.setTitle(rightButtonText, forState: .Normal)
rightButton.setTitleColor(buttonsTextColor, forState: .Normal)
rightButton.backgroundColor = buttonsBackgroundColor
rightButton.titleLabel?.font = buttonsFont
rightButton.addTarget(self, action: "rightButtonTapped:", forControlEvents: .TouchDown)
addSubview(rightButton)
label.textAlignment = .Center
label.text = String(value)
label.textColor = labelTextColor
label.backgroundColor = labelBackgroundColor
label.font = labelFont
addSubview(label)
handleIsLimitReached()
backgroundColor = buttonsBackgroundColor
layer.cornerRadius = cornerRadius
clipsToBounds = true
labelOriginalCenter = label.center
setupNumberFormatter()
NotificationCenter.default.addObserver(self, selector: #selector(GMStepper.reset), name: UIApplication.willResignActiveNotification, object: nil)
}
func setupNumberFormatter() {
let decValue = Decimal(stepValue)
let digits = decValue.significantFractionalDecimalDigits
formatter.minimumIntegerDigits = 1
formatter.minimumFractionDigits = showIntegerIfDoubleIsInteger ? 0 : digits
formatter.maximumFractionDigits = digits
}
public override func layoutSubviews() {
@ -177,51 +326,219 @@ import UIKit
leftButton.frame = CGRect(x: 0, y: 0, width: buttonWidth, height: bounds.size.height)
label.frame = CGRect(x: buttonWidth, y: 0, width: labelWidth, height: bounds.size.height)
rightButton.frame = CGRect(x: labelWidth + buttonWidth, y: 0, width: buttonWidth, height: bounds.size.height)
labelMaximumCenterX = label.center.x + labelSlideLength
labelMinimumCenterX = label.center.x - labelSlideLength
labelOriginalCenter = label.center
}
@objc private func leftButtonTapped(button: UIButton) {
func updateValue() {
if stepperState == .ShouldIncrease {
value += stepValue
} else if stepperState == .ShouldDecrease {
value -= stepValue
}
}
deinit {
resetTimer()
NotificationCenter.default.removeObserver(self)
}
/// 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.
// lazy var printTimerGaps: () -> () = {
// var prevTime: CFAbsoluteTime?
//
// return { _ in
// var now = CFAbsoluteTimeGetCurrent()
// if let prevTime = prevTime {
// print(now - prevTime)
// }
// prevTime = now
// }
// }()
}
// MARK: Pan Gesture
extension GMStepper {
@objc func handlePan(gesture: UIPanGestureRecognizer) {
switch gesture.state {
case .began:
leftButton.isEnabled = false
rightButton.isEnabled = false
case .changed:
let translation = gesture.translation(in: label)
gesture.setTranslation(CGPoint.zero, in: label)
let slidingRight = gesture.velocity(in: label).x > 0
let slidingLeft = gesture.velocity(in: label).x < 0
// Move the label with pan
if slidingRight {
label.center.x = min(labelMaximumCenterX, label.center.x + translation.x)
} else if slidingLeft {
label.center.x = max(labelMinimumCenterX, label.center.x + translation.x)
}
// When the label hits the edges, increase/decrease value and change button backgrounds
if label.center.x == labelMaximumCenterX {
// 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.
if panState != .HitRightEdge {
stepperState = .ShouldIncrease
panState = .HitRightEdge
}
animateLimitHitIfNeeded()
} else if label.center.x == labelMinimumCenterX {
if panState != .HitLeftEdge {
stepperState = .ShouldDecrease
panState = .HitLeftEdge
}
animateLimitHitIfNeeded()
} else {
panState = .Stable
stepperState = .Stable
resetTimer()
self.rightButton.backgroundColor = self.buttonsBackgroundColor
self.leftButton.backgroundColor = self.buttonsBackgroundColor
}
case .ended, .cancelled, .failed:
reset()
default:
break
}
}
@objc func handleLabelTap() {
didTouchLabel?(value)
}
@objc func reset() {
panState = .Stable
stepperState = .Stable
resetTimer()
leftButton.isEnabled = true
rightButton.isEnabled = true
label.isUserInteractionEnabled = true
UIView.animate(withDuration: self.labelSlideDuration, animations: {
self.label.center = self.labelOriginalCenter
self.rightButton.backgroundColor = self.buttonsBackgroundColor
self.leftButton.backgroundColor = self.buttonsBackgroundColor
})
}
}
// MARK: Button Events
extension GMStepper {
@objc func leftButtonTouchDown(button: UIButton) {
rightButton.isEnabled = false
label.isUserInteractionEnabled = false
resetTimer()
if value == minimumValue {
animateLimitHitForButton(leftButton)
animateLimitHitIfNeeded()
minimumExceeded?()
} else {
value -= 1
stepperState = .ShouldDecrease
animateSlideLeft()
}
}
@objc private func rightButtonTapped(button: UIButton) {
@objc func rightButtonTouchDown(button: UIButton) {
leftButton.isEnabled = false
label.isUserInteractionEnabled = false
resetTimer()
if value == maximumValue {
animateLimitHitForButton(rightButton)
animateLimitHitIfNeeded()
} else {
value += 1
stepperState = .ShouldIncrease
animateSlideRight()
}
}
private func animateSlideLeft() {
UIView.animateWithDuration(labelSlideDuration, animations: {
self.label.center.x -= self.labelSlideLength
}, completion: { _ in
UIView.animateWithDuration(self.labelSlideDuration, animations: {
self.label.center.x += self.labelSlideLength
})
})
}
private func animateSlideRight() {
UIView.animateWithDuration(labelSlideDuration, animations: {
self.label.center.x += self.labelSlideLength
}, completion: { _ in
UIView.animateWithDuration(self.labelSlideDuration, animations: {
self.label.center.x -= self.labelSlideLength
})
})
}
private func animateLimitHitForButton(button: UIButton){
UIView.animateWithDuration(limitHitAnimationDuration, animations: {
button.backgroundColor = self.limitHitAnimationColor
}, completion: { _ in
button.backgroundColor = self.buttonsBackgroundColor
})
@objc func buttonTouchUp(button: UIButton) {
reset()
}
}
// MARK: Animations
extension GMStepper {
func animateSlideLeft() {
UIView.animate(withDuration: labelSlideDuration) {
self.label.center.x -= self.labelSlideLength
}
}
func animateSlideRight() {
UIView.animate(withDuration: labelSlideDuration) {
self.label.center.x += self.labelSlideLength
}
}
func animateToOriginalPosition() {
if self.label.center != self.labelOriginalCenter {
UIView.animate(withDuration: labelSlideDuration) {
self.label.center = self.labelOriginalCenter
}
}
}
func animateLimitHitIfNeeded() {
if value == minimumValue {
animateLimitHitForButton(button: leftButton)
} else if value == maximumValue {
animateLimitHitForButton(button: rightButton)
}
}
func animateLimitHitForButton(button: UIButton){
UIView.animate(withDuration: limitHitAnimationDuration) {
button.backgroundColor = self.limitHitAnimationColor
}
}
}
// MARK: Timer
extension GMStepper {
@objc func handleTimerFire(timer: Timer) {
timerFireCount += 1
if timerFireCount % timerFireCountModulo == 0 {
updateValue()
}
}
func scheduleTimer() {
timer = Timer.scheduledTimer(timeInterval: timerInterval, target: self, selector: #selector(GMStepper.handleTimerFire), userInfo: nil, repeats: true)
}
func resetTimer() {
if let timer = timer {
timer.invalidate()
self.timer = nil
timerFireCount = 0
}
}
}
private extension GMStepper {
func handleIsLimitReached() {
let isLimitReached = value == minimumValue
leftButton.alpha = isLimitReached ? leftButtonLimitOpacity : 1
}
}
extension Decimal {
var significantFractionalDecimalDigits: Int {
return max(-exponent, 0)
}
}

View File

@ -1,19 +0,0 @@
//
// GMStepper.h
// GMStepper
//
// Created by Gunay Mert Karadogan on 5/7/15.
// Copyright (c) 2015 Gunay Mert Karadogan. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for GMStepper.
FOUNDATION_EXPORT double GMStepperVersionNumber;
//! Project version string for GMStepper.
FOUNDATION_EXPORT const unsigned char GMStepperVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <GMStepper/PublicHeader.h>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -7,60 +7,30 @@
objects = {
/* Begin PBXBuildFile section */
3116C0DB1DA4DD360015AC69 /* GMStepperExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3116C0DA1DA4DD360015AC69 /* GMStepperExampleTests.swift */; };
3198AC771DA4DEE500311FB3 /* GMStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C195B1B48445E005EFEE5 /* GMStepper.swift */; };
319C19381B4843EB005EFEE5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C19371B4843EB005EFEE5 /* AppDelegate.swift */; };
319C193A1B4843EB005EFEE5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C19391B4843EB005EFEE5 /* ViewController.swift */; };
319C193D1B4843EB005EFEE5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 319C193B1B4843EB005EFEE5 /* Main.storyboard */; };
319C193F1B4843EB005EFEE5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 319C193E1B4843EB005EFEE5 /* Images.xcassets */; };
319C19421B4843EB005EFEE5 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 319C19401B4843EB005EFEE5 /* LaunchScreen.xib */; };
319C195C1B48445E005EFEE5 /* GMStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C195B1B48445E005EFEE5 /* GMStepper.swift */; };
31B104891B49A04D008C61B4 /* GMStepper.h in Headers */ = {isa = PBXBuildFile; fileRef = 31B104881B49A04D008C61B4 /* GMStepper.h */; settings = {ATTRIBUTES = (Public, ); }; };
31B1048F1B49A04D008C61B4 /* GMStepper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B104841B49A04D008C61B4 /* GMStepper.framework */; };
31B104981B49A04D008C61B4 /* GMStepperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B104971B49A04D008C61B4 /* GMStepperTests.swift */; };
31B1049B1B49A04D008C61B4 /* GMStepper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 31B104841B49A04D008C61B4 /* GMStepper.framework */; };
31B1049C1B49A04D008C61B4 /* GMStepper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 31B104841B49A04D008C61B4 /* GMStepper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
31B104A41B49A07D008C61B4 /* GMStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C195B1B48445E005EFEE5 /* GMStepper.swift */; };
31B104A51B49A0BB008C61B4 /* GMStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319C195B1B48445E005EFEE5 /* GMStepper.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
31B104901B49A04D008C61B4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 319C192A1B4843EB005EFEE5 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 31B104831B49A04D008C61B4;
remoteInfo = GMStepper;
};
31B104921B49A04D008C61B4 /* PBXContainerItemProxy */ = {
3116C0DD1DA4DD360015AC69 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 319C192A1B4843EB005EFEE5 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 319C19311B4843EB005EFEE5;
remoteInfo = GMStepperExample;
};
31B104991B49A04D008C61B4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 319C192A1B4843EB005EFEE5 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 31B104831B49A04D008C61B4;
remoteInfo = GMStepper;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
31B104A21B49A04D008C61B4 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
31B1049C1B49A04D008C61B4 /* GMStepper.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
3116C0D81DA4DD360015AC69 /* GMStepperExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GMStepperExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3116C0DA1DA4DD360015AC69 /* GMStepperExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GMStepperExampleTests.swift; sourceTree = "<group>"; };
3116C0DC1DA4DD360015AC69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
319C19321B4843EB005EFEE5 /* GMStepperExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GMStepperExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
319C19361B4843EB005EFEE5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
319C19371B4843EB005EFEE5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@ -69,48 +39,41 @@
319C193E1B4843EB005EFEE5 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
319C19411B4843EB005EFEE5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
319C195B1B48445E005EFEE5 /* GMStepper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GMStepper.swift; sourceTree = "<group>"; };
31B104841B49A04D008C61B4 /* GMStepper.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GMStepper.framework; sourceTree = BUILT_PRODUCTS_DIR; };
31B104871B49A04D008C61B4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
31B104881B49A04D008C61B4 /* GMStepper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GMStepper.h; sourceTree = "<group>"; };
31B1048E1B49A04D008C61B4 /* GMStepperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GMStepperTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
31B104961B49A04D008C61B4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
31B104971B49A04D008C61B4 /* GMStepperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GMStepperTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
3116C0D51DA4DD360015AC69 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
319C192F1B4843EB005EFEE5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
31B1049B1B49A04D008C61B4 /* GMStepper.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
31B104801B49A04D008C61B4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
31B1048B1B49A04D008C61B4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
31B1048F1B49A04D008C61B4 /* GMStepper.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3116C0D91DA4DD360015AC69 /* GMStepperExampleTests */ = {
isa = PBXGroup;
children = (
3116C0DA1DA4DD360015AC69 /* GMStepperExampleTests.swift */,
3116C0DC1DA4DD360015AC69 /* Info.plist */,
);
path = GMStepperExampleTests;
sourceTree = "<group>";
};
319C19291B4843EB005EFEE5 = {
isa = PBXGroup;
children = (
319C195A1B48445E005EFEE5 /* GMStepper */,
319C19341B4843EB005EFEE5 /* GMStepperExample */,
31B104851B49A04D008C61B4 /* GMStepper */,
31B104941B49A04D008C61B4 /* GMStepperTests */,
3116C0D91DA4DD360015AC69 /* GMStepperExampleTests */,
319C19331B4843EB005EFEE5 /* Products */,
);
sourceTree = "<group>";
@ -119,8 +82,7 @@
isa = PBXGroup;
children = (
319C19321B4843EB005EFEE5 /* GMStepperExample.app */,
31B104841B49A04D008C61B4 /* GMStepper.framework */,
31B1048E1B49A04D008C61B4 /* GMStepperTests.xctest */,
3116C0D81DA4DD360015AC69 /* GMStepperExampleTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -155,54 +117,27 @@
path = ../GMStepper;
sourceTree = "<group>";
};
31B104851B49A04D008C61B4 /* GMStepper */ = {
isa = PBXGroup;
children = (
31B104881B49A04D008C61B4 /* GMStepper.h */,
31B104861B49A04D008C61B4 /* Supporting Files */,
);
path = GMStepper;
sourceTree = "<group>";
};
31B104861B49A04D008C61B4 /* Supporting Files */ = {
isa = PBXGroup;
children = (
31B104871B49A04D008C61B4 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
31B104941B49A04D008C61B4 /* GMStepperTests */ = {
isa = PBXGroup;
children = (
31B104971B49A04D008C61B4 /* GMStepperTests.swift */,
31B104951B49A04D008C61B4 /* Supporting Files */,
);
path = GMStepperTests;
sourceTree = "<group>";
};
31B104951B49A04D008C61B4 /* Supporting Files */ = {
isa = PBXGroup;
children = (
31B104961B49A04D008C61B4 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
31B104811B49A04D008C61B4 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
31B104891B49A04D008C61B4 /* GMStepper.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
3116C0D71DA4DD360015AC69 /* GMStepperExampleTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3116C0DF1DA4DD360015AC69 /* Build configuration list for PBXNativeTarget "GMStepperExampleTests" */;
buildPhases = (
3116C0D41DA4DD360015AC69 /* Sources */,
3116C0D51DA4DD360015AC69 /* Frameworks */,
3116C0D61DA4DD360015AC69 /* Resources */,
);
buildRules = (
);
dependencies = (
3116C0DE1DA4DD360015AC69 /* PBXTargetDependency */,
);
name = GMStepperExampleTests;
productName = GMStepperExampleTests;
productReference = 3116C0D81DA4DD360015AC69 /* GMStepperExampleTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
319C19311B4843EB005EFEE5 /* GMStepperExample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 319C19511B4843EB005EFEE5 /* Build configuration list for PBXNativeTarget "GMStepperExample" */;
@ -210,74 +145,37 @@
319C192E1B4843EB005EFEE5 /* Sources */,
319C192F1B4843EB005EFEE5 /* Frameworks */,
319C19301B4843EB005EFEE5 /* Resources */,
31B104A21B49A04D008C61B4 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
31B1049A1B49A04D008C61B4 /* PBXTargetDependency */,
);
name = GMStepperExample;
productName = GMStepperExample;
productReference = 319C19321B4843EB005EFEE5 /* GMStepperExample.app */;
productType = "com.apple.product-type.application";
};
31B104831B49A04D008C61B4 /* GMStepper */ = {
isa = PBXNativeTarget;
buildConfigurationList = 31B104A11B49A04D008C61B4 /* Build configuration list for PBXNativeTarget "GMStepper" */;
buildPhases = (
31B1047F1B49A04D008C61B4 /* Sources */,
31B104801B49A04D008C61B4 /* Frameworks */,
31B104811B49A04D008C61B4 /* Headers */,
31B104821B49A04D008C61B4 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = GMStepper;
productName = GMStepper;
productReference = 31B104841B49A04D008C61B4 /* GMStepper.framework */;
productType = "com.apple.product-type.framework";
};
31B1048D1B49A04D008C61B4 /* GMStepperTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 31B104A31B49A04D008C61B4 /* Build configuration list for PBXNativeTarget "GMStepperTests" */;
buildPhases = (
31B1048A1B49A04D008C61B4 /* Sources */,
31B1048B1B49A04D008C61B4 /* Frameworks */,
31B1048C1B49A04D008C61B4 /* Resources */,
);
buildRules = (
);
dependencies = (
31B104911B49A04D008C61B4 /* PBXTargetDependency */,
31B104931B49A04D008C61B4 /* PBXTargetDependency */,
);
name = GMStepperTests;
productName = GMStepperTests;
productReference = 31B1048E1B49A04D008C61B4 /* GMStepperTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
319C192A1B4843EB005EFEE5 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0640;
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0800;
LastUpgradeCheck = 0900;
ORGANIZATIONNAME = "Gunay Mert Karadogan";
TargetAttributes = {
3116C0D71DA4DD360015AC69 = {
CreatedOnToolsVersion = 8.0;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
TestTargetID = 319C19311B4843EB005EFEE5;
};
319C19311B4843EB005EFEE5 = {
CreatedOnToolsVersion = 6.4;
};
31B104831B49A04D008C61B4 = {
CreatedOnToolsVersion = 6.4;
};
31B1048D1B49A04D008C61B4 = {
CreatedOnToolsVersion = 6.4;
TestTargetID = 319C19311B4843EB005EFEE5;
DevelopmentTeam = 289M6XEDV4;
LastSwiftMigration = 1000;
};
};
};
@ -295,13 +193,19 @@
projectRoot = "";
targets = (
319C19311B4843EB005EFEE5 /* GMStepperExample */,
31B104831B49A04D008C61B4 /* GMStepper */,
31B1048D1B49A04D008C61B4 /* GMStepperTests */,
3116C0D71DA4DD360015AC69 /* GMStepperExampleTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
3116C0D61DA4DD360015AC69 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
319C19301B4843EB005EFEE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -312,23 +216,18 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
31B104821B49A04D008C61B4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
31B1048C1B49A04D008C61B4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
3116C0D41DA4DD360015AC69 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3116C0DB1DA4DD360015AC69 /* GMStepperExampleTests.swift in Sources */,
3198AC771DA4DEE500311FB3 /* GMStepper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
319C192E1B4843EB005EFEE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -339,40 +238,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
31B1047F1B49A04D008C61B4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
31B104A41B49A07D008C61B4 /* GMStepper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
31B1048A1B49A04D008C61B4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
31B104981B49A04D008C61B4 /* GMStepperTests.swift in Sources */,
31B104A51B49A0BB008C61B4 /* GMStepper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
31B104911B49A04D008C61B4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 31B104831B49A04D008C61B4 /* GMStepper */;
targetProxy = 31B104901B49A04D008C61B4 /* PBXContainerItemProxy */;
};
31B104931B49A04D008C61B4 /* PBXTargetDependency */ = {
3116C0DE1DA4DD360015AC69 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 319C19311B4843EB005EFEE5 /* GMStepperExample */;
targetProxy = 31B104921B49A04D008C61B4 /* PBXContainerItemProxy */;
};
31B1049A1B49A04D008C61B4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 31B104831B49A04D008C61B4 /* GMStepper */;
targetProxy = 31B104991B49A04D008C61B4 /* PBXContainerItemProxy */;
targetProxy = 3116C0DD1DA4DD360015AC69 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
@ -396,6 +268,42 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
3116C0E01DA4DD360015AC69 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
INFOPLIST_FILE = GMStepperExampleTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.gmertk.GMStepperExampleTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_VERSION = 4.2;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
};
name = Debug;
};
3116C0E11DA4DD360015AC69 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
INFOPLIST_FILE = GMStepperExampleTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.gmertk.GMStepperExampleTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
};
name = Release;
};
319C194F1B4843EB005EFEE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -404,19 +312,28 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@ -448,13 +365,21 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@ -473,6 +398,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
@ -481,9 +407,13 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 289M6XEDV4;
INFOPLIST_FILE = GMStepperExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@ -491,89 +421,28 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 289M6XEDV4;
INFOPLIST_FILE = GMStepperExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
31B1049D1B49A04D008C61B4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = GMStepper/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
31B1049E1B49A04D008C61B4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = GMStepper/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
31B1049F1B49A04D008C61B4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = GMStepperTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
};
name = Debug;
};
31B104A01B49A04D008C61B4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = GMStepperTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GMStepperExample.app/GMStepperExample";
SWIFT_VERSION = 4.2;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3116C0DF1DA4DD360015AC69 /* Build configuration list for PBXNativeTarget "GMStepperExampleTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3116C0E01DA4DD360015AC69 /* Debug */,
3116C0E11DA4DD360015AC69 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
319C192D1B4843EB005EFEE5 /* Build configuration list for PBXProject "GMStepperExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@ -592,22 +461,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
31B104A11B49A04D008C61B4 /* Build configuration list for PBXNativeTarget "GMStepper" */ = {
isa = XCConfigurationList;
buildConfigurations = (
31B1049D1B49A04D008C61B4 /* Debug */,
31B1049E1B49A04D008C61B4 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
31B104A31B49A04D008C61B4 /* Build configuration list for PBXNativeTarget "GMStepperTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
31B1049F1B49A04D008C61B4 /* Debug */,
31B104A01B49A04D008C61B4 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 319C192A1B4843EB005EFEE5 /* Project object */;

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
version = "1.8">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "31B104831B49A04D008C61B4"
BuildableName = "GMStepper.framework"
BlueprintName = "GMStepper"
ReferencedContainer = "container:GMStepperExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "31B104831B49A04D008C61B4"
BuildableName = "GMStepper.framework"
BlueprintName = "GMStepper"
ReferencedContainer = "container:GMStepperExample.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "31B104831B49A04D008C61B4"
BuildableName = "GMStepper.framework"
BlueprintName = "GMStepper"
ReferencedContainer = "container:GMStepperExample.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -14,33 +14,33 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(application: UIApplication) {
func applicationWillResignActive(_ application: UIApplication) {
// 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.
// 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.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
func applicationDidEnterBackground(_ application: UIApplication) {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// 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.
func applicationWillEnterForeground(_ application: UIApplication) {
// 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.
}
func applicationDidBecomeActive(application: UIApplication) {
func applicationDidBecomeActive(_ application: UIApplication) {
// 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.
}
func applicationWillTerminate(application: UIApplication) {
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<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">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
@ -13,17 +14,20 @@
<subviews>
<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">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<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">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<animations/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>

View File

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<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">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
@ -14,102 +16,92 @@
<viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AU6-4C-B2F" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
<rect key="frame" x="24" y="28" width="552" height="44"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="6mC-hP-wFD"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="minimumValue">
<integer key="value" value="1"/>
<userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
<real key="value" value="25"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="stepValue">
<real key="value" value="5"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="if7-U5-bAM" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
<rect key="frame" x="140" y="116" width="320" height="66"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="66" id="iQi-6P-vt9"/>
<constraint firstAttribute="width" constant="320" id="ji4-Pf-1fZ"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="minimumValue">
<integer key="value" value="7"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
<integer key="value" value="10"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
<color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
<color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="1" green="0.3591497541" blue="0.36842127060000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="limitHitAnimationColor">
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="stepValue">
<real key="value" value="0.1"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="R9n-I0-fq7" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
<rect key="frame" x="200" y="226" width="200" height="66"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="200" id="dVu-w0-mf0"/>
<constraint firstAttribute="height" constant="66" id="ie8-vl-NAV"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
<color key="value" red="0.1819814891" green="0.69426733259999995" blue="0.53024792669999998" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.1819814891" green="0.69426733259999995" blue="0.53024792669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
<color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="minimumValue">
<integer key="value" value="9"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
<integer key="value" value="13"/>
<color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="limitHitAnimationColor">
<color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.6588235294" green="0.85882352939999995" blue="0.6588235294" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="U8X-8Z-7Mo" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
<rect key="frame" x="24" y="336" width="552" height="44"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="aF3-T7-dIP"/>
<constraint firstAttribute="width" constant="200" id="vhP-7K-vOu"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.90823972230000005" green="0.92638683320000004" blue="0.93171715740000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
<color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="labelWidthWeight">
<real key="value" value="0.69999999999999996"/>
@ -117,10 +109,13 @@
<userDefinedRuntimeAttribute type="string" keyPath="leftButtonText" value="😞"/>
<userDefinedRuntimeAttribute type="string" keyPath="rightButtonText" value="☺️"/>
<userDefinedRuntimeAttribute type="number" keyPath="minimumValue">
<integer key="value" value="5"/>
<integer key="value" value="0"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="limitHitAnimationColor">
<color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="value" red="0.98624199629999998" green="0.77968657019999998" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
<integer key="value" value="100"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<variation key="default">
@ -129,8 +124,44 @@
</mask>
</variation>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9Ri-Yr-sRs" customClass="GMStepper" customModule="GMStepperExample" customModuleProvider="target">
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="180" id="dhO-Nd-SFk"/>
<constraint firstAttribute="height" constant="50" id="xPS-vU-cZc"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="maximumValue">
<real key="value" value="10"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="stepValue">
<real key="value" value="1"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
<real key="value" value="2"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<real key="value" value="4"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsBackgroundColor">
<color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="buttonsTextColor">
<color key="value" red="1" green="0.47058823529999999" blue="0.15686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="borderColor">
<color key="value" red="1" green="0.47058823529999999" blue="0.15686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelBackgroundColor">
<color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="color" keyPath="labelTextColor">
<color key="value" red="1" green="0.47058823529999999" blue="0.15686274510000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="R9n-I0-fq7" firstAttribute="centerX" secondItem="U8X-8Z-7Mo" secondAttribute="centerX" id="3cD-WW-Qg4"/>
<constraint firstItem="if7-U5-bAM" firstAttribute="top" secondItem="AU6-4C-B2F" secondAttribute="bottom" constant="44" id="662-W9-CUn"/>
@ -140,7 +171,9 @@
<constraint firstItem="if7-U5-bAM" firstAttribute="centerX" secondItem="R9n-I0-fq7" secondAttribute="centerX" id="K7g-rC-ehJ"/>
<constraint firstItem="U8X-8Z-7Mo" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" constant="8" id="S1b-pD-UXA"/>
<constraint firstItem="U8X-8Z-7Mo" firstAttribute="top" secondItem="R9n-I0-fq7" secondAttribute="bottom" constant="44" id="fBW-Xx-pa0"/>
<constraint firstItem="9Ri-Yr-sRs" firstAttribute="centerX" secondItem="kh9-bI-dsS" secondAttribute="centerX" id="fay-qT-jKR"/>
<constraint firstItem="AU6-4C-B2F" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" constant="8" id="iIM-b2-jzV"/>
<constraint firstItem="9Ri-Yr-sRs" firstAttribute="top" secondItem="U8X-8Z-7Mo" secondAttribute="bottom" constant="44" id="nKi-Fp-8B7"/>
<constraint firstAttribute="trailingMargin" secondItem="U8X-8Z-7Mo" secondAttribute="trailing" constant="8" id="ppd-nb-fL8"/>
<constraint firstItem="AU6-4C-B2F" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" constant="8" symbolic="YES" id="zDK-gF-kms"/>
</constraints>
@ -151,6 +184,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="274" y="363"/>
</scene>
</scenes>
</document>

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -13,10 +13,10 @@ class ViewController: UIViewController {
@IBOutlet weak var stepper: GMStepper!
override func viewDidLoad() {
super.viewDidLoad()
stepper.addTarget(self, action: "stepperValueChanged:", forControlEvents: .ValueChanged)
stepper.addTarget(self, action: #selector(ViewController.stepperValueChanged), for: .valueChanged)
}
func stepperValueChanged(stepper: GMStepper) {
println(stepper.value)
@objc func stepperValueChanged(stepper: GMStepper) {
print(stepper.value, terminator: "")
}
}

View File

@ -1,16 +1,15 @@
//
// GMStepperTests.swift
// GMStepperTests
// GMStepperExampleTests.swift
// GMStepperExampleTests
//
// Created by Gunay Mert Karadogan on 5/7/15.
// Created by Gunay Mert Karadogan on 4/7/15.
// Copyright (c) 2015 Gunay Mert Karadogan. All rights reserved.
//
import UIKit
import XCTest
import UIKit
class GMStepperTests: XCTestCase {
class GMStepperExampleTests: XCTestCase {
var stepper: GMStepper!
override func setUp() {
@ -20,7 +19,7 @@ class GMStepperTests: XCTestCase {
func testDefaults() {
XCTAssert(stepper.minimumValue == 0, "minimumValue defaults 0")
XCTAssert(stepper.maximumValue == 10, "maximumValue defaults to 10")
XCTAssert(stepper.maximumValue == 100, "maximumValue defaults to 100")
XCTAssert(stepper.value == 0, "value defaults to 0")
}
@ -39,5 +38,5 @@ class GMStepperTests: XCTestCase {
XCTAssert(stepper.value == stepper.maximumValue, "Pass")
}
}

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.gunaymert.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@ -16,8 +16,6 @@
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>

View File

@ -3,11 +3,12 @@
[![License](https://img.shields.io/cocoapods/l/GMStepper.svg?style=flat)](http://cocoapods.org/pods/GMStepper)
[![Platform](https://img.shields.io/cocoapods/p/GMStepper.svg?style=flat)](http://cocoapods.org/pods/GMStepper)
A stepper with a sliding label in the middle.
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/).
## Screenshot
![Screenshot_0.gif](https://raw.githubusercontent.com/gmertk/GMStepper/master/Screenshots/screenshot_0.gif)
![Screenshot_1.gif](https://raw.githubusercontent.com/gmertk/GMStepper/master/Screenshots/screenshot_1.gif)
## Usage
@ -19,7 +20,7 @@ it, simply add the following lines to your Podfile:
use_frameworks!
pod "GMStepper"
```
## Setup
If 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.
@ -27,13 +28,22 @@ If you want to use storyboards, just drop a UIView into your storyboard and set
## Properties
```swift
/// Current value of the stepper. Defaults to 0.
var value: Int = 0
var value: Double = 0
/// Minimum value. Must be less than maximumValue. Defaults to 0.
var minimumValue: Int = 0
var minimumValue: Double = 0
/// Maximum value. Must be more than minimumValue. Defaults to 10.
var maximumValue: Int = 10
/// Maximum value. Must be more than minimumValue. Defaults to 100.
var maximumValue: Double = 100
/// Step/Increment value as in UIStepper. Defaults to 1.
var stepValue: Double = 1
/// The same as UIStepper's autorepeat. If true, holding on the buttons or keeping the pan gesture alters the value repeatedly. Defaults to true.
var autorepeat: Bool = true
/// If the value is integer, it is shown without floating point.
var showIntegerIfDoubleIsInteger: Bool = true
/// Text on the left button. Be sure that it fits in the button. Defaults to "-".
var leftButtonText: String = "-"
@ -59,20 +69,30 @@ var labelBackgroundColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alph
/// Font of the middle label. Defaults to AvenirNext-Bold, 25.0 points in size.
var labelFont = UIFont(name: "AvenirNext-Bold", size: 25.0)
/// Corner radius of the middle label's layer. Defaults to 0.0.
var labelCornerRadius: CGFloat = 0.0
/// Corner radius of the stepper's layer. Defaults to 4.0.
var cornerRadius: CGFloat = 4.0
/// Border width of the stepper and middle label's layer. Defaults to 0.0.
var borderWidth: CGFloat = 0.0
/// Color of the border of the stepper and middle label's layer. Defaults to clear color.
var borderColor: UIColor = UIColor.clearColor()
/// 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.
var labelWidthWeight: CGFloat = 0.5
var labelWidthWeight: CGFloat = 0.5
/// Color of the flashing animation on the buttons in case the value hit the limit.
var limitHitAnimationColor: UIColor = UIColor(red:0.26, green:0.6, blue:0.87, alpha:1)
```
## Author
## Authors
Günay Mert Karadoğan, mertkaradogan@gmail.com
* [Brent Whitman](https://github.com/bwhtmn) - Maintainer
* [Günay Mert Karadoğan](https://github.com/gmertk) - Creator
## License

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB