├── .gitignore ├── LICENSE ├── PP-iOS学习交流群群二维码.png ├── PPCounter IOSDemo ├── PPCounter IOSDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ ├── AndyPang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── duoyi.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── AndyPang.xcuserdatad │ │ └── xcschemes │ │ │ ├── PPCounter IOSDemo.xcscheme │ │ │ └── xcschememanagement.plist │ │ ├── YiAi.xcuserdatad │ │ └── xcschemes │ │ │ ├── PPCounter IOSDemo.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── duoyi.xcuserdatad │ │ └── xcschemes │ │ ├── PPCounter IOSDemo.xcscheme │ │ └── xcschememanagement.plist └── PPCounter IOSDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── PPCounter MacOSDemo ├── PPCounter MacOSDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ ├── AndyPang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── duoyi.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── AndyPang.xcuserdatad │ │ └── xcschemes │ │ │ ├── PPCounter MacOSDemo.xcscheme │ │ │ └── xcschememanagement.plist │ │ ├── YiAi.xcuserdatad │ │ └── xcschemes │ │ │ ├── PPCounter MacOSDemo.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── duoyi.xcuserdatad │ │ └── xcschemes │ │ ├── PPCounter MacOSDemo.xcscheme │ │ └── xcschememanagement.plist └── PPCounter MacOSDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── PPCounter.podspec ├── PPCounter.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ ├── AndyPang.xcuserdatad │ └── UserInterfaceState.xcuserstate │ ├── YiAi.xcuserdatad │ └── UserInterfaceState.xcuserstate │ └── duoyi.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── PPCounter ├── Core │ ├── PPCounterConst.h │ ├── PPCounterConst.m │ ├── PPCounterEngine.h │ └── PPCounterEngine.m ├── PPCounter.h └── UIKit │ ├── UIButton+PPCounter.h │ ├── UIButton+PPCounter.m │ ├── UILabel+PPCounter.h │ └── UILabel+PPCounter.m ├── Picture ├── Mac.gif ├── PPCounter.gif └── PPCounter.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 jkpang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PP-iOS学习交流群群二维码.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PP-iOS学习交流群群二维码.png -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 22F0EA341E6DB30D00FF7F7D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F0EA331E6DB30D00FF7F7D /* main.m */; }; 11 | 22F0EA371E6DB30D00FF7F7D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F0EA361E6DB30D00FF7F7D /* AppDelegate.m */; }; 12 | 22F0EA3A1E6DB30D00FF7F7D /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F0EA391E6DB30D00FF7F7D /* ViewController.m */; }; 13 | 22F0EA3D1E6DB30D00FF7F7D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22F0EA3B1E6DB30D00FF7F7D /* Main.storyboard */; }; 14 | 22F0EA3F1E6DB30D00FF7F7D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22F0EA3E1E6DB30D00FF7F7D /* Assets.xcassets */; }; 15 | 22F0EA421E6DB30D00FF7F7D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22F0EA401E6DB30D00FF7F7D /* LaunchScreen.storyboard */; }; 16 | 35F3C0CE1E6FDC960018D3C0 /* PPCounterConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F3C0C51E6FDC960018D3C0 /* PPCounterConst.m */; }; 17 | 35F3C0CF1E6FDC960018D3C0 /* PPCounterEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F3C0C71E6FDC960018D3C0 /* PPCounterEngine.m */; }; 18 | 35F3C0D01E6FDC960018D3C0 /* UIButton+PPCounter.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F3C0CB1E6FDC960018D3C0 /* UIButton+PPCounter.m */; }; 19 | 35F3C0D11E6FDC960018D3C0 /* UILabel+PPCounter.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F3C0CD1E6FDC960018D3C0 /* UILabel+PPCounter.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 22F0EA2F1E6DB30D00FF7F7D /* PPCounter IOSDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PPCounter IOSDemo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 22F0EA331E6DB30D00FF7F7D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | 22F0EA351E6DB30D00FF7F7D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | 22F0EA361E6DB30D00FF7F7D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | 22F0EA381E6DB30D00FF7F7D /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 22F0EA391E6DB30D00FF7F7D /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | 22F0EA3C1E6DB30D00FF7F7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 22F0EA3E1E6DB30D00FF7F7D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 22F0EA411E6DB30D00FF7F7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 22F0EA431E6DB30D00FF7F7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 35F3C0C41E6FDC960018D3C0 /* PPCounterConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCounterConst.h; sourceTree = ""; }; 34 | 35F3C0C51E6FDC960018D3C0 /* PPCounterConst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PPCounterConst.m; sourceTree = ""; }; 35 | 35F3C0C61E6FDC960018D3C0 /* PPCounterEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCounterEngine.h; sourceTree = ""; }; 36 | 35F3C0C71E6FDC960018D3C0 /* PPCounterEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PPCounterEngine.m; sourceTree = ""; }; 37 | 35F3C0C81E6FDC960018D3C0 /* PPCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCounter.h; sourceTree = ""; }; 38 | 35F3C0CA1E6FDC960018D3C0 /* UIButton+PPCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+PPCounter.h"; sourceTree = ""; }; 39 | 35F3C0CB1E6FDC960018D3C0 /* UIButton+PPCounter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+PPCounter.m"; sourceTree = ""; }; 40 | 35F3C0CC1E6FDC960018D3C0 /* UILabel+PPCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UILabel+PPCounter.h"; sourceTree = ""; }; 41 | 35F3C0CD1E6FDC960018D3C0 /* UILabel+PPCounter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UILabel+PPCounter.m"; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 22F0EA2C1E6DB30D00FF7F7D /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 22F0EA261E6DB30D00FF7F7D = { 56 | isa = PBXGroup; 57 | children = ( 58 | 22F0EA311E6DB30D00FF7F7D /* PPCounter IOSDemo */, 59 | 22F0EA301E6DB30D00FF7F7D /* Products */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | 22F0EA301E6DB30D00FF7F7D /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 22F0EA2F1E6DB30D00FF7F7D /* PPCounter IOSDemo.app */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 22F0EA311E6DB30D00FF7F7D /* PPCounter IOSDemo */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 35F3C0C21E6FDC960018D3C0 /* PPCounter */, 75 | 22F0EA351E6DB30D00FF7F7D /* AppDelegate.h */, 76 | 22F0EA361E6DB30D00FF7F7D /* AppDelegate.m */, 77 | 22F0EA381E6DB30D00FF7F7D /* ViewController.h */, 78 | 22F0EA391E6DB30D00FF7F7D /* ViewController.m */, 79 | 22F0EA3B1E6DB30D00FF7F7D /* Main.storyboard */, 80 | 22F0EA3E1E6DB30D00FF7F7D /* Assets.xcassets */, 81 | 22F0EA401E6DB30D00FF7F7D /* LaunchScreen.storyboard */, 82 | 22F0EA431E6DB30D00FF7F7D /* Info.plist */, 83 | 22F0EA321E6DB30D00FF7F7D /* Supporting Files */, 84 | ); 85 | path = "PPCounter IOSDemo"; 86 | sourceTree = ""; 87 | }; 88 | 22F0EA321E6DB30D00FF7F7D /* Supporting Files */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 22F0EA331E6DB30D00FF7F7D /* main.m */, 92 | ); 93 | name = "Supporting Files"; 94 | sourceTree = ""; 95 | }; 96 | 35F3C0C21E6FDC960018D3C0 /* PPCounter */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 35F3C0C81E6FDC960018D3C0 /* PPCounter.h */, 100 | 35F3C0C31E6FDC960018D3C0 /* Core */, 101 | 35F3C0C91E6FDC960018D3C0 /* UIKit */, 102 | ); 103 | name = PPCounter; 104 | path = ../../PPCounter; 105 | sourceTree = ""; 106 | }; 107 | 35F3C0C31E6FDC960018D3C0 /* Core */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 35F3C0C41E6FDC960018D3C0 /* PPCounterConst.h */, 111 | 35F3C0C51E6FDC960018D3C0 /* PPCounterConst.m */, 112 | 35F3C0C61E6FDC960018D3C0 /* PPCounterEngine.h */, 113 | 35F3C0C71E6FDC960018D3C0 /* PPCounterEngine.m */, 114 | ); 115 | path = Core; 116 | sourceTree = ""; 117 | }; 118 | 35F3C0C91E6FDC960018D3C0 /* UIKit */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 35F3C0CA1E6FDC960018D3C0 /* UIButton+PPCounter.h */, 122 | 35F3C0CB1E6FDC960018D3C0 /* UIButton+PPCounter.m */, 123 | 35F3C0CC1E6FDC960018D3C0 /* UILabel+PPCounter.h */, 124 | 35F3C0CD1E6FDC960018D3C0 /* UILabel+PPCounter.m */, 125 | ); 126 | path = UIKit; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | 22F0EA2E1E6DB30D00FF7F7D /* PPCounter IOSDemo */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 22F0EA461E6DB30D00FF7F7D /* Build configuration list for PBXNativeTarget "PPCounter IOSDemo" */; 135 | buildPhases = ( 136 | 22F0EA2B1E6DB30D00FF7F7D /* Sources */, 137 | 22F0EA2C1E6DB30D00FF7F7D /* Frameworks */, 138 | 22F0EA2D1E6DB30D00FF7F7D /* Resources */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | ); 144 | name = "PPCounter IOSDemo"; 145 | productName = "PPCounter IOSDemo"; 146 | productReference = 22F0EA2F1E6DB30D00FF7F7D /* PPCounter IOSDemo.app */; 147 | productType = "com.apple.product-type.application"; 148 | }; 149 | /* End PBXNativeTarget section */ 150 | 151 | /* Begin PBXProject section */ 152 | 22F0EA271E6DB30D00FF7F7D /* Project object */ = { 153 | isa = PBXProject; 154 | attributes = { 155 | LastUpgradeCheck = 0820; 156 | ORGANIZATIONNAME = AndyPang; 157 | TargetAttributes = { 158 | 22F0EA2E1E6DB30D00FF7F7D = { 159 | CreatedOnToolsVersion = 8.2.1; 160 | DevelopmentTeam = YY4NTQ7LN8; 161 | ProvisioningStyle = Automatic; 162 | }; 163 | }; 164 | }; 165 | buildConfigurationList = 22F0EA2A1E6DB30D00FF7F7D /* Build configuration list for PBXProject "PPCounter IOSDemo" */; 166 | compatibilityVersion = "Xcode 3.2"; 167 | developmentRegion = English; 168 | hasScannedForEncodings = 0; 169 | knownRegions = ( 170 | en, 171 | Base, 172 | ); 173 | mainGroup = 22F0EA261E6DB30D00FF7F7D; 174 | productRefGroup = 22F0EA301E6DB30D00FF7F7D /* Products */; 175 | projectDirPath = ""; 176 | projectRoot = ""; 177 | targets = ( 178 | 22F0EA2E1E6DB30D00FF7F7D /* PPCounter IOSDemo */, 179 | ); 180 | }; 181 | /* End PBXProject section */ 182 | 183 | /* Begin PBXResourcesBuildPhase section */ 184 | 22F0EA2D1E6DB30D00FF7F7D /* Resources */ = { 185 | isa = PBXResourcesBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | 22F0EA421E6DB30D00FF7F7D /* LaunchScreen.storyboard in Resources */, 189 | 22F0EA3F1E6DB30D00FF7F7D /* Assets.xcassets in Resources */, 190 | 22F0EA3D1E6DB30D00FF7F7D /* Main.storyboard in Resources */, 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | }; 194 | /* End PBXResourcesBuildPhase section */ 195 | 196 | /* Begin PBXSourcesBuildPhase section */ 197 | 22F0EA2B1E6DB30D00FF7F7D /* Sources */ = { 198 | isa = PBXSourcesBuildPhase; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | 35F3C0D11E6FDC960018D3C0 /* UILabel+PPCounter.m in Sources */, 202 | 35F3C0D01E6FDC960018D3C0 /* UIButton+PPCounter.m in Sources */, 203 | 22F0EA3A1E6DB30D00FF7F7D /* ViewController.m in Sources */, 204 | 22F0EA371E6DB30D00FF7F7D /* AppDelegate.m in Sources */, 205 | 35F3C0CE1E6FDC960018D3C0 /* PPCounterConst.m in Sources */, 206 | 35F3C0CF1E6FDC960018D3C0 /* PPCounterEngine.m in Sources */, 207 | 22F0EA341E6DB30D00FF7F7D /* main.m in Sources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXSourcesBuildPhase section */ 212 | 213 | /* Begin PBXVariantGroup section */ 214 | 22F0EA3B1E6DB30D00FF7F7D /* Main.storyboard */ = { 215 | isa = PBXVariantGroup; 216 | children = ( 217 | 22F0EA3C1E6DB30D00FF7F7D /* Base */, 218 | ); 219 | name = Main.storyboard; 220 | sourceTree = ""; 221 | }; 222 | 22F0EA401E6DB30D00FF7F7D /* LaunchScreen.storyboard */ = { 223 | isa = PBXVariantGroup; 224 | children = ( 225 | 22F0EA411E6DB30D00FF7F7D /* Base */, 226 | ); 227 | name = LaunchScreen.storyboard; 228 | sourceTree = ""; 229 | }; 230 | /* End PBXVariantGroup section */ 231 | 232 | /* Begin XCBuildConfiguration section */ 233 | 22F0EA441E6DB30D00FF7F7D /* Debug */ = { 234 | isa = XCBuildConfiguration; 235 | buildSettings = { 236 | ALWAYS_SEARCH_USER_PATHS = NO; 237 | CLANG_ANALYZER_NONNULL = YES; 238 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 239 | CLANG_CXX_LIBRARY = "libc++"; 240 | CLANG_ENABLE_MODULES = YES; 241 | CLANG_ENABLE_OBJC_ARC = YES; 242 | CLANG_WARN_BOOL_CONVERSION = YES; 243 | CLANG_WARN_CONSTANT_CONVERSION = YES; 244 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 245 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 246 | CLANG_WARN_EMPTY_BODY = YES; 247 | CLANG_WARN_ENUM_CONVERSION = YES; 248 | CLANG_WARN_INFINITE_RECURSION = YES; 249 | CLANG_WARN_INT_CONVERSION = YES; 250 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 251 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 252 | CLANG_WARN_UNREACHABLE_CODE = YES; 253 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 254 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 255 | COPY_PHASE_STRIP = NO; 256 | DEBUG_INFORMATION_FORMAT = dwarf; 257 | ENABLE_STRICT_OBJC_MSGSEND = YES; 258 | ENABLE_TESTABILITY = YES; 259 | GCC_C_LANGUAGE_STANDARD = gnu99; 260 | GCC_DYNAMIC_NO_PIC = NO; 261 | GCC_NO_COMMON_BLOCKS = YES; 262 | GCC_OPTIMIZATION_LEVEL = 0; 263 | GCC_PREPROCESSOR_DEFINITIONS = ( 264 | "DEBUG=1", 265 | "$(inherited)", 266 | ); 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 274 | MTL_ENABLE_DEBUG_INFO = YES; 275 | ONLY_ACTIVE_ARCH = YES; 276 | SDKROOT = iphoneos; 277 | TARGETED_DEVICE_FAMILY = "1,2"; 278 | }; 279 | name = Debug; 280 | }; 281 | 22F0EA451E6DB30D00FF7F7D /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ALWAYS_SEARCH_USER_PATHS = NO; 285 | CLANG_ANALYZER_NONNULL = YES; 286 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 287 | CLANG_CXX_LIBRARY = "libc++"; 288 | CLANG_ENABLE_MODULES = YES; 289 | CLANG_ENABLE_OBJC_ARC = YES; 290 | CLANG_WARN_BOOL_CONVERSION = YES; 291 | CLANG_WARN_CONSTANT_CONVERSION = YES; 292 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 293 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 294 | CLANG_WARN_EMPTY_BODY = YES; 295 | CLANG_WARN_ENUM_CONVERSION = YES; 296 | CLANG_WARN_INFINITE_RECURSION = YES; 297 | CLANG_WARN_INT_CONVERSION = YES; 298 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 299 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 300 | CLANG_WARN_UNREACHABLE_CODE = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 303 | COPY_PHASE_STRIP = NO; 304 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 305 | ENABLE_NS_ASSERTIONS = NO; 306 | ENABLE_STRICT_OBJC_MSGSEND = YES; 307 | GCC_C_LANGUAGE_STANDARD = gnu99; 308 | GCC_NO_COMMON_BLOCKS = YES; 309 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 310 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 311 | GCC_WARN_UNDECLARED_SELECTOR = YES; 312 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 313 | GCC_WARN_UNUSED_FUNCTION = YES; 314 | GCC_WARN_UNUSED_VARIABLE = YES; 315 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 316 | MTL_ENABLE_DEBUG_INFO = NO; 317 | SDKROOT = iphoneos; 318 | TARGETED_DEVICE_FAMILY = "1,2"; 319 | VALIDATE_PRODUCT = YES; 320 | }; 321 | name = Release; 322 | }; 323 | 22F0EA471E6DB30D00FF7F7D /* Debug */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 327 | DEVELOPMENT_TEAM = YY4NTQ7LN8; 328 | INFOPLIST_FILE = "PPCounter IOSDemo/Info.plist"; 329 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 330 | PRODUCT_BUNDLE_IDENTIFIER = "com.jkpang.PPCounter-IOSDemo"; 331 | PRODUCT_NAME = "$(TARGET_NAME)"; 332 | }; 333 | name = Debug; 334 | }; 335 | 22F0EA481E6DB30D00FF7F7D /* Release */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 339 | DEVELOPMENT_TEAM = YY4NTQ7LN8; 340 | INFOPLIST_FILE = "PPCounter IOSDemo/Info.plist"; 341 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 342 | PRODUCT_BUNDLE_IDENTIFIER = "com.jkpang.PPCounter-IOSDemo"; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | }; 345 | name = Release; 346 | }; 347 | /* End XCBuildConfiguration section */ 348 | 349 | /* Begin XCConfigurationList section */ 350 | 22F0EA2A1E6DB30D00FF7F7D /* Build configuration list for PBXProject "PPCounter IOSDemo" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 22F0EA441E6DB30D00FF7F7D /* Debug */, 354 | 22F0EA451E6DB30D00FF7F7D /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | 22F0EA461E6DB30D00FF7F7D /* Build configuration list for PBXNativeTarget "PPCounter IOSDemo" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 22F0EA471E6DB30D00FF7F7D /* Debug */, 363 | 22F0EA481E6DB30D00FF7F7D /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | /* End XCConfigurationList section */ 369 | }; 370 | rootObject = 22F0EA271E6DB30D00FF7F7D /* Project object */; 371 | } 372 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/project.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/project.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/project.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/project.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/xcuserdata/AndyPang.xcuserdatad/xcschemes/PPCounter IOSDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/xcuserdata/AndyPang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPCounter IOSDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 22F0EA2E1E6DB30D00FF7F7D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/xcuserdata/YiAi.xcuserdatad/xcschemes/PPCounter IOSDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/xcuserdata/YiAi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPCounter IOSDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 22F0EA2E1E6DB30D00FF7F7D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/xcuserdata/duoyi.xcuserdatad/xcschemes/PPCounter IOSDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo.xcodeproj/xcuserdata/duoyi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPCounter IOSDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 22F0EA2E1E6DB30D00FF7F7D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PPCounter IOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PPCounter IOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // 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. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 56 | 62 | 68 | 78 | 84 | 90 | 96 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/15. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/15. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import "ViewController.h" 28 | #import "PPCounter.h" 29 | 30 | @interface ViewController () 31 | 32 | @property (weak, nonatomic) IBOutlet UILabel *label1; 33 | @property (weak, nonatomic) IBOutlet UILabel *label2; 34 | @property (weak, nonatomic) IBOutlet UILabel *label3; 35 | 36 | @property (weak, nonatomic) IBOutlet UIButton *button1; 37 | @property (weak, nonatomic) IBOutlet UIButton *button2; 38 | @property (weak, nonatomic) IBOutlet UIButton *button3; 39 | 40 | @end 41 | 42 | @implementation ViewController 43 | 44 | - (void)viewDidLoad { 45 | [super viewDidLoad]; 46 | 47 | [self change:PPCounterAnimationOptionCurveEaseInOut]; 48 | } 49 | 50 | 51 | - (IBAction)select:(UISegmentedControl *)sender 52 | { 53 | [self change:sender.selectedSegmentIndex+1]; 54 | } 55 | 56 | - (void)change:(PPCounterAnimationOptions)animationOptions 57 | { 58 | [self exampleLabel1:animationOptions]; 59 | [self exampleLabel2:animationOptions]; 60 | [self exampleLabel3:animationOptions]; 61 | 62 | [self exampleButton1:animationOptions]; 63 | [self exampleButton2:animationOptions]; 64 | [self exampleButton3:animationOptions]; 65 | } 66 | 67 | #pragma mark - UIlabel 68 | 69 | - (void)exampleLabel1:(PPCounterAnimationOptions)animationOptions 70 | { 71 | // 设置动画类型 72 | self.label1.animationOptions = animationOptions; 73 | 74 | // 开始计数 75 | [self.label1 pp_fromNumber:0 toNumber:50 duration:1.5f format:^NSString *(CGFloat number) { 76 | return [NSString stringWithFormat:@"%.0f",number]; 77 | }]; 78 | 79 | } 80 | 81 | - (void)exampleLabel2:(PPCounterAnimationOptions)animationOptions 82 | { 83 | 84 | self.label2.animationOptions = animationOptions; 85 | 86 | [self.label2 pp_fromNumber:0 toNumber:100 duration:1.5 animationOptions:animationOptions attributedFormat:^NSAttributedString *(CGFloat number) { 87 | 88 | NSString *string = [NSString stringWithFormat:@"%ld%%",(NSInteger)number]; 89 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string]; 90 | // 设置字体属性 91 | NSRange range = [string rangeOfString:[NSString stringWithFormat:@"%ld",(NSInteger)number]]; 92 | [attributedString addAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:22],NSForegroundColorAttributeName:[UIColor brownColor]} range:range]; 93 | return attributedString; 94 | 95 | } completion:^(CGFloat endNumber) { 96 | self.label2.textColor = [UIColor redColor]; 97 | }]; 98 | 99 | } 100 | 101 | - (void)exampleLabel3:(PPCounterAnimationOptions)animationOptions 102 | { 103 | 104 | self.label3.animationOptions = animationOptions; 105 | 106 | [self.label3 pp_fromNumber:0 toNumber:2016101 duration:1.5f format:^NSString *(CGFloat number) { 107 | NSNumberFormatter *formatter = [NSNumberFormatter new]; 108 | formatter.numberStyle = NSNumberFormatterDecimalStyle; 109 | formatter.positiveFormat = @"###,##0.00"; 110 | NSNumber *amountNumber = [NSNumber numberWithFloat:number]; 111 | return [NSString stringWithFormat:@"¥%@",[formatter stringFromNumber:amountNumber]]; 112 | }]; 113 | 114 | } 115 | 116 | #pragma mark - UIButton 117 | - (void)exampleButton1:(PPCounterAnimationOptions)animationOptions 118 | { 119 | // 设置动画类型 120 | self.button1.animationOptions = animationOptions; 121 | 122 | // 开始计数 123 | [self.button1 pp_fromNumber:0 toNumber:50 duration:1.5f format:^NSString *(CGFloat number) { 124 | 125 | return [NSString stringWithFormat:@"%.0f",number]; 126 | }]; 127 | 128 | } 129 | 130 | - (void)exampleButton2:(PPCounterAnimationOptions)animationOptions 131 | { 132 | self.button2.animationOptions = animationOptions; 133 | 134 | [self.button2 pp_fromNumber:0 toNumber:100 duration:1.5 animationOptions:animationOptions attributedFormat:^NSAttributedString *(CGFloat number) { 135 | 136 | NSString *string = [NSString stringWithFormat:@"%ld%%",(NSInteger)number]; 137 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string]; 138 | // 设置字体属性 139 | NSRange range = [string rangeOfString:[NSString stringWithFormat:@"%ld",(NSInteger)number]]; 140 | [attributedString addAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:22],NSForegroundColorAttributeName:[UIColor orangeColor]} range:range]; 141 | return attributedString; 142 | 143 | } completion:^(CGFloat endNumber) { 144 | [self.button2 setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal]; 145 | }]; 146 | } 147 | 148 | - (void)exampleButton3:(PPCounterAnimationOptions)animationOptions 149 | { 150 | self.button3.animationOptions = animationOptions; 151 | 152 | [self.button3 pp_fromNumber:0 toNumber:50 duration:1.5f format:^NSString *(CGFloat number) { 153 | 154 | NSNumberFormatter *formatter = [NSNumberFormatter new]; 155 | formatter.numberStyle = NSNumberFormatterDecimalStyle; 156 | formatter.positiveFormat = @"###,##0.00"; 157 | NSNumber *amountNumber = [NSNumber numberWithFloat:number]; 158 | return [NSString stringWithFormat:@"¥%@",[formatter stringFromNumber:amountNumber]]; 159 | }]; 160 | 161 | } 162 | 163 | 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /PPCounter IOSDemo/PPCounter IOSDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PPCounter IOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 22F0EA571E6DB33500FF7F7D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F0EA561E6DB33500FF7F7D /* AppDelegate.m */; }; 11 | 22F0EA5A1E6DB33500FF7F7D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F0EA591E6DB33500FF7F7D /* main.m */; }; 12 | 22F0EA5D1E6DB33500FF7F7D /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F0EA5C1E6DB33500FF7F7D /* ViewController.m */; }; 13 | 22F0EA5F1E6DB33500FF7F7D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 22F0EA5E1E6DB33500FF7F7D /* Assets.xcassets */; }; 14 | 22F0EA621E6DB33500FF7F7D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 22F0EA601E6DB33500FF7F7D /* Main.storyboard */; }; 15 | 35F3C0DE1E6FDCBC0018D3C0 /* PPCounterConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F3C0D51E6FDCBC0018D3C0 /* PPCounterConst.m */; }; 16 | 35F3C0DF1E6FDCBC0018D3C0 /* PPCounterEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F3C0D71E6FDCBC0018D3C0 /* PPCounterEngine.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 22F0EA521E6DB33500FF7F7D /* PPCounter MacOSDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PPCounter MacOSDemo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 22F0EA551E6DB33500FF7F7D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 22 | 22F0EA561E6DB33500FF7F7D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 23 | 22F0EA591E6DB33500FF7F7D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 24 | 22F0EA5B1E6DB33500FF7F7D /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 25 | 22F0EA5C1E6DB33500FF7F7D /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 26 | 22F0EA5E1E6DB33500FF7F7D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | 22F0EA611E6DB33500FF7F7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 28 | 22F0EA631E6DB33500FF7F7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | 35F3C0D41E6FDCBC0018D3C0 /* PPCounterConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCounterConst.h; sourceTree = ""; }; 30 | 35F3C0D51E6FDCBC0018D3C0 /* PPCounterConst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PPCounterConst.m; sourceTree = ""; }; 31 | 35F3C0D61E6FDCBC0018D3C0 /* PPCounterEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCounterEngine.h; sourceTree = ""; }; 32 | 35F3C0D71E6FDCBC0018D3C0 /* PPCounterEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PPCounterEngine.m; sourceTree = ""; }; 33 | 35F3C0D81E6FDCBC0018D3C0 /* PPCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCounter.h; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 22F0EA4F1E6DB33500FF7F7D /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 22F0EA491E6DB33500FF7F7D = { 48 | isa = PBXGroup; 49 | children = ( 50 | 22F0EA541E6DB33500FF7F7D /* PPCounter MacOSDemo */, 51 | 22F0EA531E6DB33500FF7F7D /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | 22F0EA531E6DB33500FF7F7D /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 22F0EA521E6DB33500FF7F7D /* PPCounter MacOSDemo.app */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | 22F0EA541E6DB33500FF7F7D /* PPCounter MacOSDemo */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 35F3C0D21E6FDCBC0018D3C0 /* PPCounter */, 67 | 22F0EA551E6DB33500FF7F7D /* AppDelegate.h */, 68 | 22F0EA561E6DB33500FF7F7D /* AppDelegate.m */, 69 | 22F0EA5B1E6DB33500FF7F7D /* ViewController.h */, 70 | 22F0EA5C1E6DB33500FF7F7D /* ViewController.m */, 71 | 22F0EA5E1E6DB33500FF7F7D /* Assets.xcassets */, 72 | 22F0EA601E6DB33500FF7F7D /* Main.storyboard */, 73 | 22F0EA631E6DB33500FF7F7D /* Info.plist */, 74 | 22F0EA581E6DB33500FF7F7D /* Supporting Files */, 75 | ); 76 | path = "PPCounter MacOSDemo"; 77 | sourceTree = ""; 78 | }; 79 | 22F0EA581E6DB33500FF7F7D /* Supporting Files */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 22F0EA591E6DB33500FF7F7D /* main.m */, 83 | ); 84 | name = "Supporting Files"; 85 | sourceTree = ""; 86 | }; 87 | 35F3C0D21E6FDCBC0018D3C0 /* PPCounter */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 35F3C0D81E6FDCBC0018D3C0 /* PPCounter.h */, 91 | 35F3C0D31E6FDCBC0018D3C0 /* Core */, 92 | ); 93 | name = PPCounter; 94 | path = ../../PPCounter; 95 | sourceTree = ""; 96 | }; 97 | 35F3C0D31E6FDCBC0018D3C0 /* Core */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 35F3C0D41E6FDCBC0018D3C0 /* PPCounterConst.h */, 101 | 35F3C0D51E6FDCBC0018D3C0 /* PPCounterConst.m */, 102 | 35F3C0D61E6FDCBC0018D3C0 /* PPCounterEngine.h */, 103 | 35F3C0D71E6FDCBC0018D3C0 /* PPCounterEngine.m */, 104 | ); 105 | path = Core; 106 | sourceTree = ""; 107 | }; 108 | /* End PBXGroup section */ 109 | 110 | /* Begin PBXNativeTarget section */ 111 | 22F0EA511E6DB33500FF7F7D /* PPCounter MacOSDemo */ = { 112 | isa = PBXNativeTarget; 113 | buildConfigurationList = 22F0EA661E6DB33500FF7F7D /* Build configuration list for PBXNativeTarget "PPCounter MacOSDemo" */; 114 | buildPhases = ( 115 | 22F0EA4E1E6DB33500FF7F7D /* Sources */, 116 | 22F0EA4F1E6DB33500FF7F7D /* Frameworks */, 117 | 22F0EA501E6DB33500FF7F7D /* Resources */, 118 | ); 119 | buildRules = ( 120 | ); 121 | dependencies = ( 122 | ); 123 | name = "PPCounter MacOSDemo"; 124 | productName = "PPCounter MacOSDemo"; 125 | productReference = 22F0EA521E6DB33500FF7F7D /* PPCounter MacOSDemo.app */; 126 | productType = "com.apple.product-type.application"; 127 | }; 128 | /* End PBXNativeTarget section */ 129 | 130 | /* Begin PBXProject section */ 131 | 22F0EA4A1E6DB33500FF7F7D /* Project object */ = { 132 | isa = PBXProject; 133 | attributes = { 134 | LastUpgradeCheck = 0820; 135 | ORGANIZATIONNAME = AndyPang; 136 | TargetAttributes = { 137 | 22F0EA511E6DB33500FF7F7D = { 138 | CreatedOnToolsVersion = 8.2.1; 139 | DevelopmentTeam = YY4NTQ7LN8; 140 | ProvisioningStyle = Automatic; 141 | }; 142 | }; 143 | }; 144 | buildConfigurationList = 22F0EA4D1E6DB33500FF7F7D /* Build configuration list for PBXProject "PPCounter MacOSDemo" */; 145 | compatibilityVersion = "Xcode 3.2"; 146 | developmentRegion = English; 147 | hasScannedForEncodings = 0; 148 | knownRegions = ( 149 | en, 150 | Base, 151 | ); 152 | mainGroup = 22F0EA491E6DB33500FF7F7D; 153 | productRefGroup = 22F0EA531E6DB33500FF7F7D /* Products */; 154 | projectDirPath = ""; 155 | projectRoot = ""; 156 | targets = ( 157 | 22F0EA511E6DB33500FF7F7D /* PPCounter MacOSDemo */, 158 | ); 159 | }; 160 | /* End PBXProject section */ 161 | 162 | /* Begin PBXResourcesBuildPhase section */ 163 | 22F0EA501E6DB33500FF7F7D /* Resources */ = { 164 | isa = PBXResourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | 22F0EA5F1E6DB33500FF7F7D /* Assets.xcassets in Resources */, 168 | 22F0EA621E6DB33500FF7F7D /* Main.storyboard in Resources */, 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | }; 172 | /* End PBXResourcesBuildPhase section */ 173 | 174 | /* Begin PBXSourcesBuildPhase section */ 175 | 22F0EA4E1E6DB33500FF7F7D /* Sources */ = { 176 | isa = PBXSourcesBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | 22F0EA5D1E6DB33500FF7F7D /* ViewController.m in Sources */, 180 | 22F0EA5A1E6DB33500FF7F7D /* main.m in Sources */, 181 | 35F3C0DE1E6FDCBC0018D3C0 /* PPCounterConst.m in Sources */, 182 | 35F3C0DF1E6FDCBC0018D3C0 /* PPCounterEngine.m in Sources */, 183 | 22F0EA571E6DB33500FF7F7D /* AppDelegate.m in Sources */, 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXSourcesBuildPhase section */ 188 | 189 | /* Begin PBXVariantGroup section */ 190 | 22F0EA601E6DB33500FF7F7D /* Main.storyboard */ = { 191 | isa = PBXVariantGroup; 192 | children = ( 193 | 22F0EA611E6DB33500FF7F7D /* Base */, 194 | ); 195 | name = Main.storyboard; 196 | sourceTree = ""; 197 | }; 198 | /* End PBXVariantGroup section */ 199 | 200 | /* Begin XCBuildConfiguration section */ 201 | 22F0EA641E6DB33500FF7F7D /* Debug */ = { 202 | isa = XCBuildConfiguration; 203 | buildSettings = { 204 | ALWAYS_SEARCH_USER_PATHS = NO; 205 | CLANG_ANALYZER_NONNULL = YES; 206 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 207 | CLANG_CXX_LIBRARY = "libc++"; 208 | CLANG_ENABLE_MODULES = YES; 209 | CLANG_ENABLE_OBJC_ARC = YES; 210 | CLANG_WARN_BOOL_CONVERSION = YES; 211 | CLANG_WARN_CONSTANT_CONVERSION = YES; 212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 213 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INFINITE_RECURSION = YES; 217 | CLANG_WARN_INT_CONVERSION = YES; 218 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 219 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 220 | CLANG_WARN_UNREACHABLE_CODE = YES; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | CODE_SIGN_IDENTITY = "-"; 223 | COPY_PHASE_STRIP = NO; 224 | DEBUG_INFORMATION_FORMAT = dwarf; 225 | ENABLE_STRICT_OBJC_MSGSEND = YES; 226 | ENABLE_TESTABILITY = YES; 227 | GCC_C_LANGUAGE_STANDARD = gnu99; 228 | GCC_DYNAMIC_NO_PIC = NO; 229 | GCC_NO_COMMON_BLOCKS = YES; 230 | GCC_OPTIMIZATION_LEVEL = 0; 231 | GCC_PREPROCESSOR_DEFINITIONS = ( 232 | "DEBUG=1", 233 | "$(inherited)", 234 | ); 235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 236 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 237 | GCC_WARN_UNDECLARED_SELECTOR = YES; 238 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 239 | GCC_WARN_UNUSED_FUNCTION = YES; 240 | GCC_WARN_UNUSED_VARIABLE = YES; 241 | MACOSX_DEPLOYMENT_TARGET = 10.12; 242 | MTL_ENABLE_DEBUG_INFO = YES; 243 | ONLY_ACTIVE_ARCH = YES; 244 | SDKROOT = macosx; 245 | }; 246 | name = Debug; 247 | }; 248 | 22F0EA651E6DB33500FF7F7D /* Release */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ALWAYS_SEARCH_USER_PATHS = NO; 252 | CLANG_ANALYZER_NONNULL = YES; 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 254 | CLANG_CXX_LIBRARY = "libc++"; 255 | CLANG_ENABLE_MODULES = YES; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_BOOL_CONVERSION = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 260 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 261 | CLANG_WARN_EMPTY_BODY = YES; 262 | CLANG_WARN_ENUM_CONVERSION = YES; 263 | CLANG_WARN_INFINITE_RECURSION = YES; 264 | CLANG_WARN_INT_CONVERSION = YES; 265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 266 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 267 | CLANG_WARN_UNREACHABLE_CODE = YES; 268 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 269 | CODE_SIGN_IDENTITY = "-"; 270 | COPY_PHASE_STRIP = NO; 271 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 272 | ENABLE_NS_ASSERTIONS = NO; 273 | ENABLE_STRICT_OBJC_MSGSEND = YES; 274 | GCC_C_LANGUAGE_STANDARD = gnu99; 275 | GCC_NO_COMMON_BLOCKS = YES; 276 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 277 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 278 | GCC_WARN_UNDECLARED_SELECTOR = YES; 279 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 280 | GCC_WARN_UNUSED_FUNCTION = YES; 281 | GCC_WARN_UNUSED_VARIABLE = YES; 282 | MACOSX_DEPLOYMENT_TARGET = 10.12; 283 | MTL_ENABLE_DEBUG_INFO = NO; 284 | SDKROOT = macosx; 285 | }; 286 | name = Release; 287 | }; 288 | 22F0EA671E6DB33500FF7F7D /* Debug */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 292 | COMBINE_HIDPI_IMAGES = YES; 293 | DEVELOPMENT_TEAM = YY4NTQ7LN8; 294 | INFOPLIST_FILE = "PPCounter MacOSDemo/Info.plist"; 295 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 296 | MACOSX_DEPLOYMENT_TARGET = 10.10; 297 | PRODUCT_BUNDLE_IDENTIFIER = "com.jkpang.PPCounter-MacOSDemo"; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | }; 300 | name = Debug; 301 | }; 302 | 22F0EA681E6DB33500FF7F7D /* Release */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 306 | COMBINE_HIDPI_IMAGES = YES; 307 | DEVELOPMENT_TEAM = YY4NTQ7LN8; 308 | INFOPLIST_FILE = "PPCounter MacOSDemo/Info.plist"; 309 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 310 | MACOSX_DEPLOYMENT_TARGET = 10.10; 311 | PRODUCT_BUNDLE_IDENTIFIER = "com.jkpang.PPCounter-MacOSDemo"; 312 | PRODUCT_NAME = "$(TARGET_NAME)"; 313 | }; 314 | name = Release; 315 | }; 316 | /* End XCBuildConfiguration section */ 317 | 318 | /* Begin XCConfigurationList section */ 319 | 22F0EA4D1E6DB33500FF7F7D /* Build configuration list for PBXProject "PPCounter MacOSDemo" */ = { 320 | isa = XCConfigurationList; 321 | buildConfigurations = ( 322 | 22F0EA641E6DB33500FF7F7D /* Debug */, 323 | 22F0EA651E6DB33500FF7F7D /* Release */, 324 | ); 325 | defaultConfigurationIsVisible = 0; 326 | defaultConfigurationName = Release; 327 | }; 328 | 22F0EA661E6DB33500FF7F7D /* Build configuration list for PBXNativeTarget "PPCounter MacOSDemo" */ = { 329 | isa = XCConfigurationList; 330 | buildConfigurations = ( 331 | 22F0EA671E6DB33500FF7F7D /* Debug */, 332 | 22F0EA681E6DB33500FF7F7D /* Release */, 333 | ); 334 | defaultConfigurationIsVisible = 0; 335 | defaultConfigurationName = Release; 336 | }; 337 | /* End XCConfigurationList section */ 338 | }; 339 | rootObject = 22F0EA4A1E6DB33500FF7F7D /* Project object */; 340 | } 341 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/project.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/project.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/project.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/project.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/xcuserdata/AndyPang.xcuserdatad/xcschemes/PPCounter MacOSDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/xcuserdata/AndyPang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPCounter MacOSDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 22F0EA511E6DB33500FF7F7D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/xcuserdata/YiAi.xcuserdatad/xcschemes/PPCounter MacOSDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/xcuserdata/YiAi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPCounter MacOSDemo.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 22F0EA511E6DB33500FF7F7D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/xcuserdata/duoyi.xcuserdatad/xcschemes/PPCounter MacOSDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo.xcodeproj/xcuserdata/duoyi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PPCounter MacOSDemo.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 22F0EA511E6DB33500FF7F7D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PPCounter MacOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PPCounter MacOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 18 | // Insert code here to initialize your application 19 | } 20 | 21 | 22 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 23 | // Insert code here to tear down your application 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | Default 510 | 511 | 512 | 513 | 514 | 515 | 516 | Left to Right 517 | 518 | 519 | 520 | 521 | 522 | 523 | Right to Left 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | Default 535 | 536 | 537 | 538 | 539 | 540 | 541 | Left to Right 542 | 543 | 544 | 545 | 546 | 547 | 548 | Right to Left 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2017年 AndyPang. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // PPCounter MacOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : NSViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // PPCounter MacOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "PPCounter.h" 11 | 12 | @interface ViewController () 13 | @property (weak) IBOutlet NSTextField *numberLabel; 14 | 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | // Do any additional setup after loading the view. 23 | } 24 | 25 | 26 | - (void)setRepresentedObject:(id)representedObject { 27 | [super setRepresentedObject:representedObject]; 28 | 29 | // Update the view, if already loaded. 30 | } 31 | 32 | - (IBAction)start:(NSButton *)sender 33 | { 34 | self.numberLabel.textColor = [NSColor blackColor]; 35 | [[PPCounterEngine counterEngine] fromNumber:0 36 | toNumber:999 37 | duration:2.f 38 | animationOptions:PPCounterAnimationOptionCurveEaseOut 39 | currentNumber:^(CGFloat number) { 40 | self.numberLabel.stringValue = [NSString stringWithFormat:@"%ld",(NSInteger)number]; 41 | } completion:^(CGFloat endNumber) { 42 | self.numberLabel.textColor = [NSColor redColor]; 43 | }]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /PPCounter MacOSDemo/PPCounter MacOSDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PPCounter MacOSDemo 4 | // 5 | // Created by AndyPang on 2017/3/6. 6 | // Copyright © 2017年 AndyPang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /PPCounter.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | s.name = "PPCounter" 5 | 6 | s.version = "0.6.0" 7 | 8 | s.osx.deployment_target = '10.10' 9 | 10 | s.ios.deployment_target = '7.0' 11 | 12 | s.summary = "iOS与macOS中一款优雅的数字/金额增减动效控件" 13 | 14 | s.homepage = "https://github.com/jkpang/PPCounter.git" 15 | 16 | s.license = { :type => "MIT", :file => "LICENSE" } 17 | 18 | s.author = { "jkpang" => "jkpang@outlook.com" } 19 | 20 | s.source = { :git => "https://github.com/jkpang/PPCounter.git", :tag => s.version.to_s } 21 | 22 | s.source_files = 'PPCounter/PPCounter.h' 23 | s.ios.source_files = 'PPCounter/Core/*.{h,m}', 'PPCounter/UIKit/*.{h,m}' 24 | s.osx.source_files = 'PPCounter/Core/*.{h,m}' 25 | 26 | s.requires_arc = true 27 | 28 | end 29 | -------------------------------------------------------------------------------- /PPCounter.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PPCounter.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PPCounter.xcworkspace/xcuserdata/AndyPang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPCounter.xcworkspace/xcuserdata/YiAi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PPCounter.xcworkspace/xcuserdata/YiAi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPCounter.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/PPCounter.xcworkspace/xcuserdata/duoyi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PPCounter/Core/PPCounterConst.h: -------------------------------------------------------------------------------- 1 | // 2 | // PPCounterConst.h 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/17. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import 28 | #import 29 | 30 | extern NSString *const kPPCounterAnimationOptions; 31 | 32 | typedef void(^PPCompletionBlock)(CGFloat endNumber); 33 | 34 | typedef void(^PPCurrentNumberBlock)(CGFloat currentNumber); 35 | 36 | typedef NSString *(^PPFormatBlock)(CGFloat currentNumber); 37 | 38 | typedef NSAttributedString *(^PPAttributedFormatBlock)(CGFloat currentNumber); 39 | 40 | typedef NS_ENUM(NSUInteger, PPCounterAnimationOptions) { 41 | /** 由慢到快,再由快到慢*/ 42 | PPCounterAnimationOptionCurveEaseInOut = 1, 43 | /** 由慢到快*/ 44 | PPCounterAnimationOptionCurveEaseIn, 45 | /** 由快到慢*/ 46 | PPCounterAnimationOptionCurveEaseOut, 47 | /** 匀速*/ 48 | PPCounterAnimationOptionCurveLinear 49 | }; 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /PPCounter/Core/PPCounterConst.m: -------------------------------------------------------------------------------- 1 | // 2 | // PPCounterConst.m 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/17. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import "PPCounterConst.h" 28 | 29 | NSString *const kPPCounterAnimationOptions = @"kPPCounterAnimationOptions"; 30 | -------------------------------------------------------------------------------- /PPCounter/Core/PPCounterEngine.h: -------------------------------------------------------------------------------- 1 | // 2 | // PPCounter.h 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/15. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import 28 | #import "PPCounterConst.h" 29 | 30 | @interface PPCounterEngine : NSObject 31 | 32 | /** 33 | 类方法创建一个计数器的实例 34 | */ 35 | + (instancetype)counterEngine; 36 | 37 | /** 38 | 在指定时间内数字从 numberA -> numberB 39 | 40 | @param starNumer 开始的数字 41 | @param endNumber 结束的数字 42 | @param duration 指定的时间 43 | @param animationOptions 动画类型 44 | @param currentNumber 当前数字的回调 45 | @param completion 已完成的回调 46 | */ 47 | - (void)fromNumber:(CGFloat)starNumer 48 | toNumber:(CGFloat)endNumber 49 | duration:(CFTimeInterval)duration 50 | animationOptions:(PPCounterAnimationOptions)animationOptions 51 | currentNumber:(PPCurrentNumberBlock)currentNumber 52 | completion:(PPCompletionBlock)completion; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /PPCounter/Core/PPCounterEngine.m: -------------------------------------------------------------------------------- 1 | // 2 | // PPCounter.m 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/15. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import "PPCounterEngine.h" 28 | #if TARGET_OS_IPHONE 29 | #import 30 | #elif TARGET_OS_MAC 31 | #import 32 | #endif 33 | 34 | /** 函数指针*/ 35 | typedef CGFloat (*PPCurrentBufferFunction)(CGFloat); 36 | 37 | 38 | @interface PPCounterEngine () 39 | 40 | /** 定时器*/ 41 | #if TARGET_OS_IPHONE 42 | @property (nonatomic, strong) CADisplayLink *timer; 43 | #elif TARGET_OS_MAC 44 | @property (nonatomic, strong) dispatch_source_t timer; 45 | #endif 46 | /** 开始的数字*/ 47 | @property (nonatomic, assign) CGFloat starNumber; 48 | /** 结束的数字*/ 49 | @property (nonatomic, assign) CGFloat endNumber; 50 | 51 | /** 动画的总持续时间*/ 52 | @property (nonatomic, assign) CFTimeInterval durationTime; 53 | /** 记录上一帧动画的时间*/ 54 | @property (nonatomic, assign) CFTimeInterval lastTime; 55 | /** 记录动画已持续的时间*/ 56 | @property (nonatomic, assign) CFTimeInterval progressTime; 57 | 58 | /** 获取当前数字的Block*/ 59 | @property (nonatomic, copy) PPCurrentNumberBlock currentNumber; 60 | /** 计数完成的Block*/ 61 | @property (nonatomic, copy) PPCompletionBlock completion; 62 | 63 | /** 动画函数*/ 64 | @property PPCurrentBufferFunction currentBufferFunction; 65 | 66 | @end 67 | 68 | @implementation PPCounterEngine 69 | 70 | - (instancetype)init 71 | { 72 | if (self = [super init]) { 73 | _currentBufferFunction = PPBufferFunctionEaseInOut; 74 | } 75 | return self; 76 | } 77 | 78 | + (instancetype)counterEngine 79 | { 80 | return [[self alloc] init]; 81 | } 82 | 83 | - (void)fromNumber:(CGFloat)starNumer 84 | toNumber:(CGFloat)endNumber 85 | duration:(CFTimeInterval)durationTime 86 | animationOptions:(PPCounterAnimationOptions)animationOptions 87 | currentNumber:(PPCurrentNumberBlock)currentNumber 88 | completion:(PPCompletionBlock)completion 89 | { 90 | // 开始前清空定时器 91 | [self cleanTimer]; 92 | 93 | // 如果开始数字与结束数字相等 94 | if (starNumer == endNumber) { 95 | currentNumber ? currentNumber(endNumber) : nil ; 96 | completion ? completion(endNumber) : nil; 97 | return; 98 | } 99 | 100 | // 初始化相关变量 101 | _starNumber = starNumer; 102 | _endNumber = endNumber; 103 | _durationTime = durationTime; 104 | 105 | // 设置缓冲动画类型 106 | [self setAnimationOptions:animationOptions]; 107 | 108 | // 设置block回调函数 109 | currentNumber ? _currentNumber = currentNumber : nil ; 110 | completion ? _completion = completion : nil ; 111 | 112 | // 记录定时器运行前的时间 113 | _lastTime = CACurrentMediaTime(); 114 | 115 | // 实例化定时器 116 | #if TARGET_OS_IPHONE 117 | _timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(changeNumber)]; 118 | _timer.frameInterval = 2; 119 | [_timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 120 | [_timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode]; 121 | #elif TARGET_OS_MAC 122 | _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); 123 | dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 1/30.f * NSEC_PER_SEC, 0 * NSEC_PER_SEC); 124 | dispatch_source_set_event_handler(_timer, ^{ 125 | [self changeNumber]; 126 | }); 127 | dispatch_resume(_timer); 128 | #endif 129 | 130 | 131 | } 132 | 133 | - (void)changeNumber 134 | { 135 | // 1.记录当前动画开始的时间 136 | CFTimeInterval thisTime = CACurrentMediaTime(); 137 | // 2.计算动画已持续的时间量 138 | _progressTime = _progressTime + (thisTime - _lastTime); 139 | // 3.准备下一次的计算 140 | _lastTime = thisTime; 141 | 142 | if (_progressTime >= _durationTime) { 143 | [self cleanTimer]; 144 | _currentNumber ? _currentNumber(_endNumber) : nil ; 145 | _completion ? _completion(_endNumber) : nil ; 146 | return; 147 | } 148 | _currentNumber ? _currentNumber([self computeNumber]) : nil ; 149 | } 150 | 151 | - (void)setAnimationOptions:(PPCounterAnimationOptions)animationOptions 152 | { 153 | switch (animationOptions) { 154 | case PPCounterAnimationOptionCurveEaseInOut: 155 | _currentBufferFunction = PPBufferFunctionEaseInOut; 156 | break; 157 | case PPCounterAnimationOptionCurveEaseIn: 158 | _currentBufferFunction = PPBufferFunctionEaseIn; 159 | break; 160 | case PPCounterAnimationOptionCurveEaseOut: 161 | _currentBufferFunction = PPBufferFunctionEaseOut; 162 | break; 163 | case PPCounterAnimationOptionCurveLinear: 164 | _currentBufferFunction = PPBufferFunctionLinear; 165 | break; 166 | default: 167 | break; 168 | } 169 | } 170 | 171 | /** 172 | 计算数字 173 | */ 174 | - (CGFloat)computeNumber 175 | { 176 | CGFloat percent = _progressTime / _durationTime; 177 | return _starNumber + (_currentBufferFunction(percent) * (_endNumber - _starNumber)); 178 | } 179 | 180 | /** 181 | 清除定时器 182 | */ 183 | - (void)cleanTimer 184 | { 185 | if (!_timer) {return;} 186 | #if TARGET_OS_IPHONE 187 | [_timer invalidate]; 188 | #elif TARGET_OS_MAC 189 | dispatch_source_cancel(_timer); 190 | #endif 191 | _timer = nil; 192 | _progressTime = 0; 193 | } 194 | 195 | #pragma mark - 缓冲动画函数 196 | 197 | CGFloat PPBufferFunctionEaseOut(CGFloat p) 198 | { 199 | return (p == 1.0) ? p : 1 - pow(2, -10 * p); 200 | } 201 | 202 | CGFloat PPBufferFunctionEaseIn(CGFloat p) 203 | { 204 | return (p == 0.0) ? p : pow(2, 10 * (p - 1)); 205 | } 206 | 207 | CGFloat PPBufferFunctionEaseInOut(CGFloat p) 208 | { 209 | if(p == 0.0 || p == 1.0) return p; 210 | 211 | if(p < 0.5) { 212 | return 0.5 * pow(2, (20 * p) - 10); 213 | } else { 214 | return -0.5 * pow(2, (-20 * p) + 10) + 1; 215 | } 216 | } 217 | 218 | CGFloat PPBufferFunctionLinear(CGFloat p) 219 | { 220 | return p; 221 | } 222 | 223 | @end 224 | -------------------------------------------------------------------------------- /PPCounter/PPCounter.h: -------------------------------------------------------------------------------- 1 | // 2 | // PPCounter.h 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/23. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #ifndef PPCounter_h 28 | #define PPCounter_h 29 | 30 | #import "PPCounterEngine.h" 31 | 32 | #if TARGET_OS_IPHONE 33 | #import "UILabel+PPCounter.h" 34 | #import "UIButton+PPCounter.h" 35 | #endif 36 | 37 | #endif /* PPCounter_h */ 38 | -------------------------------------------------------------------------------- /PPCounter/UIKit/UIButton+PPCounter.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+PPCounter.h 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/17. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import 28 | #import "PPCounterEngine.h" 29 | 30 | @interface UIButton (PPCounter) 31 | 32 | /** 动画类型*/ 33 | @property (nonatomic, assign) PPCounterAnimationOptions animationOptions; 34 | 35 | #pragma mark - normal 36 | 37 | /** 38 | 正常字体属性UIButton中的数字在指定时间从 numberA -> numberB, 39 | 40 | @param numberA 开始的数字 41 | @param numberB 结束的数字 42 | @param duration 持续时间 43 | @param format 设置字体一般属性的Block 44 | */ 45 | - (void)pp_fromNumber:(CGFloat)numberA 46 | toNumber:(CGFloat)numberB 47 | duration:(CFTimeInterval)duration 48 | format:(PPFormatBlock)format; 49 | 50 | /** 51 | 1.正常字体属性UIButton中的数字在指定时间从 numberA -> numberB, 52 | 2.有结束回调 53 | 54 | @param numberA 开始的数字 55 | @param numberB 结束的数字 56 | @param duration 持续时间 57 | @param format 设置一般字体的Block 58 | @param completion 完成的Block 59 | */ 60 | - (void)pp_fromNumber:(CGFloat)numberA 61 | toNumber:(CGFloat)numberB 62 | duration:(CFTimeInterval)duration 63 | format:(PPFormatBlock)format 64 | completion:(PPCompletionBlock)completion; 65 | 66 | /** 67 | 1.正常字体属性UIButton中的数字在指定时间从 numberA -> numberB, 68 | 2.可设置动画类型, 69 | 3.有结束回调 70 | 71 | @param numberA 开始的数字 72 | @param numberB 结束的数字 73 | @param duration 持续时间 74 | @param animationOptions 动画类型 75 | @param format 设置字体一般属性的block 76 | @param completion 完成的block 77 | */ 78 | - (void)pp_fromNumber:(CGFloat)numberA 79 | toNumber:(CGFloat)numberB 80 | duration:(CFTimeInterval)duration 81 | animationOptions:(PPCounterAnimationOptions)animationOptions 82 | format:(PPFormatBlock)format 83 | completion:(PPCompletionBlock)completion; 84 | 85 | 86 | #pragma mark - attributed 87 | 88 | /** 89 | 富文本字体属性UIButton中的数字在指定时间从 numberA -> numberB, 90 | 91 | @param numberA 开始的数字 92 | @param numberB 结束的数字 93 | @param duration 持续时间 94 | @param attributedFormat 设置富文本字体属性的Block 95 | */ 96 | - (void)pp_fromNumber:(CGFloat)numberA 97 | toNumber:(CGFloat)numberB 98 | duration:(CFTimeInterval)duration 99 | attributedFormat:(PPAttributedFormatBlock)attributedFormat; 100 | 101 | /** 102 | 1.富文本字体属性UIButton中的数字在指定时间从 numberA -> numberB, 103 | 2.有结束回调 104 | 105 | @param numberA 开始的数字 106 | @param numberB 结束的数字 107 | @param duration 持续时间 108 | @param attributedFormat 设置富文本字体属性的Block 109 | @param completion 完成的Block 110 | */ 111 | - (void)pp_fromNumber:(CGFloat)numberA 112 | toNumber:(CGFloat)numberB 113 | duration:(CFTimeInterval)duration 114 | attributedFormat:(PPAttributedFormatBlock)attributedFormat 115 | completion:(PPCompletionBlock)completion; 116 | 117 | /** 118 | 1.富文本字体属性UIButton中的数字在指定时间从 numberA -> numberB, 119 | 2.可设置动画类型, 120 | 3.有结束回调 121 | 122 | @param numberA 开始的数字 123 | @param numberB 结束的数字 124 | @param duration 持续时间 125 | @param animationOptions 动画类型 126 | @param attributedFormat 设置富文本字体属性的Block 127 | @param completion 完成的Block 128 | */ 129 | - (void)pp_fromNumber:(CGFloat)numberA 130 | toNumber:(CGFloat)numberB 131 | duration:(CFTimeInterval)duration 132 | animationOptions:(PPCounterAnimationOptions)animationOptions 133 | attributedFormat:(PPAttributedFormatBlock)attributedFormat 134 | completion:(PPCompletionBlock)completion; 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /PPCounter/UIKit/UIButton+PPCounter.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+PPCounter.m 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/17. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import "UIButton+PPCounter.h" 28 | #import 29 | 30 | @implementation UIButton (PPCounter) 31 | 32 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration format:(PPFormatBlock)format 33 | { 34 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut format:format completion:nil]; 35 | } 36 | 37 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration format:(PPFormatBlock)format completion:(PPCompletionBlock)completion 38 | { 39 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut format:format completion:completion]; 40 | } 41 | 42 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration attributedFormat:(PPAttributedFormatBlock)attributedFormat 43 | { 44 | 45 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut attributedFormat:attributedFormat completion:nil]; 46 | } 47 | 48 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration attributedFormat:(PPAttributedFormatBlock)attributedFormat completion:(PPCompletionBlock)completion 49 | { 50 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut attributedFormat:attributedFormat completion:completion]; 51 | } 52 | 53 | #pragma mark - normal font 54 | - (void)pp_fromNumber:(CGFloat)numberA 55 | toNumber:(CGFloat)numberB 56 | duration:(CFTimeInterval)duration 57 | animationOptions:(PPCounterAnimationOptions)animationOptions 58 | format:(PPFormatBlock)format 59 | completion:(PPCompletionBlock)completion 60 | { 61 | if (self.animationOptions) {animationOptions = self.animationOptions;} 62 | 63 | [[PPCounterEngine counterEngine] fromNumber:numberA toNumber:numberB duration:duration animationOptions:animationOptions currentNumber:^(CGFloat number) { 64 | 65 | format ? [self setTitle:format(number) forState:UIControlStateNormal] : nil ; 66 | 67 | } completion:completion]; 68 | 69 | } 70 | 71 | #pragma mark - attributed font 72 | - (void)pp_fromNumber:(CGFloat)numberA 73 | toNumber:(CGFloat)numberB 74 | duration:(CFTimeInterval)duration 75 | animationOptions:(PPCounterAnimationOptions)animationOptions 76 | attributedFormat:(PPAttributedFormatBlock)attributedFormat 77 | completion:(PPCompletionBlock)completion 78 | { 79 | if (self.animationOptions) {animationOptions = self.animationOptions;} 80 | 81 | [[PPCounterEngine counterEngine] fromNumber:numberA toNumber:numberB duration:duration animationOptions:animationOptions currentNumber:^(CGFloat number) { 82 | 83 | attributedFormat ? [self setAttributedTitle:attributedFormat(number) forState:UIControlStateNormal] : nil ; 84 | 85 | } completion:completion]; 86 | } 87 | 88 | #pragma mark - setter/getter 89 | 90 | - (void)setAnimationOptions:(PPCounterAnimationOptions)animationOptions 91 | { 92 | objc_setAssociatedObject(self, &kPPCounterAnimationOptions, @(animationOptions), OBJC_ASSOCIATION_ASSIGN); 93 | } 94 | 95 | - (PPCounterAnimationOptions)animationOptions 96 | { 97 | return [objc_getAssociatedObject(self, &kPPCounterAnimationOptions) integerValue]; 98 | } 99 | @end 100 | -------------------------------------------------------------------------------- /PPCounter/UIKit/UILabel+PPCounter.h: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+PPCounter.h 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/15. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import 28 | #import "PPCounterEngine.h" 29 | 30 | @interface UILabel (PPCounter) 31 | 32 | /** 动画类型*/ 33 | @property (nonatomic, assign) PPCounterAnimationOptions animationOptions; 34 | 35 | 36 | #pragma mark - normal 37 | 38 | /** 39 | 正常字体属性UILabel中的数字在指定时间从 numberA -> numberB, 40 | 41 | @param numberA 开始的数字 42 | @param numberB 结束的数字 43 | @param duration 持续时间 44 | @param format 设置字体一般属性的Block 45 | */ 46 | - (void)pp_fromNumber:(CGFloat)numberA 47 | toNumber:(CGFloat)numberB 48 | duration:(CFTimeInterval)duration 49 | format:(PPFormatBlock)format; 50 | 51 | /** 52 | 1.正常字体属性UILabel中的数字在指定时间从 numberA -> numberB, 53 | 2.有结束回调 54 | 55 | @param numberA 开始的数字 56 | @param numberB 结束的数字 57 | @param duration 持续时间 58 | @param format 设置一般字体的Block 59 | @param completion 完成的Block 60 | */ 61 | - (void)pp_fromNumber:(CGFloat)numberA 62 | toNumber:(CGFloat)numberB 63 | duration:(CFTimeInterval)duration 64 | format:(PPFormatBlock)format 65 | completion:(PPCompletionBlock)completion; 66 | 67 | /** 68 | 1.正常字体属性UILabel中的数字在指定时间从 numberA -> numberB, 69 | 2.可设置动画类型, 70 | 3.有结束回调 71 | 72 | @param numberA 开始的数字 73 | @param numberB 结束的数字 74 | @param duration 持续时间 75 | @param animationOptions 动画类型 76 | @param format 设置字体一般属性的block 77 | @param completion 完成的block 78 | */ 79 | - (void)pp_fromNumber:(CGFloat)numberA 80 | toNumber:(CGFloat)numberB 81 | duration:(CFTimeInterval)duration 82 | animationOptions:(PPCounterAnimationOptions)animationOptions 83 | format:(PPFormatBlock)format 84 | completion:(PPCompletionBlock)completion; 85 | 86 | 87 | #pragma mark - attributed 88 | 89 | /** 90 | 富文本字体属性UILabel中的数字在指定时间从 numberA -> numberB, 91 | 92 | @param numberA 开始的数字 93 | @param numberB 结束的数字 94 | @param duration 持续时间 95 | @param attributedFormat 设置富文本字体属性的Block 96 | */ 97 | - (void)pp_fromNumber:(CGFloat)numberA 98 | toNumber:(CGFloat)numberB 99 | duration:(CFTimeInterval)duration 100 | attributedFormat:(PPAttributedFormatBlock)attributedFormat; 101 | 102 | /** 103 | 1.富文本字体属性UILabel中的数字在指定时间从 numberA -> numberB, 104 | 2.有结束回调 105 | 106 | @param numberA 开始的数字 107 | @param numberB 结束的数字 108 | @param duration 持续时间 109 | @param attributedFormat 设置富文本字体属性的Block 110 | @param completion 完成的Block 111 | */ 112 | 113 | - (void)pp_fromNumber:(CGFloat)numberA 114 | toNumber:(CGFloat)numberB 115 | duration:(CFTimeInterval)duration 116 | attributedFormat:(PPAttributedFormatBlock)attributedFormat 117 | completion:(PPCompletionBlock)completion; 118 | 119 | /** 120 | 1.富文本字体属性UILabel中的数字在指定时间从 numberA -> numberB, 121 | 2.可设置动画类型, 122 | 3.有结束回调 123 | 124 | @param numberA 开始的数字 125 | @param numberB 结束的数字 126 | @param duration 持续时间 127 | @param animationOptions 动画类型 128 | @param attributedFormat 设置富文本字体属性的Block 129 | @param completion 完成的Block 130 | */ 131 | - (void)pp_fromNumber:(CGFloat)numberA 132 | toNumber:(CGFloat)numberB 133 | duration:(CFTimeInterval)duration 134 | animationOptions:(PPCounterAnimationOptions)animationOptions 135 | attributedFormat:(PPAttributedFormatBlock)attributedFormat 136 | completion:(PPCompletionBlock)completion; 137 | 138 | @end 139 | -------------------------------------------------------------------------------- /PPCounter/UIKit/UILabel+PPCounter.m: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+PPCounter.m 3 | // PPCounter 4 | // 5 | // Created by AndyPang on 16/10/15. 6 | // Copyright © 2016年 AndyPang. All rights reserved. 7 | // 8 | 9 | /* 10 | ********************************************************************************* 11 | * 12 | *⭐️⭐️⭐️ 新建 PP-iOS学习交流群: 323408051 欢迎加入!!! ⭐️⭐️⭐️ 13 | * 14 | * 如果您在使用 PPCounter 的过程中出现bug或有更好的建议,还请及时以下列方式联系我,我会及 15 | * 时修复bug,解决问题. 16 | * 17 | * Weibo : jkpang-庞 18 | * Email : jkpang@outlook.com 19 | * QQ 群 : 323408051 20 | * GitHub: https://github.com/jkpang 21 | * 22 | * 如果 PPCounter 好用,希望您能Star支持,你的 ⭐️ 是我持续更新的动力! 23 | * 24 | ********************************************************************************* 25 | */ 26 | 27 | #import "UILabel+PPCounter.h" 28 | #import 29 | 30 | @implementation UILabel (PPCounter) 31 | 32 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration format:(PPFormatBlock)format 33 | { 34 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut format:format completion:nil]; 35 | } 36 | 37 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration format:(PPFormatBlock)format completion:(PPCompletionBlock)completion 38 | { 39 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut format:format completion:completion]; 40 | } 41 | 42 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration attributedFormat:(PPAttributedFormatBlock)attributedFormat 43 | { 44 | 45 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut attributedFormat:attributedFormat completion:nil]; 46 | } 47 | 48 | - (void)pp_fromNumber:(CGFloat)numberA toNumber:(CGFloat)numberB duration:(CFTimeInterval)duration attributedFormat:(PPAttributedFormatBlock)attributedFormat completion:(PPCompletionBlock)completion 49 | { 50 | [self pp_fromNumber:numberA toNumber:numberB duration:duration animationOptions:PPCounterAnimationOptionCurveEaseInOut attributedFormat:attributedFormat completion:completion]; 51 | } 52 | 53 | #pragma mark - normal font 54 | - (void)pp_fromNumber:(CGFloat)numberA 55 | toNumber:(CGFloat)numberB 56 | duration:(CFTimeInterval)duration 57 | animationOptions:(PPCounterAnimationOptions)animationOptions 58 | format:(PPFormatBlock)format 59 | completion:(PPCompletionBlock)completion 60 | { 61 | if (self.animationOptions) {animationOptions = self.animationOptions;} 62 | 63 | [[PPCounterEngine counterEngine] fromNumber:numberA toNumber:numberB duration:duration animationOptions:animationOptions currentNumber:^(CGFloat number) { 64 | 65 | format ? self.text = format(number) : nil ; 66 | 67 | } completion:completion]; 68 | 69 | } 70 | 71 | #pragma mark - attributed font 72 | - (void)pp_fromNumber:(CGFloat)numberA 73 | toNumber:(CGFloat)numberB 74 | duration:(CFTimeInterval)duration 75 | animationOptions:(PPCounterAnimationOptions)animationOptions 76 | attributedFormat:(PPAttributedFormatBlock)attributedFormat 77 | completion:(PPCompletionBlock)completion 78 | { 79 | if (self.animationOptions) {animationOptions = self.animationOptions;} 80 | 81 | [[PPCounterEngine counterEngine] fromNumber:numberA toNumber:numberB duration:duration animationOptions:animationOptions currentNumber:^(CGFloat number) { 82 | 83 | attributedFormat ? self.attributedText = attributedFormat(number) : nil ; 84 | 85 | } completion:completion]; 86 | } 87 | 88 | #pragma mark - setter/getter 89 | 90 | - (void)setAnimationOptions:(PPCounterAnimationOptions)animationOptions 91 | { 92 | objc_setAssociatedObject(self, &kPPCounterAnimationOptions, @(animationOptions), OBJC_ASSOCIATION_ASSIGN); 93 | } 94 | 95 | - (PPCounterAnimationOptions)animationOptions 96 | { 97 | return [objc_getAssociatedObject(self, &kPPCounterAnimationOptions) integerValue]; 98 | } 99 | @end 100 | -------------------------------------------------------------------------------- /Picture/Mac.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/Picture/Mac.gif -------------------------------------------------------------------------------- /Picture/PPCounter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/Picture/PPCounter.gif -------------------------------------------------------------------------------- /Picture/PPCounter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkpang/PPCounter/3d6e0cef4162347034c8f8a0638167312bd7d247/Picture/PPCounter.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/jkpang/PPCounter/blob/master/Picture/PPCounter.png) 2 | 3 | ![](https://img.shields.io/badge/platform-iOS%7CmacOS-red.svg) ![](https://img.shields.io/badge/language-Objective--C-orange.svg) ![](https://img.shields.io/cocoapods/v/PPCounter.svg?style=flat) ![](https://img.shields.io/cocoapods/dt/PPCounter.svg) ![](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg) [![](https://img.shields.io/badge/weibo-jkpang--%E5%BA%9E-red.svg)](http://weibo.com/5743737098/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) 4 | 5 | iOS与macOS中一款优雅的数字/金额增减动效控件 6 | 7 | ![iPhone](https://github.com/jkpang/PPCounter/blob/master/Picture/PPCounter.gif) 8 | ![Mac](https://github.com/jkpang/PPCounter/blob/master/Picture/Mac.gif) 9 | 10 | * 支持iOS/macOS双平台(pods版本v0.5.0起支持) 11 | * 支持UILable/UIButton/自定义文本 控件的数字加减动画; 12 | * 支持一般文本属性以及富文本属性的字体显示; 13 | * 支持四种时间曲线函数动画:由慢到快再到慢、由慢到特别快、由快到慢、匀速; 14 | * 支持自定义的文本格式,例如:数字格式化千分位显示; 15 | * 支持CocoaPods导入 16 | 17 | 18 | ### 新建 PP-iOS学习交流群 : 323408051 有关于PP系列封装的问题和iOS技术可以在此群讨论 19 | 20 | 21 | ### [简书地址](http://www.jianshu.com/p/53b9bac43201) 22 | 23 | ## Requirements 要求 24 | * iOS 7+ 25 | * macOS 10.10+ 26 | * Xcode 8+ 27 | 28 | ## Installation 安装 29 | ### 1.手动安装: 30 | `下载DEMO后,将子文件夹PPCounter拖入到项目中, 导入头文件 PPCounter.h 开始使用` 31 | ### 2.CocoaPods安装: 32 | first 33 | `pod 'PPCounter',:git => 'https://github.com/jkpang/PPCounter.git'` 34 | 35 | then 36 | `pod install 或 pod install --no-repo-update` 37 | 38 | 如果发现pod search PPCounter 不是最新版本,在终端执行pod setup命令更新本地spec镜像缓存(时间可能有点长),重新搜索就OK了 39 | ## Usage 使用方法 40 | ### 1. UILabel 41 | #### 1.1 设置一般字体属性UILabel 42 | ```objc 43 | .... 44 | [label pp_fromNumber:0 toNumber:100 duration:1.5 animationOptions:PPCounterAnimationOptionCurveEaseOut format:^NSString *(CGFloat number) { 45 | // 此处自由拼接内容 46 | return [NSString stringWithFormat:@"%.2f",number]; 47 | } completion:^{ 48 | 49 | // 完成的回调 50 | }]; 51 | ``` 52 | #### 1.2 设置富文本字体属性UILabel 53 | 54 | ```objc 55 | .... 56 | [label pp_fromNumber:0 toNumber:100 duration:1.5 animationOptions:PPCounterAnimationOptionCurveEaseOut attributedFormat:^NSAttributedString *(CGFloat number) { 57 | 58 | // 此处自由设置富文本属性的内容 59 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@""]; 60 | return attributedString; 61 | } completion:^{ 62 | 63 | // 完成的回调 64 | }]; 65 | 66 | ``` 67 | ### 2. UIButton 68 | 69 | #### 2.1 设置一般字体属性UIButton 70 | ```objc 71 | .... 72 | [button pp_fromNumber:0 toNumber:100 duration:1.5 animationOptions:PPCounterAnimationOptionCurveEaseOut format:^NSString *(CGFloat number) { 73 | // 此处自由拼接内容 74 | return [NSString stringWithFormat:@"%.2f",number]; 75 | } completion:^{ 76 | 77 | // 完成的回调 78 | }]; 79 | ``` 80 | #### 2.2 设置富文本字体属性UIButton 81 | 82 | ```objc 83 | .... 84 | [button pp_fromNumber:0 toNumber:100 duration:1.5 animationOptions:PPCounterAnimationOptionCurveEaseOut attributedFormat:^NSAttributedString *(CGFloat number) { 85 | 86 | // 此处自由设置富文本属性的内容 87 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@""]; 88 | return attributedString; 89 | } completion:^{ 90 | 91 | // 完成的回调 92 | }]; 93 | 94 | ``` 95 | 96 | 以上就是PPCounter的简单使用方法,更详细的用法请看demo 97 | ### 3, macOS Platform 使用 98 | 99 | ```objc 100 | [[PPCounterEngine counterEngine] fromNumber:0 101 | toNumber:999 102 | duration:2.f 103 | animationOptions:PPCounterAnimationOptionCurveEaseOut 104 | currentNumber:^(CGFloat number) { 105 | // lable控件 106 | self.numberLabel.stringValue = [NSString stringWithFormat:@"%ld",(NSInteger)number]; 107 | } completion:^{ 108 | // 计数完成的回调 109 | self.numberLabel.textColor = [NSColor redColor]; 110 | }]; 111 | ``` 112 | ### 你的star是我持续更新的动力! 113 | === 114 | ## CocoaPods更新日志 115 | * 2017.03.07(tag:0.6.0)--Mac下的定时器由 NSTimer --> dispatch_source_t; 116 | * 2017.03.07(tag:0.5.0)--支持iOS/MacOS双平台; 117 | * 2017.01.07(tag:0.2.0)--优化代码命名规范; 118 | * 2016.10.23(tag:0.1.1)--优化代码结构与调用API方法; 119 | * 2016.10.19(tag:0.1.0)--初始化到CocoaPods; 120 | 121 | ## 我的App <-> My APP 122 | - [PPHub](https://github.com/PPHubApp/PPHub-Feedback):一个简洁漂亮的 GitHub iOS客户端 <-> A simple and beautiful GitHub iOS client 123 | [![App_Store](https://github.com/jkpang/PPHub-Feedback/blob/master/Resource/Download_on_the_App_Store_135x40.svg)](https://itunes.apple.com/cn/app/PPHub%20For%20GitHub/id1314212521?mt=8) 124 | 125 | ## 联系方式: 126 | * Weibo : [@jkpang-庞](http://weibo.com/5743737098/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) 127 | * Email : jkpang@outlook.com 128 | * QQ群 : 323408051 129 | 130 | ![PP-iOS学习交流群群二维码](https://github.com/jkpang/PPCounter/blob/master/PP-iOS%E5%AD%A6%E4%B9%A0%E4%BA%A4%E6%B5%81%E7%BE%A4%E7%BE%A4%E4%BA%8C%E7%BB%B4%E7%A0%81.png) 131 | 132 | ## 许可证 133 | PPCounter 使用 MIT 许可证,详情见 LICENSE 文件。 134 | 135 | --------------------------------------------------------------------------------