From fe436774aaee4952bd603d94f5c2b4954aa7f25b Mon Sep 17 00:00:00 2001 From: EyreFree Date: Sat, 27 Jul 2019 17:12:41 +0800 Subject: [PATCH] 5.1.0 --- CHANGELOG.md | 6 + EFCountingLabel.podspec | 2 +- EFCountingLabel/Classes/EFCount.swift | 58 ++-- EFCountingLabel/Classes/EFCountAdapter.swift | 22 +- EFCountingLabel/Classes/EFTimingMethod.swift | 12 +- Example/EFCountingLabel/AppDelegate.swift | 7 +- .../ListTableViewController.swift | 78 ++++-- .../CustomTableViewController.swift | 63 +++-- .../StoryboardButtonViewController.swift | 48 +++- .../StoryboardLabelViewController.swift | 57 ++-- Example/Podfile.lock | 2 +- Example/Pods/Manifest.lock | 2 +- Example/Pods/Pods.xcodeproj/project.pbxproj | 262 +++++++++--------- README.md | 59 ++-- README_CN.md | 59 ++-- 15 files changed, 391 insertions(+), 346 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcfa7f0..3f214d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ----- +## [5.1.0](https://github.com/EFPrefix/EFCountingLabel/releases/tag/5.1.0) (2019-07-27) + +- Refactoring. + +--- + ## [5.0.0](https://github.com/EFPrefix/EFCountingLabel/releases/tag/5.0.0) (2019-03-30) - Upgrade to Swift 5.0. diff --git a/EFCountingLabel.podspec b/EFCountingLabel.podspec index db9057f..e77aec9 100644 --- a/EFCountingLabel.podspec +++ b/EFCountingLabel.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'EFCountingLabel' - s.version = '5.0.0' + s.version = '5.1.0' s.summary = 'A label which can show number change animated.' s.description = <<-DESC diff --git a/EFCountingLabel/Classes/EFCount.swift b/EFCountingLabel/Classes/EFCount.swift index dbb9f3b..55313ce 100644 --- a/EFCountingLabel/Classes/EFCount.swift +++ b/EFCountingLabel/Classes/EFCount.swift @@ -1,3 +1,11 @@ +// +// EFCount.swift +// EFCountingLabel +// +// Created by Kirow on 2019/05/14. +// +// Copyright (c) 2017 EyreFree +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights @@ -33,15 +41,15 @@ extension EFCount { public func countFromZeroTo(_ endValue: CGFloat, withDuration duration: TimeInterval) { countFrom(0, to: endValue, withDuration: duration) } - + public func countFrom(_ startValue: CGFloat, to endValue: CGFloat) { countFrom(startValue, to: endValue, withDuration: 0) } - + public func countFromCurrentValueTo(_ endValue: CGFloat) { countFromCurrentValueTo(endValue, withDuration: 0) } - + public func countFromZeroTo(_ endValue: CGFloat) { countFromZeroTo(endValue, withDuration: 0) } @@ -49,27 +57,27 @@ extension EFCount { public class EFCounter { public var timingFunction: EFTiming = EFTimingFunction.linear - + public var updateBlock: ((CGFloat) -> Void)? public var completionBlock: (() -> Void)? - + public private(set) var fromValue: CGFloat = 0 public private(set) var toValue: CGFloat = 1 private var currentDuration: TimeInterval = 0 public private(set) var totalDuration: TimeInterval = 1 private var lastUpdate: TimeInterval = 0 - + private var timer: CADisplayLink? - + public var isCounting: Bool { return timer != nil } - + public var progress: CGFloat { guard totalDuration != 0 else { return 1 } return CGFloat(currentDuration / totalDuration) } - + public var currentValue: CGFloat { if currentDuration == 0 { return 0 @@ -78,36 +86,36 @@ public class EFCounter { } return fromValue + timingFunction.update(progress) * (toValue - fromValue) } - + public init() { - + } - + // CADisplayLink callback @objc public func updateValue(_ timer: Timer) { let now = CACurrentMediaTime() currentDuration += now - lastUpdate lastUpdate = now - + if currentDuration >= totalDuration { invalidate() currentDuration = totalDuration } - + updateBlock?(currentValue) - + if currentDuration == totalDuration { runCompletionBlock() } } - + private func runCompletionBlock() { if let tryCompletionBlock = completionBlock { completionBlock = nil tryCompletionBlock() } } - + //set init values public func reset() { invalidate() @@ -117,7 +125,7 @@ public class EFCounter { lastUpdate = 0 totalDuration = 1 } - + public func invalidate() { timer?.invalidate() timer = nil @@ -128,25 +136,25 @@ extension EFCounter: EFCount { public func countFromCurrentValueTo(_ endValue: CGFloat, withDuration duration: TimeInterval) { countFrom(currentValue, to: endValue, withDuration: duration) } - + public func countFrom(_ startValue: CGFloat, to endValue: CGFloat, withDuration duration: TimeInterval) { fromValue = startValue toValue = endValue - + // remove any (possible) old timers invalidate() - + if duration == 0.0 { // No animation updateBlock?(endValue) runCompletionBlock() return } - + currentDuration = 0 totalDuration = duration lastUpdate = CACurrentMediaTime() - + let timer = CADisplayLink(target: self, selector: #selector(updateValue(_:))) if #available(iOS 10.0, *) { timer.preferredFramesPerSecond = 30 @@ -157,9 +165,9 @@ extension EFCounter: EFCount { timer.add(to: .main, forMode: .tracking) self.timer = timer } - + public func stopCountAtCurrentValue() { invalidate() updateBlock?(currentValue) } -} \ No newline at end of file +} diff --git a/EFCountingLabel/Classes/EFCountAdapter.swift b/EFCountingLabel/Classes/EFCountAdapter.swift index e7b416f..3b8a3da 100644 --- a/EFCountingLabel/Classes/EFCountAdapter.swift +++ b/EFCountingLabel/Classes/EFCountAdapter.swift @@ -1,3 +1,11 @@ +// +// EFCountAdapter.swift +// EFCountingLabel +// +// Created by Kirow on 2019/05/14. +// +// Copyright (c) 2017 EyreFree +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights @@ -33,7 +41,7 @@ extension EFCountAdapter { counter.updateBlock = nil } } - + public func setCompletionBlock(_ completion: ((_ sender: Self) -> Void)?) { if let completion = completion { counter.completionBlock = { [unowned self] in @@ -43,15 +51,15 @@ extension EFCountAdapter { counter.completionBlock = nil } } - + public func countFrom(_ startValue: CGFloat, to endValue: CGFloat, withDuration duration: TimeInterval) { counter.countFrom(startValue, to: endValue, withDuration: duration) } - + public func countFromCurrentValueTo(_ endValue: CGFloat, withDuration duration: TimeInterval) { countFrom(counter.currentValue, to: endValue, withDuration: duration) } - + public func stopCountAtCurrentValue() { counter.stopCountAtCurrentValue() } @@ -99,7 +107,7 @@ open class EFCountingButton: UIButton, EFCountAdapter { return nil } } - + deinit { counter.invalidate() } @@ -107,7 +115,7 @@ open class EFCountingButton: UIButton, EFCountAdapter { open class EFCountingLabel: UILabel, EFCountAdapter { public private(set) var counter = EFCounter() - + open var formatBlock: ((CGFloat) -> String)? { set { if let formatBlock = newValue { @@ -147,7 +155,7 @@ open class EFCountingLabel: UILabel, EFCountAdapter { return nil } } - + deinit { counter.invalidate() } diff --git a/EFCountingLabel/Classes/EFTimingMethod.swift b/EFCountingLabel/Classes/EFTimingMethod.swift index 40c3fec..439453b 100644 --- a/EFCountingLabel/Classes/EFTimingMethod.swift +++ b/EFCountingLabel/Classes/EFTimingMethod.swift @@ -1,6 +1,6 @@ // // EFTimingMethod.swift -// EFTimingMethod +// EFCountingLabel // // Created by Kirow on 2019/05/14. // @@ -26,12 +26,12 @@ public enum EFTimingFunction: EFTiming { case linear - case easeIn(easingRate: CGFloat) - case easeOut(easingRate: CGFloat) - case easeInOut(easingRate: CGFloat) + case easeIn(easingRate: CGFloat = 3) + case easeOut(easingRate: CGFloat = 3) + case easeInOut(easingRate: CGFloat = 3) case easeInBounce case easeOutBounce - + public func update(_ time: CGFloat) -> CGFloat { switch self { case .linear: @@ -67,4 +67,4 @@ public enum EFTimingFunction: EFTiming { return 63.0 / 64.0 + pow(11.0 / 4.0, 2) * pow(time - 21.0 / 22.0, 2) } } -} \ No newline at end of file +} diff --git a/Example/EFCountingLabel/AppDelegate.swift b/Example/EFCountingLabel/AppDelegate.swift index d1a6b60..2166a0b 100644 --- a/Example/EFCountingLabel/AppDelegate.swift +++ b/Example/EFCountingLabel/AppDelegate.swift @@ -28,11 +28,10 @@ import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - + var window: UIWindow? - - func application(_ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { UIApplication.shared.isStatusBarHidden = false return true } diff --git a/Example/EFCountingLabel/ListTableViewController.swift b/Example/EFCountingLabel/ListTableViewController.swift index efceb01..fbf182c 100644 --- a/Example/EFCountingLabel/ListTableViewController.swift +++ b/Example/EFCountingLabel/ListTableViewController.swift @@ -1,79 +1,103 @@ // -// Created by Kirow on 2019-05-26. -// Copyright (c) 2019 CocoaPods. All rights reserved. +// ListTableViewController.swift +// EFCountingLabel // +// Created by Kirow on 2019-05-26. +// +// Copyright (c) 2017 EyreFree +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. import Foundation import UIKit import EFCountingLabel class ListTableViewController: UITableViewController { - + @IBOutlet weak var createButtonCell: UITableViewCell! @IBOutlet weak var createLabelCell: UITableViewCell! - + var refreshLabelBlock: (() -> Void)? - + private func present(countingView: T) -> UIViewController where T: UIView { countingView.translatesAutoresizingMaskIntoConstraints = false - + let controller = UIViewController() controller.view.backgroundColor = .white - + controller.view.addSubview(countingView) countingView.centerXAnchor.constraint(equalTo: controller.view.centerXAnchor).isActive = true countingView.centerYAnchor.constraint(equalTo: controller.view.centerYAnchor).isActive = true - + navigationController?.pushViewController(controller, animated: true) - + return controller } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let cell = tableView.cellForRow(at: indexPath) else { return } - + switch cell { case createButtonCell: showControllerWithButton() case createLabelCell: showControllerWithLabel() default: return } } - + func showControllerWithLabel() { let label = EFCountingLabel() label.counter.timingFunction = EFTimingFunction.easeOut(easingRate: 4) label.setUpdateBlock { value, label in label.text = String(format: "%.2f%%", value) } - + //do not retain to release label immediately after pop viewController refreshLabelBlock = { [unowned label] in label.countFromZeroTo(100, withDuration: 10) } - + let controller = present(countingView: label) - + refreshLabelBlock?() - - controller.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .refresh, target: self, - action: #selector(didClickRefreshLabel(_:))) + + controller.navigationItem.rightBarButtonItem = UIBarButtonItem( + barButtonSystemItem: .refresh, + target: self, + action: #selector(didClickRefreshLabel(_:)) + ) } - + @objc func didClickRefreshLabel(_ sender: UIBarButtonItem) { refreshLabelBlock?() } - + func showControllerWithButton() { let button = EFCountingButton(type: .custom) button.counter.timingFunction = EFTimingFunction.easeInOut(easingRate: 2) button.setTitleColor(.black, for: .normal) button.backgroundColor = .orange button.layer.cornerRadius = 10 - + button.widthAnchor.constraint(equalToConstant: 120).isActive = true - + button.setTitle("Start Counter", for: .normal) button.setUpdateBlock { value, button in button.setTitle(String(format: "%.2f%%", value), for: .normal) @@ -81,12 +105,12 @@ class ListTableViewController: UITableViewController { button.setCompletionBlock { button in button.setTitle("Restart Counter", for: .normal) } - + button.addTarget(self, action: #selector(didClickCountingButton(_:)), for: .touchUpInside) - + _ = present(countingView: button) } - + @objc func didClickCountingButton(_ sender: EFCountingButton) { if sender.counter.isCounting { sender.stopCountAtCurrentValue() @@ -94,6 +118,4 @@ class ListTableViewController: UITableViewController { sender.countFromZeroTo(100, withDuration: 10) } } - - -} \ No newline at end of file +} diff --git a/Example/EFCountingLabel/ViewControllers/CustomTableViewController.swift b/Example/EFCountingLabel/ViewControllers/CustomTableViewController.swift index b651872..31b5433 100644 --- a/Example/EFCountingLabel/ViewControllers/CustomTableViewController.swift +++ b/Example/EFCountingLabel/ViewControllers/CustomTableViewController.swift @@ -1,7 +1,28 @@ // -// Created by Kirow on 2019-05-26. -// Copyright (c) 2019 CocoaPods. All rights reserved. +// CustomTableViewController.swift +// EFCountingLabel // +// Created by Kirow on 2019-05-26. +// +// Copyright (c) 2017 EyreFree +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. import Foundation import UIKit @@ -9,7 +30,7 @@ import EFCountingLabel struct CounterCellModel { let counter: EFCounter - + init(from: CGFloat, to: CGFloat, duration: TimeInterval, function: EFTiming = EFTimingFunction.linear) { self.counter = EFCounter() self.counter.timingFunction = function @@ -18,59 +39,58 @@ struct CounterCellModel { } class CountingTableViewCell: UITableViewCell { - + weak var counter: EFCounter? - + func setCounter(_ model: CounterCellModel, formatter: NumberFormatter) { //unbind counter from cell if let current = self.counter { current.updateBlock = nil } - + if let from = formatter.string(from: NSNumber(value: Int(model.counter.fromValue))), - let to = formatter.string(from: NSNumber(value: Int(model.counter.toValue))) { + let to = formatter.string(from: NSNumber(value: Int(model.counter.toValue))) { textLabel?.text = "Count from \(from) to \(to)" } - + //bind new counter model.counter.updateBlock = { [unowned self] value in self.detailTextLabel?.text = formatter.string(from: NSNumber(value: Int(value))) } - + counter = model.counter } - } class CustomTableViewController: UIViewController { @IBOutlet weak var tableView: UITableView! - + lazy var formatter: NumberFormatter = { let formatter = NumberFormatter() formatter.groupingSeparator = "." - + formatter.usesGroupingSeparator = true formatter.groupingSize = 3 return formatter }() - + var dataSource: [CounterCellModel] = [] - + override func viewDidLoad() { super.viewDidLoad() remakeDataSource() tableView.reloadData() } - + @IBAction func didClickRefresh(_ sender: UIBarButtonItem) { remakeDataSource() tableView.reloadData() } - + private func remakeDataSource() { dataSource.forEach({ $0.counter.invalidate() }) dataSource.removeAll() - + var prevValue: CGFloat = 0 for i in 1...12 { let from = prevValue @@ -80,26 +100,25 @@ class CustomTableViewController: UIViewController { prevValue = to } } - + deinit { dataSource.forEach({ $0.counter.invalidate() }) } } - extension CustomTableViewController: UITableViewDelegate, UITableViewDataSource { public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataSource.count } - + public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "CountingTableViewCell") as? CountingTableViewCell else { fatalError() } - + let model = dataSource[indexPath.row] cell.setCounter(model, formatter: formatter) - + return cell } } diff --git a/Example/EFCountingLabel/ViewControllers/StoryboardButtonViewController.swift b/Example/EFCountingLabel/ViewControllers/StoryboardButtonViewController.swift index c4e8ce6..dcbc0b4 100644 --- a/Example/EFCountingLabel/ViewControllers/StoryboardButtonViewController.swift +++ b/Example/EFCountingLabel/ViewControllers/StoryboardButtonViewController.swift @@ -1,30 +1,50 @@ // -// Created by Kirow on 2019-05-26. -// Copyright (c) 2019 CocoaPods. All rights reserved. +// StoryboardButtonViewController.swift +// EFCountingLabel // +// Created by Kirow on 2019-05-26. +// +// Copyright (c) 2017 EyreFree +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. import Foundation import UIKit import EFCountingLabel - class StoryboardButtonViewController: UIViewController { @IBOutlet weak var countDownButton: EFCountingButton! @IBOutlet weak var stoppableButton: EFCountingButton! - + override func viewDidLoad() { super.viewDidLoad() - + let textAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 14, weight: .bold), .foregroundColor: UIColor.darkText ] - + let valueAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 18, weight: .ultraLight), .foregroundColor: UIColor.red ] - + stoppableButton.setUpdateBlock { value, button in button.setTitle("\(value)", for: .normal) let attributed = NSMutableAttributedString() @@ -32,28 +52,27 @@ class StoryboardButtonViewController: UIViewController { attributed.append(NSAttributedString(string: String(format: "%.04f", value), attributes: valueAttributes)) button.setAttributedTitle(attributed, for: .normal) } - + stoppableButton.setCompletionBlock { button in button.counter.reset() button.setTitle("Press to Start", for: .normal) } - + countDownButton.setUpdateBlock { value, button in button.setTitle("\(Int(value))", for: .normal) } - + countDownButton.setCompletionBlock { button in button.setTitle("Count Down", for: .normal) } - } - + @IBAction func didClickCountDownButton(_ sender: EFCountingButton) { if !sender.counter.isCounting { sender.countFrom(10, to: 0, withDuration: 10) } } - + @IBAction func didClickStopButton(_ sender: EFCountingButton) { if sender.counter.isCounting { sender.stopCountAtCurrentValue() @@ -63,8 +82,7 @@ class StoryboardButtonViewController: UIViewController { } else { sender.contentHorizontalAlignment = .left sender.countFromCurrentValueTo(1000000, withDuration: 20) - + } - } } diff --git a/Example/EFCountingLabel/ViewControllers/StoryboardLabelViewController.swift b/Example/EFCountingLabel/ViewControllers/StoryboardLabelViewController.swift index 1e330f5..0a44d9e 100644 --- a/Example/EFCountingLabel/ViewControllers/StoryboardLabelViewController.swift +++ b/Example/EFCountingLabel/ViewControllers/StoryboardLabelViewController.swift @@ -1,47 +1,68 @@ // -// Created by Kirow on 2019-05-26. -// Copyright (c) 2019 CocoaPods. All rights reserved. +// StoryboardLabelViewController.swift +// EFCountingLabel // +// Created by Kirow on 2019-05-26. +// +// Copyright (c) 2017 EyreFree +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. import Foundation import UIKit import EFCountingLabel class StoryboardLabelViewController: UIViewController { - + @IBOutlet weak var simpleCounterLabel: EFCountingLabel! @IBOutlet weak var attributedCountLabel: EFCountingLabel! @IBOutlet weak var timingCounterLabel: EFCountingLabel! @IBOutlet weak var completionCounterLabel: EFCountingLabel! - + override func viewDidLoad() { super.viewDidLoad() - + //simple label setup simpleCounterLabel.setUpdateBlock { value, label in label.text = String(format: "%d", Int(value)) } - + //attributed label setup let highlightAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont(name: "HelveticaNeue", size: 20) ?? UIFont.systemFont(ofSize: 20) ] - + let normalAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont(name: "HelveticaNeue-UltraLight", size: 20) ?? UIFont.systemFont(ofSize: 20) ] - + attributedCountLabel.setUpdateBlock { value, label in let prefix = String(format: "%d", Int(value)) let postfix = String(format: "/%d", 100) - + let prefixAttr = NSMutableAttributedString(string: prefix, attributes: highlightAttributes) let postfixAttr = NSAttributedString(string: postfix, attributes: normalAttributes) prefixAttr.append(postfixAttr) - + label.attributedText = prefixAttr } - + //timing label setup let formatter = NumberFormatter() formatter.numberStyle = .decimal @@ -49,27 +70,25 @@ class StoryboardLabelViewController: UIViewController { label.text = "Score: " + (formatter.string(from: NSNumber(value: Int(value))) ?? "") } timingCounterLabel.counter.timingFunction = EFTimingFunction.easeOut(easingRate: 3) - - + //completion label setup completionCounterLabel.setUpdateBlock { value, label in label.text = String(format: "%i%%", Int(value)) } - + completionCounterLabel.setCompletionBlock { label in label.textColor = UIColor(red: 0, green: 0.5, blue: 0, alpha: 1) } - - + startCount() } - + @IBAction func startCount() { simpleCounterLabel.countFrom(1, to: 10, withDuration: 3.0) timingCounterLabel.countFrom(0, to: 10000, withDuration: 2.5) attributedCountLabel.countFrom(0, to: 100, withDuration: 2.5) - + completionCounterLabel.textColor = .darkText completionCounterLabel.countFrom(0, to: 100, withDuration: 4) } -} \ No newline at end of file +} diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 4869f88..dd10311 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 18006cf8308f1ddc4db21317a6cf556416d587b1 -COCOAPODS: 1.7.0 +COCOAPODS: 1.7.5 diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index 4869f88..dd10311 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 18006cf8308f1ddc4db21317a6cf556416d587b1 -COCOAPODS: 1.7.0 +COCOAPODS: 1.7.5 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 9050562..f154684 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,29 +7,29 @@ objects = { /* Begin PBXBuildFile section */ - 1070573C1E1B8CA300A20F5281858AF2 /* EFTimingMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1472D3235BDBC3BF3188A31F0DEEDBD6 /* EFTimingMethod.swift */; }; - 55DE45DFC78EE4DFFB469AE7E8F5BE80 /* EFCountAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5DF3BCAAE7A3F89BF3A894393FF77FD /* EFCountAdapter.swift */; }; - 796042A8368D0BCD22F5067CAFBC9AAA /* Pods-EFCountingLabel_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CFB60A8A0636D3156E365D8E97630977 /* Pods-EFCountingLabel_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 99BD2673543CE37CDBB8BD77F3E2A7BE /* EFCountingLabel-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CD6344AA5AB8530F79D6D6764111030 /* EFCountingLabel-dummy.m */; }; - A7668615A02C8C0AB40535A43E15EF2E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; - B6F120A3E3709F329A8B496489BAED25 /* Pods-EFCountingLabel_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 03AD160971F8E453D87B755BE0C3C73F /* Pods-EFCountingLabel_Example-dummy.m */; }; - BE467AE21FB5AB3CCC73836103FF166A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; - C4E3E9AFE3F78473E52C5805D91BC484 /* Pods-EFCountingLabel_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B87957D051F840B09E442BD2872E46A8 /* Pods-EFCountingLabel_Tests-dummy.m */; }; - C51BD10C806D78E1F24D3538B3F84D78 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; - CA6C4B7F9DA47D5B8747791EE4ABA338 /* EFCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3BA4587F159B32F6842390E030C25F /* EFCount.swift */; }; - DF8794213EEFAD6B2E1D39C87076CD2A /* Pods-EFCountingLabel_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1653CDC9D6E3900BEBD4B6FE574D6FC6 /* Pods-EFCountingLabel_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E5FBFEF301E81B265F543C46C0844477 /* EFCountingLabel-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAE910C2B97E4852C942B947FAC1F4A /* EFCountingLabel-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2030C0BD04C6FE221FB08A14D029E097 /* Pods-EFCountingLabel_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 03AD160971F8E453D87B755BE0C3C73F /* Pods-EFCountingLabel_Example-dummy.m */; }; + 24970E61EFC148F124B13DA21200E44B /* Pods-EFCountingLabel_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B87957D051F840B09E442BD2872E46A8 /* Pods-EFCountingLabel_Tests-dummy.m */; }; + 2A2AC199E504660604EDA6DAB86EBF9E /* EFCountingLabel-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAE910C2B97E4852C942B947FAC1F4A /* EFCountingLabel-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2E9F70E53DF558816F8EF5794BD8A39E /* EFCountAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5DF3BCAAE7A3F89BF3A894393FF77FD /* EFCountAdapter.swift */; }; + 2F1116A617E6B4AC325A142835ECECEC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + 46E4C58B2F4A507735F280036130D20A /* EFTimingMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1472D3235BDBC3BF3188A31F0DEEDBD6 /* EFTimingMethod.swift */; }; + 4DBBD6C29C515FBD9D693A99F640B2BF /* Pods-EFCountingLabel_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1653CDC9D6E3900BEBD4B6FE574D6FC6 /* Pods-EFCountingLabel_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4DC54E51ECD6D08BC366578BA4E7982A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + 4F334D216196E032FB47C2E3A5872704 /* EFCountingLabel-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CD6344AA5AB8530F79D6D6764111030 /* EFCountingLabel-dummy.m */; }; + 820EFD1568A1189BFF89BF65933CBE9F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + F1A867186CB8C80A13D6C7DEF75697A5 /* EFCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C3BA4587F159B32F6842390E030C25F /* EFCount.swift */; }; + F7AB21C08B052A19B47DB09B36ADDB26 /* Pods-EFCountingLabel_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CFB60A8A0636D3156E365D8E97630977 /* Pods-EFCountingLabel_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 7528D4093B510B2016E8D24530EBB7A0 /* PBXContainerItemProxy */ = { + 376372BF4D7E62D33101037E088B139B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 8C4582010343B9B88E6D43FB890130C9; remoteInfo = "Pods-EFCountingLabel_Example"; }; - 92D50A755015C935850BBE0B8F53FCCF /* PBXContainerItemProxy */ = { + 5588D3660451B3EA397D771C18F98B82 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; @@ -51,15 +51,15 @@ 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 38147FE581C08350930DCDC6884202DA /* Pods-EFCountingLabel_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-EFCountingLabel_Tests-acknowledgements.markdown"; sourceTree = ""; }; 4AA26DDA8FF36EE3034003B8A38591F5 /* EFCountingLabel.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = EFCountingLabel.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 5EBFFBCF9E56DA4AF71E6A1981521E28 /* EFCountingLabel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = EFCountingLabel.framework; path = EFCountingLabel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 5FCB0AD06832AF841C3D5A06093D29D3 /* Pods-EFCountingLabel_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-EFCountingLabel_Example.modulemap"; sourceTree = ""; }; - 68BD45FDCADBE44BB1A1DD892EADD13D /* Pods_EFCountingLabel_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_EFCountingLabel_Tests.framework; path = "Pods-EFCountingLabel_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64484A7ECC99C41AA0499383F4DC8157 /* Pods_EFCountingLabel_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_EFCountingLabel_Tests.framework; path = "Pods-EFCountingLabel_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 75F9DADB329292DCDA3696F5EFB1FE08 /* Pods_EFCountingLabel_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_EFCountingLabel_Example.framework; path = "Pods-EFCountingLabel_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 7656696EF20F921F44EAA42B0E19A86E /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; 7C3BA4587F159B32F6842390E030C25F /* EFCount.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EFCount.swift; path = EFCountingLabel/Classes/EFCount.swift; sourceTree = ""; }; 7C5CC72CC53F6EDCEB7844FB8B8C0085 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; 7CD6344AA5AB8530F79D6D6764111030 /* EFCountingLabel-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "EFCountingLabel-dummy.m"; sourceTree = ""; }; - 891D0BF5D243CB4AF7DD531AF078ED6A /* Pods_EFCountingLabel_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_EFCountingLabel_Example.framework; path = "Pods-EFCountingLabel_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - A05C17F2FC14F4EF84EACA5043DF897A /* EFCountingLabel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = EFCountingLabel.framework; path = EFCountingLabel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B72AE3A853FF2ABD2F3FF343E8BCD815 /* Pods-EFCountingLabel_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-EFCountingLabel_Tests.modulemap"; sourceTree = ""; }; B87957D051F840B09E442BD2872E46A8 /* Pods-EFCountingLabel_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-EFCountingLabel_Tests-dummy.m"; sourceTree = ""; }; C7873A1764BC773CAABCE0CBD1CE77B0 /* EFCountingLabel.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = EFCountingLabel.xcconfig; sourceTree = ""; }; @@ -76,27 +76,27 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 03C80E20B5D93E3B8747E286CBC06199 /* Frameworks */ = { + 4CB0066236F62A084B7370BFA5175040 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BE467AE21FB5AB3CCC73836103FF166A /* Foundation.framework in Frameworks */, + 2F1116A617E6B4AC325A142835ECECEC /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5D445095A6471536D4555D95F44957A4 /* Frameworks */ = { + 4FC1EF6B9DB01E4626B9F608934616A0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C51BD10C806D78E1F24D3538B3F84D78 /* Foundation.framework in Frameworks */, + 820EFD1568A1189BFF89BF65933CBE9F /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 844A98193DD0181538BF35E74C9A622F /* Frameworks */ = { + B470023E252E235D6D04AEA2E18530FF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A7668615A02C8C0AB40535A43E15EF2E /* Foundation.framework in Frameworks */, + 4DC54E51ECD6D08BC366578BA4E7982A /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -160,9 +160,9 @@ 5F48950C6E5D66C419CF07FC3D07B2CE /* Products */ = { isa = PBXGroup; children = ( - A05C17F2FC14F4EF84EACA5043DF897A /* EFCountingLabel.framework */, - 891D0BF5D243CB4AF7DD531AF078ED6A /* Pods_EFCountingLabel_Example.framework */, - 68BD45FDCADBE44BB1A1DD892EADD13D /* Pods_EFCountingLabel_Tests.framework */, + 5EBFFBCF9E56DA4AF71E6A1981521E28 /* EFCountingLabel.framework */, + 75F9DADB329292DCDA3696F5EFB1FE08 /* Pods_EFCountingLabel_Example.framework */, + 64484A7ECC99C41AA0499383F4DC8157 /* Pods_EFCountingLabel_Tests.framework */, ); name = Products; sourceTree = ""; @@ -230,27 +230,27 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 56E14661D61F5450E024D88F7DCC98DE /* Headers */ = { + 1C6B97ECFE5D5D28BBC9542CEBA9D902 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - E5FBFEF301E81B265F543C46C0844477 /* EFCountingLabel-umbrella.h in Headers */, + 2A2AC199E504660604EDA6DAB86EBF9E /* EFCountingLabel-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 7ECD7F17A471C6E8F7706848DA7C2059 /* Headers */ = { + 785BA2E3A4EA76D5B4F2BDB01C8EAF62 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 796042A8368D0BCD22F5067CAFBC9AAA /* Pods-EFCountingLabel_Example-umbrella.h in Headers */, + 4DBBD6C29C515FBD9D693A99F640B2BF /* Pods-EFCountingLabel_Tests-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - C21D77B7B097C9C9AAE2C55817302123 /* Headers */ = { + 82A6C8683F273335FC23D6F46226A2C5 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - DF8794213EEFAD6B2E1D39C87076CD2A /* Pods-EFCountingLabel_Tests-umbrella.h in Headers */, + F7AB21C08B052A19B47DB09B36ADDB26 /* Pods-EFCountingLabel_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -259,31 +259,31 @@ /* Begin PBXNativeTarget section */ 8C4582010343B9B88E6D43FB890130C9 /* Pods-EFCountingLabel_Example */ = { isa = PBXNativeTarget; - buildConfigurationList = 9B5EAF5B37CFD9C1477DCE779E67300D /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Example" */; + buildConfigurationList = CFB7E478A7B5BF81EEC649C0D1915735 /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Example" */; buildPhases = ( - 7ECD7F17A471C6E8F7706848DA7C2059 /* Headers */, - 39D3B6519B41472602E24DBDC4AB41B2 /* Sources */, - 03C80E20B5D93E3B8747E286CBC06199 /* Frameworks */, - D4D84E29808C4E59E50C74C2C30DF125 /* Resources */, + 82A6C8683F273335FC23D6F46226A2C5 /* Headers */, + 7B482A4E6D14EF7AE8371BF9755BD5CC /* Sources */, + 4FC1EF6B9DB01E4626B9F608934616A0 /* Frameworks */, + ACE85E0F95F1F3515F5EBA20C729D040 /* Resources */, ); buildRules = ( ); dependencies = ( - 0C8980F3E0A17FEA5839440152A3DDF5 /* PBXTargetDependency */, + 9EC5DE094DCA60B8709DD3ED1FB20AD0 /* PBXTargetDependency */, ); name = "Pods-EFCountingLabel_Example"; productName = "Pods-EFCountingLabel_Example"; - productReference = 891D0BF5D243CB4AF7DD531AF078ED6A /* Pods_EFCountingLabel_Example.framework */; + productReference = 75F9DADB329292DCDA3696F5EFB1FE08 /* Pods_EFCountingLabel_Example.framework */; productType = "com.apple.product-type.framework"; }; 8D87E5A9FC1F8F56498963BEA9EDFE7A /* EFCountingLabel */ = { isa = PBXNativeTarget; - buildConfigurationList = 4292598DB4E727168C30EDCEE710E63C /* Build configuration list for PBXNativeTarget "EFCountingLabel" */; + buildConfigurationList = 14114E04A57A6E889A8AB768089F3FF2 /* Build configuration list for PBXNativeTarget "EFCountingLabel" */; buildPhases = ( - 56E14661D61F5450E024D88F7DCC98DE /* Headers */, - FAAD5C2007B70D95691FAE31CCE81D15 /* Sources */, - 5D445095A6471536D4555D95F44957A4 /* Frameworks */, - EE5FE66F40113B3B9746FF81AF21FA36 /* Resources */, + 1C6B97ECFE5D5D28BBC9542CEBA9D902 /* Headers */, + FF4C03218B39446A6E0B97C35A28345F /* Sources */, + B470023E252E235D6D04AEA2E18530FF /* Frameworks */, + 504078AF28E44AC7EC62FB7174169BA1 /* Resources */, ); buildRules = ( ); @@ -291,26 +291,26 @@ ); name = EFCountingLabel; productName = EFCountingLabel; - productReference = A05C17F2FC14F4EF84EACA5043DF897A /* EFCountingLabel.framework */; + productReference = 5EBFFBCF9E56DA4AF71E6A1981521E28 /* EFCountingLabel.framework */; productType = "com.apple.product-type.framework"; }; B0F85C85FC1A7A5C9193CC47492B429F /* Pods-EFCountingLabel_Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 3A307B924BEE0348F4E4FCB86EFAAC77 /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Tests" */; + buildConfigurationList = B32D7FB7CE0460F76A743F252BC65AB2 /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Tests" */; buildPhases = ( - C21D77B7B097C9C9AAE2C55817302123 /* Headers */, - A2023ABC758724D4BC539A0FB3566157 /* Sources */, - 844A98193DD0181538BF35E74C9A622F /* Frameworks */, - D063ECA84BDF88A43703882F7CC5502E /* Resources */, + 785BA2E3A4EA76D5B4F2BDB01C8EAF62 /* Headers */, + 067A26798E992C43807E73341520E732 /* Sources */, + 4CB0066236F62A084B7370BFA5175040 /* Frameworks */, + D81BEC4E7ED82E13FB85EE27DD0AAFED /* Resources */, ); buildRules = ( ); dependencies = ( - 28A430DB2F8493A60C8B72E4194A341B /* PBXTargetDependency */, + 80CB48CBCFB16B806FC5B427ADBDFFDE /* PBXTargetDependency */, ); name = "Pods-EFCountingLabel_Tests"; productName = "Pods-EFCountingLabel_Tests"; - productReference = 68BD45FDCADBE44BB1A1DD892EADD13D /* Pods_EFCountingLabel_Tests.framework */; + productReference = 64484A7ECC99C41AA0499383F4DC8157 /* Pods_EFCountingLabel_Tests.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -319,8 +319,8 @@ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1020; - LastUpgradeCheck = 1020; + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; @@ -342,21 +342,21 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - D063ECA84BDF88A43703882F7CC5502E /* Resources */ = { + 504078AF28E44AC7EC62FB7174169BA1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - D4D84E29808C4E59E50C74C2C30DF125 /* Resources */ = { + ACE85E0F95F1F3515F5EBA20C729D040 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - EE5FE66F40113B3B9746FF81AF21FA36 /* Resources */ = { + D81BEC4E7ED82E13FB85EE27DD0AAFED /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -366,54 +366,54 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 39D3B6519B41472602E24DBDC4AB41B2 /* Sources */ = { + 067A26798E992C43807E73341520E732 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B6F120A3E3709F329A8B496489BAED25 /* Pods-EFCountingLabel_Example-dummy.m in Sources */, + 24970E61EFC148F124B13DA21200E44B /* Pods-EFCountingLabel_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - A2023ABC758724D4BC539A0FB3566157 /* Sources */ = { + 7B482A4E6D14EF7AE8371BF9755BD5CC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C4E3E9AFE3F78473E52C5805D91BC484 /* Pods-EFCountingLabel_Tests-dummy.m in Sources */, + 2030C0BD04C6FE221FB08A14D029E097 /* Pods-EFCountingLabel_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - FAAD5C2007B70D95691FAE31CCE81D15 /* Sources */ = { + FF4C03218B39446A6E0B97C35A28345F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CA6C4B7F9DA47D5B8747791EE4ABA338 /* EFCount.swift in Sources */, - 55DE45DFC78EE4DFFB469AE7E8F5BE80 /* EFCountAdapter.swift in Sources */, - 99BD2673543CE37CDBB8BD77F3E2A7BE /* EFCountingLabel-dummy.m in Sources */, - 1070573C1E1B8CA300A20F5281858AF2 /* EFTimingMethod.swift in Sources */, + F1A867186CB8C80A13D6C7DEF75697A5 /* EFCount.swift in Sources */, + 2E9F70E53DF558816F8EF5794BD8A39E /* EFCountAdapter.swift in Sources */, + 4F334D216196E032FB47C2E3A5872704 /* EFCountingLabel-dummy.m in Sources */, + 46E4C58B2F4A507735F280036130D20A /* EFTimingMethod.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 0C8980F3E0A17FEA5839440152A3DDF5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = EFCountingLabel; - target = 8D87E5A9FC1F8F56498963BEA9EDFE7A /* EFCountingLabel */; - targetProxy = 92D50A755015C935850BBE0B8F53FCCF /* PBXContainerItemProxy */; - }; - 28A430DB2F8493A60C8B72E4194A341B /* PBXTargetDependency */ = { + 80CB48CBCFB16B806FC5B427ADBDFFDE /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Pods-EFCountingLabel_Example"; target = 8C4582010343B9B88E6D43FB890130C9 /* Pods-EFCountingLabel_Example */; - targetProxy = 7528D4093B510B2016E8D24530EBB7A0 /* PBXContainerItemProxy */; + targetProxy = 376372BF4D7E62D33101037E088B139B /* PBXContainerItemProxy */; + }; + 9EC5DE094DCA60B8709DD3ED1FB20AD0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = EFCountingLabel; + target = 8D87E5A9FC1F8F56498963BEA9EDFE7A /* EFCountingLabel */; + targetProxy = 5588D3660451B3EA397D771C18F98B82 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 2236389BB76DBC3C99877BD344A40B8E /* Release */ = { + 48C55CC40D4957F47734037F8F6B47B9 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C81588BB56B75D425E8D9A36FF3EC746 /* Pods-EFCountingLabel_Tests.release.xcconfig */; + baseConfigurationReference = 1EFBE3A78B27DC1330FC7FF43C8F2BC0 /* Pods-EFCountingLabel_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; @@ -439,11 +439,10 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; 4BE66A09A74FD25164AAB3C2645B9B93 /* Release */ = { isa = XCBuildConfiguration; @@ -505,6 +504,38 @@ }; name = Release; }; + 7D91F06BB64DE78C4ECDB94ED32F1DF9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C7873A1764BC773CAABCE0CBD1CE77B0 /* EFCountingLabel.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/EFCountingLabel/EFCountingLabel-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/EFCountingLabel/EFCountingLabel-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/EFCountingLabel/EFCountingLabel.modulemap"; + PRODUCT_MODULE_NAME = EFCountingLabel; + PRODUCT_NAME = EFCountingLabel; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; 7EF7227D9B20A1D549000096ACCB23D7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -569,9 +600,9 @@ }; name = Debug; }; - ACAC07C68B3CF0F869B10080669F110A /* Release */ = { + A9A24C9334AC8E004CCC5F682CC03C59 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FF5C152FC56C4D532DFA882CD1ED0E99 /* Pods-EFCountingLabel_Example.release.xcconfig */; + baseConfigurationReference = D8CDAA9A313CCF8FBB622265D33E9F24 /* Pods-EFCountingLabel_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; @@ -597,15 +628,14 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - B919EB876FC6A16D808C709A0088CA27 /* Debug */ = { + B28AFC5B08621C8189A05CAC4CA4C98C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1EFBE3A78B27DC1330FC7FF43C8F2BC0 /* Pods-EFCountingLabel_Tests.debug.xcconfig */; + baseConfigurationReference = C81588BB56B75D425E8D9A36FF3EC746 /* Pods-EFCountingLabel_Tests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; @@ -631,44 +661,13 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - C4B6D09F00E180E2FAF1B5A41F158CD3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C7873A1764BC773CAABCE0CBD1CE77B0 /* EFCountingLabel.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/EFCountingLabel/EFCountingLabel-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/EFCountingLabel/EFCountingLabel-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/EFCountingLabel/EFCountingLabel.modulemap"; - PRODUCT_MODULE_NAME = EFCountingLabel; - PRODUCT_NAME = EFCountingLabel; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - C56260C5DCCC8737D0C539594AE773BF /* Debug */ = { + E1855C02B62E07FAD9C2F20A5EE66EA3 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = C7873A1764BC773CAABCE0CBD1CE77B0 /* EFCountingLabel.xcconfig */; buildSettings = { @@ -699,9 +698,9 @@ }; name = Debug; }; - C8B4C19AC31EF19A04BAA8D78E7DC1E4 /* Debug */ = { + F982390348FBCCBA1AF164B776685DB9 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D8CDAA9A313CCF8FBB622265D33E9F24 /* Pods-EFCountingLabel_Example.debug.xcconfig */; + baseConfigurationReference = FF5C152FC56C4D532DFA882CD1ED0E99 /* Pods-EFCountingLabel_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; @@ -727,46 +726,47 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 3A307B924BEE0348F4E4FCB86EFAAC77 /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Tests" */ = { + 14114E04A57A6E889A8AB768089F3FF2 /* Build configuration list for PBXNativeTarget "EFCountingLabel" */ = { isa = XCConfigurationList; buildConfigurations = ( - B919EB876FC6A16D808C709A0088CA27 /* Debug */, - 2236389BB76DBC3C99877BD344A40B8E /* Release */, + E1855C02B62E07FAD9C2F20A5EE66EA3 /* Debug */, + 7D91F06BB64DE78C4ECDB94ED32F1DF9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4292598DB4E727168C30EDCEE710E63C /* Build configuration list for PBXNativeTarget "EFCountingLabel" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - C56260C5DCCC8737D0C539594AE773BF /* Debug */, - C4B6D09F00E180E2FAF1B5A41F158CD3 /* Release */, + 7EF7227D9B20A1D549000096ACCB23D7 /* Debug */, + 4BE66A09A74FD25164AAB3C2645B9B93 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + B32D7FB7CE0460F76A743F252BC65AB2 /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 7EF7227D9B20A1D549000096ACCB23D7 /* Debug */, - 4BE66A09A74FD25164AAB3C2645B9B93 /* Release */, + 48C55CC40D4957F47734037F8F6B47B9 /* Debug */, + B28AFC5B08621C8189A05CAC4CA4C98C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9B5EAF5B37CFD9C1477DCE779E67300D /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Example" */ = { + CFB7E478A7B5BF81EEC649C0D1915735 /* Build configuration list for PBXNativeTarget "Pods-EFCountingLabel_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( - C8B4C19AC31EF19A04BAA8D78E7DC1E4 /* Debug */, - ACAC07C68B3CF0F869B10080669F110A /* Release */, + A9A24C9334AC8E004CCC5F682CC03C59 /* Debug */, + F982390348FBCCBA1AF164B776685DB9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/README.md b/README.md index b1aaeff..e5d5159 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ To run the example project, clone the repo, and run `pod install` from the Examp |:--------|:-------------------------------------| | 1.x | Xcode 8.0+
Swift 3.0+
iOS 8.0+ | | 4.x | Xcode 9.0+
Swift 4.0+
iOS 8.0+ | -| 5.x | Xcode 9.0+
Swift 5.0+
iOS 8.0+ | +| 5.x | Xcode 10.0+
Swift 5.0+
iOS 8.0+ | ## Installation @@ -68,27 +68,18 @@ You can also add it to your `xib` or `storyboard` , just make sure you set the c ### Use -Set the format of your label. This will be filled with a single int or float (depending on how you format it) when it updates: +Set the format of your label. This will be filled with string (depending on how you format it) when it updates, you can provide a `formatBlock`, which permits greate control over how the text is formatted: ```swift -myLabel.format = "%d" -``` - -Alternatively, you can provide a `formatBlock`, which permits greater control over how the text is formatted: - -```swift -myLabel.formatBlock = { -      (value) in -      return "Score: " + (formatter.string(from: NSNumber(value: Int(value))) ?? "") +myLabel.setUpdateBlock { value, label in + label.text = String(format: "%.2f%%", value) } ``` -There is also a `attributedFormatBlock` to use an attributed string. If the `formatBlock` is specified, it takes precedence over the `format`. - -Optionally, set the mode. The default is `EFLabelCountingMethod.linear`, which will not change speed until it reaches the end. Other options are described below in the Methods section. +Optionally, set the timing function. The default is `EFTimingFunction.linear`, which will not change speed until it reaches the end. Other options are described below in the Methods section. ```swift -myLabel.method = .easeOut +myLabel.counter.timingFunction = EFTimingFunction.easeOut(easingRate: 3) ``` When you want the label to start counting, just call: @@ -103,12 +94,6 @@ You can also specify the duration. The default is 2.0 seconds. myLabel.countFrom(1, to: 10, withDuration: 3.0) ``` -Additionally, there is `animationDuration` property which you can use to override the default animation duration. - -```swift -myLabel.animationDuration = 1.0 -``` - You can use common convinient methods for counting, such as: ```swift @@ -119,45 +104,33 @@ myLabel.countFromZeroTo(100) Behind the scenes, these convinient methods use one base method, which has the following full signature: ```swift -myLabel.countFrom( - startValue: CGFloat, -      to: CGFloat, - withDuration: TimeInterval -) +myLabel.countFrom(startValue: CGFloat, to: CGFloat, withDuration: TimeInterval) ``` You can get current value of your label using `currentValue` method (works correctly in the process of animation too): ```swift -let currentValue = myLabel.currentValue() +let currentValue: CGFloat = myLabel.counter.currentValue ``` Optionally, you can specify a `completionBlock` to perform an acton when the label has finished counting: ```swift -myLabel.completionBlock = { - () in - print("finish") +myLabel.completionBlock = { () in + print("finish") } ``` -### Formats - -When you set the `format` property, the label will look for the presence of integer [conversion specifiers](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html) like `%d`, `%-i`, `%+o`, `%llu`, `%1$ 1X`, etc., and if found, will cast the value to `Int` before formatting the string. Otherwise, it will format it using a `CGFloat`, expecting a float conversion specifier like `%f`, `%e`, `%g`, `%a`, etc. - -If you're using a `CGFloat` value, it's recommended to limit the number of digits with a format string, such as `"%.1f"` for one decimal place. - -Because it uses the standard `String(format: String, arguments: CVarArg...)` method, you can also include arbitrary text in your format, such as `"Points: %i"`. - ### Modes There are currently four modes of counting. -- EFLabelCountingMethod.linear: Counts linearly from the start to the end; -- EFLabelCountingMethod.easeIn: Ease In starts out slow and speeds up counting as it gets to the end, stopping suddenly at the final value; -- EFLabelCountingMethod.easeOut: Ease Out starts out fast and slows down as it gets to the destination value; -- EFLabelCountingMethod.easeInOut: Ease In/Out starts out slow, speeds up towards the middle, and then slows down as it approaches the destination. It is a nice, smooth curve that looks great, and is the default method. -- ... +- EFTimingFunction.linear: Counts linearly from the start to the end; +- EFTimingFunction.easeIn: Ease In starts out slow and speeds up counting as it gets to the end, stopping suddenly at the final value; +- EFTimingFunction.easeOut: Ease Out starts out fast and slows down as it gets to the destination value; +- EFTimingFunction.easeInOut: Ease In/Out starts out slow, speeds up towards the middle, and then slows down as it approaches the destination. It is a nice, smooth curve that looks great, and is the default method; +- EFTimingFunction.easeInBounce; +- EFTimingFunction.easeOutBounce. ## Apps using EFCountingLabel diff --git a/README_CN.md b/README_CN.md index 6312fe7..b1826e7 100644 --- a/README_CN.md +++ b/README_CN.md @@ -54,7 +54,7 @@ git clone git@github.com:EFPrefix/EFCountingLabel.git; cd EFCountingLabel/Exampl |:--------|:-------------------------------------| | 1.x | Xcode 8.0+
Swift 3.0+
iOS 8.0+ | | 4.x | Xcode 9.0+
Swift 4.0+
iOS 8.0+ | -| 5.x | Xcode 9.0+
Swift 5.0+
iOS 8.0+ | +| 5.x | Xcode 10.0+
Swift 5.0+
iOS 8.0+ | ## 安装 @@ -85,27 +85,18 @@ self.view.addSubview(myLabel) ### 使用 -设置标签格式. 设置标签格式后,标签会在更新数值的时候以你设置的方式填充,默认是显示 float 类型的数值,也可以设置成显示 int 类型的数值,比如下面的代码: +设置标签格式. 设置标签格式后,标签会在更新数值的时候以你设置的方式填充,你可以使用 `formatBlock`,这个可以对显示的文本格式进行高度的自定义: ```swift -myLabel.format = "%d" -``` - -另外,你也可以使用 `formatBlock`,这个可以对显示的文本格式进行更加高度的自定义: - -```swift -myLabel.formatBlock = { -      (value) in -      return "Score: " + (formatter.string(from: NSNumber(value: Int(value))) ?? "") +myLabel.setUpdateBlock { value, label in + label.text = String(format: "%.2f%%", value) } ``` -除此之外还有一个 `attributedFormatBlock` 用于设置属性字符串的格式,用法和上面的 block 类似。如果指定了以上两个 `formatBlock` 中的任意一个,它将会覆盖掉 `format`属性,因为 block 的优先级更高。 - -可选项,设置动画样式,默认的动画样式是 `EFLabelCountingMethod.linear`,这个样式是匀速显示动画。以下将介绍其他动画样式及用法: +可选项,设置动画样式,默认的动画样式是 `EFTimingFunction.linear`,这个样式是匀速显示动画。以下将介绍其他动画样式及用法: ```swift -myLabel.method = .easeOut +myLabel.counter.timingFunction = EFTimingFunction.easeOut(easingRate: 3) ``` 需要计数时只需要使用以下方法即可: @@ -120,12 +111,6 @@ myLabel.countFrom(5, to: 100) myLabel.countFrom(1, to: 10, withDuration: 3.0) ``` -另外,也可以使用 `animationDuration` 属性去设置动画时长。 - -```swift -myLabel.animationDuration = 1.0 -``` - 可以使用便利方法计数,例如: ```swift @@ -136,45 +121,33 @@ myLabel.countFromZeroTo(100) 本质上,这些便利方法都是基于一个总方法封装的,以下就是这个方法完整的声明: ```swift -myLabel.countFrom( - startValue: CGFloat, -      to: CGFloat, - withDuration: TimeInterval -) +myLabel.countFrom(startValue: CGFloat, to: CGFloat, withDuration: TimeInterval) ``` 可以使用 `currentValue` 方法获得当前数据(即使在动画过程中也可以正常获得): ```swift -let currentValue = myLabel.currentValue() +let currentValue: CGFloat = myLabel.counter.currentValue ``` 可选项,可以使用 `completionBlock` 获得动画结束的事件: ```swift -myLabel.completionBlock = { - () in - print("finish") +myLabel.completionBlock = { () in + print("finish") } ``` -### 格式 - -当设置 `format` 属性后,标签会检测是否有 `%[^fega]*[diouxc]` 格式,如果能找到,就会将内容以 `Int` 类型展示。否则,将会使用默认的 `CGFloat` 类型展示。 - -假如你需要以 `CGFloat` 类型展示,最好设置小数点位数限制,例如使用 `@"%.1f"` 来限制只显示一位小数。 - -因为使用了标准的 `String(format: String, arguments: CVarArg...)` 方法,你可以按照自己的意愿自定义格式,例如:`@"Points: %i"`。 - ### 模式 当前有多种动画模式: -- EFLabelCountingMethod.linear:匀速计数动画,是默认采用的动画样式; -- EFLabelCountingMethod.easeIn:开始比较缓慢,快结束时加速,结束时突然停止; -- EFLabelCountingMethod.easeOut:开始速度很快,快结束时变得缓慢; -- EFLabelCountingMethod.easeInOut:开始时比较缓慢,中间加速,快结束时减速。动画速度是一个平滑的曲线。 -- ... +- EFTimingFunction.linear:匀速计数动画,是默认采用的动画样式; +- EFTimingFunction.easeIn:开始比较缓慢,快结束时加速,结束时突然停止; +- EFTimingFunction.easeOut:开始速度很快,快结束时变得缓慢; +- EFTimingFunction.easeInOut:开始时比较缓慢,中间加速,快结束时减速。动画速度是一个平滑的曲线。 +- EFTimingFunction.easeInBounce; +- EFTimingFunction.easeOutBounce。 ## 使用 EFCountingLabel 的应用