├── .gitignore ├── CHANGELOG.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── MetricPrefixNumberFormatter.podspec ├── MetricPrefixNumberFormatter.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── MetricPrefixNumberFormatter.xcscheme │ └── iOS Example.xcscheme ├── Plist ├── Framework.plist └── Tests.plist ├── README.md ├── Source ├── MetricPrefix.swift ├── MetricPrefixNumberFormatter+Extension.swift └── MetricPrefixNumberFormatter.swift ├── Tests └── Tests.swift ├── iOS Example ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── ExampleViewController.swift └── Info.plist └── logo.png /.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 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## 1.1.0 4 | 5 | * Updated to Swift 5. 6 | 7 | ## 1.0.0 8 | 9 | Initial release. 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'cocoapods', '~> 1.6.0' 4 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.0) 5 | activesupport (4.2.11) 6 | i18n (~> 0.7) 7 | minitest (~> 5.1) 8 | thread_safe (~> 0.3, >= 0.3.4) 9 | tzinfo (~> 1.1) 10 | atomos (0.1.3) 11 | claide (1.0.2) 12 | cocoapods (1.6.1) 13 | activesupport (>= 4.0.2, < 5) 14 | claide (>= 1.0.2, < 2.0) 15 | cocoapods-core (= 1.6.1) 16 | cocoapods-deintegrate (>= 1.0.2, < 2.0) 17 | cocoapods-downloader (>= 1.2.2, < 2.0) 18 | cocoapods-plugins (>= 1.0.0, < 2.0) 19 | cocoapods-search (>= 1.0.0, < 2.0) 20 | cocoapods-stats (>= 1.0.0, < 2.0) 21 | cocoapods-trunk (>= 1.3.1, < 2.0) 22 | cocoapods-try (>= 1.1.0, < 2.0) 23 | colored2 (~> 3.1) 24 | escape (~> 0.0.4) 25 | fourflusher (>= 2.2.0, < 3.0) 26 | gh_inspector (~> 1.0) 27 | molinillo (~> 0.6.6) 28 | nap (~> 1.0) 29 | ruby-macho (~> 1.4) 30 | xcodeproj (>= 1.8.1, < 2.0) 31 | cocoapods-core (1.6.1) 32 | activesupport (>= 4.0.2, < 6) 33 | fuzzy_match (~> 2.0.4) 34 | nap (~> 1.0) 35 | cocoapods-deintegrate (1.0.3) 36 | cocoapods-downloader (1.2.2) 37 | cocoapods-plugins (1.0.0) 38 | nap 39 | cocoapods-search (1.0.0) 40 | cocoapods-stats (1.1.0) 41 | cocoapods-trunk (1.3.1) 42 | nap (>= 0.8, < 2.0) 43 | netrc (~> 0.11) 44 | cocoapods-try (1.1.0) 45 | colored2 (3.1.2) 46 | concurrent-ruby (1.1.4) 47 | escape (0.0.4) 48 | fourflusher (2.2.0) 49 | fuzzy_match (2.0.4) 50 | gh_inspector (1.1.3) 51 | i18n (0.9.5) 52 | concurrent-ruby (~> 1.0) 53 | minitest (5.11.3) 54 | molinillo (0.6.6) 55 | nanaimo (0.2.6) 56 | nap (1.1.0) 57 | netrc (0.11.0) 58 | ruby-macho (1.4.0) 59 | thread_safe (0.3.6) 60 | tzinfo (1.2.5) 61 | thread_safe (~> 0.1) 62 | xcodeproj (1.8.1) 63 | CFPropertyList (>= 2.3.3, < 4.0) 64 | atomos (~> 0.1.3) 65 | claide (>= 1.0.2, < 2.0) 66 | colored2 (~> 3.1) 67 | nanaimo (~> 0.2.6) 68 | 69 | PLATFORMS 70 | ruby 71 | 72 | DEPENDENCIES 73 | cocoapods (~> 1.6.0) 74 | 75 | BUNDLED WITH 76 | 2.0.1 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Rostyslav Dovhaliuk 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 | -------------------------------------------------------------------------------- /MetricPrefixNumberFormatter.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "MetricPrefixNumberFormatter" 3 | s.version = "1.1.0" 4 | s.summary = "NSNumberFormatter subclass designed to format large and small numbers using the metric prefixes." 5 | s.homepage = "https://github.com/RenGate/MetricPrefixNumberFormatter" 6 | s.license = 'MIT' 7 | s.authors = { 'Rostyslav Dovhaliuk' => 'rdovhaliuk@gmail.com' } 8 | s.social_media_url = 'https://twitter.com/rostyslav_d' 9 | s.ios.deployment_target = '8.0' 10 | s.source = { :git => 'https://github.com/RenGate/MetricPrefixNumberFormatter.git', :tag => s.version.to_s } 11 | s.source_files = "Source/*.{swift}" 12 | s.swift_version = '5.0' 13 | s.ios.frameworks = "Foundation" 14 | end 15 | -------------------------------------------------------------------------------- /MetricPrefixNumberFormatter.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3E3E0FAA21623CD90055258B /* MetricPrefixNumberFormatter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3E0FA021623CD90055258B /* MetricPrefixNumberFormatter.framework */; }; 11 | 3E3E0FC721623D6B0055258B /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3E0FBD21623D560055258B /* Tests.swift */; }; 12 | 639408E8223BD05600D5C7E6 /* MetricPrefixNumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 639408E7223BD05600D5C7E6 /* MetricPrefixNumberFormatter.swift */; }; 13 | 639408EA223BF45000D5C7E6 /* MetricPrefix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 639408E9223BF45000D5C7E6 /* MetricPrefix.swift */; }; 14 | 639408EC223BF77800D5C7E6 /* MetricPrefixNumberFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 639408EB223BF77800D5C7E6 /* MetricPrefixNumberFormatter+Extension.swift */; }; 15 | 9A5A7009217DF23000DA5152 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5A7008217DF23000DA5152 /* AppDelegate.swift */; }; 16 | 9A5A700E217DF23000DA5152 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9A5A700C217DF23000DA5152 /* Main.storyboard */; }; 17 | 9A5A7010217DF23100DA5152 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9A5A700F217DF23100DA5152 /* Assets.xcassets */; }; 18 | 9A5A7013217DF23100DA5152 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9A5A7011217DF23100DA5152 /* LaunchScreen.storyboard */; }; 19 | 9A5A701B217E181700DA5152 /* ExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5A701A217E181700DA5152 /* ExampleViewController.swift */; }; 20 | 9A5A701E217E1A1100DA5152 /* MetricPrefixNumberFormatter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3E0FA021623CD90055258B /* MetricPrefixNumberFormatter.framework */; }; 21 | 9A5A701F217E1A1100DA5152 /* MetricPrefixNumberFormatter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3E0FA021623CD90055258B /* MetricPrefixNumberFormatter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 6382E0E2229312F700DE0410 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 3E3E0F9721623CD90055258B /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 3E3E0F9F21623CD90055258B; 30 | remoteInfo = MetricPrefixNumberFormatter; 31 | }; 32 | 6382E0E3229312F700DE0410 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 3E3E0F9721623CD90055258B /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 3E3E0F9F21623CD90055258B; 37 | remoteInfo = MetricPrefixNumberFormatter; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXCopyFilesBuildPhase section */ 42 | 9A5A7022217E1A1100DA5152 /* Embed Frameworks */ = { 43 | isa = PBXCopyFilesBuildPhase; 44 | buildActionMask = 2147483647; 45 | dstPath = ""; 46 | dstSubfolderSpec = 10; 47 | files = ( 48 | 9A5A701F217E1A1100DA5152 /* MetricPrefixNumberFormatter.framework in Embed Frameworks */, 49 | ); 50 | name = "Embed Frameworks"; 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXCopyFilesBuildPhase section */ 54 | 55 | /* Begin PBXFileReference section */ 56 | 3E3E0FA021623CD90055258B /* MetricPrefixNumberFormatter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MetricPrefixNumberFormatter.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 3E3E0FA921623CD90055258B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 3E3E0FBD21623D560055258B /* Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 59 | 3E3E0FBF21623D560055258B /* Tests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Tests.plist; sourceTree = ""; }; 60 | 3E3E0FC021623D560055258B /* Framework.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Framework.plist; sourceTree = ""; }; 61 | 639408E7223BD05600D5C7E6 /* MetricPrefixNumberFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricPrefixNumberFormatter.swift; sourceTree = ""; }; 62 | 639408E9223BF45000D5C7E6 /* MetricPrefix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricPrefix.swift; sourceTree = ""; }; 63 | 639408EB223BF77800D5C7E6 /* MetricPrefixNumberFormatter+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MetricPrefixNumberFormatter+Extension.swift"; sourceTree = ""; }; 64 | 9A5A7006217DF23000DA5152 /* iOS Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | 9A5A7008217DF23000DA5152 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 66 | 9A5A700D217DF23000DA5152 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 67 | 9A5A700F217DF23100DA5152 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 68 | 9A5A7012217DF23100DA5152 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 69 | 9A5A7014217DF23100DA5152 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70 | 9A5A701A217E181700DA5152 /* ExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleViewController.swift; sourceTree = ""; }; 71 | /* End PBXFileReference section */ 72 | 73 | /* Begin PBXFrameworksBuildPhase section */ 74 | 3E3E0F9D21623CD90055258B /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | 3E3E0FA621623CD90055258B /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | 3E3E0FAA21623CD90055258B /* MetricPrefixNumberFormatter.framework in Frameworks */, 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | 9A5A7003217DF23000DA5152 /* Frameworks */ = { 90 | isa = PBXFrameworksBuildPhase; 91 | buildActionMask = 2147483647; 92 | files = ( 93 | 9A5A701E217E1A1100DA5152 /* MetricPrefixNumberFormatter.framework in Frameworks */, 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | /* End PBXFrameworksBuildPhase section */ 98 | 99 | /* Begin PBXGroup section */ 100 | 3E3E0F9621623CD90055258B = { 101 | isa = PBXGroup; 102 | children = ( 103 | 3E3E0FBE21623D560055258B /* Plist */, 104 | 3E3E0FBA21623D560055258B /* Source */, 105 | 3E3E0FBC21623D560055258B /* Tests */, 106 | 9A5A7007217DF23000DA5152 /* iOS Example */, 107 | 3E3E0FA121623CD90055258B /* Products */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | 3E3E0FA121623CD90055258B /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 3E3E0FA021623CD90055258B /* MetricPrefixNumberFormatter.framework */, 115 | 3E3E0FA921623CD90055258B /* Tests.xctest */, 116 | 9A5A7006217DF23000DA5152 /* iOS Example.app */, 117 | ); 118 | name = Products; 119 | sourceTree = ""; 120 | }; 121 | 3E3E0FBA21623D560055258B /* Source */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 639408E9223BF45000D5C7E6 /* MetricPrefix.swift */, 125 | 639408E7223BD05600D5C7E6 /* MetricPrefixNumberFormatter.swift */, 126 | 639408EB223BF77800D5C7E6 /* MetricPrefixNumberFormatter+Extension.swift */, 127 | ); 128 | path = Source; 129 | sourceTree = ""; 130 | }; 131 | 3E3E0FBC21623D560055258B /* Tests */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 3E3E0FBD21623D560055258B /* Tests.swift */, 135 | ); 136 | path = Tests; 137 | sourceTree = ""; 138 | }; 139 | 3E3E0FBE21623D560055258B /* Plist */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 3E3E0FBF21623D560055258B /* Tests.plist */, 143 | 3E3E0FC021623D560055258B /* Framework.plist */, 144 | ); 145 | path = Plist; 146 | sourceTree = ""; 147 | }; 148 | 9A5A7007217DF23000DA5152 /* iOS Example */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 9A5A7008217DF23000DA5152 /* AppDelegate.swift */, 152 | 9A5A701A217E181700DA5152 /* ExampleViewController.swift */, 153 | 9A5A700C217DF23000DA5152 /* Main.storyboard */, 154 | 9A5A700F217DF23100DA5152 /* Assets.xcassets */, 155 | 9A5A7011217DF23100DA5152 /* LaunchScreen.storyboard */, 156 | 9A5A7014217DF23100DA5152 /* Info.plist */, 157 | ); 158 | path = "iOS Example"; 159 | sourceTree = ""; 160 | }; 161 | /* End PBXGroup section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | 3E3E0F9F21623CD90055258B /* MetricPrefixNumberFormatter */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = 3E3E0FB421623CD90055258B /* Build configuration list for PBXNativeTarget "MetricPrefixNumberFormatter" */; 167 | buildPhases = ( 168 | 3E3E0F9C21623CD90055258B /* Sources */, 169 | 3E3E0F9D21623CD90055258B /* Frameworks */, 170 | 3E3E0F9E21623CD90055258B /* Resources */, 171 | ); 172 | buildRules = ( 173 | ); 174 | dependencies = ( 175 | ); 176 | name = MetricPrefixNumberFormatter; 177 | productName = MetricPrefixNumberFormatter; 178 | productReference = 3E3E0FA021623CD90055258B /* MetricPrefixNumberFormatter.framework */; 179 | productType = "com.apple.product-type.framework"; 180 | }; 181 | 3E3E0FA821623CD90055258B /* Tests */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 3E3E0FB721623CD90055258B /* Build configuration list for PBXNativeTarget "Tests" */; 184 | buildPhases = ( 185 | 3E3E0FA521623CD90055258B /* Sources */, 186 | 3E3E0FA621623CD90055258B /* Frameworks */, 187 | 3E3E0FA721623CD90055258B /* Resources */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | 3E3E0FAC21623CD90055258B /* PBXTargetDependency */, 193 | ); 194 | name = Tests; 195 | productName = MetricPrefixNumberFormatterTests; 196 | productReference = 3E3E0FA921623CD90055258B /* Tests.xctest */; 197 | productType = "com.apple.product-type.bundle.unit-test"; 198 | }; 199 | 9A5A7005217DF23000DA5152 /* iOS Example */ = { 200 | isa = PBXNativeTarget; 201 | buildConfigurationList = 9A5A7017217DF23100DA5152 /* Build configuration list for PBXNativeTarget "iOS Example" */; 202 | buildPhases = ( 203 | 9A5A7002217DF23000DA5152 /* Sources */, 204 | 9A5A7003217DF23000DA5152 /* Frameworks */, 205 | 9A5A7004217DF23000DA5152 /* Resources */, 206 | 9A5A7022217E1A1100DA5152 /* Embed Frameworks */, 207 | ); 208 | buildRules = ( 209 | ); 210 | dependencies = ( 211 | 9A5A7021217E1A1100DA5152 /* PBXTargetDependency */, 212 | ); 213 | name = "iOS Example"; 214 | productName = "iOS Example"; 215 | productReference = 9A5A7006217DF23000DA5152 /* iOS Example.app */; 216 | productType = "com.apple.product-type.application"; 217 | }; 218 | /* End PBXNativeTarget section */ 219 | 220 | /* Begin PBXProject section */ 221 | 3E3E0F9721623CD90055258B /* Project object */ = { 222 | isa = PBXProject; 223 | attributes = { 224 | LastSwiftUpdateCheck = 1000; 225 | LastUpgradeCheck = 1000; 226 | ORGANIZATIONNAME = "Rostyslav Dovhaliuk"; 227 | TargetAttributes = { 228 | 3E3E0F9F21623CD90055258B = { 229 | CreatedOnToolsVersion = 10.0; 230 | LastSwiftMigration = 1020; 231 | }; 232 | 3E3E0FA821623CD90055258B = { 233 | CreatedOnToolsVersion = 10.0; 234 | LastSwiftMigration = 1020; 235 | }; 236 | 9A5A7005217DF23000DA5152 = { 237 | CreatedOnToolsVersion = 10.0; 238 | LastSwiftMigration = 1020; 239 | }; 240 | }; 241 | }; 242 | buildConfigurationList = 3E3E0F9A21623CD90055258B /* Build configuration list for PBXProject "MetricPrefixNumberFormatter" */; 243 | compatibilityVersion = "Xcode 9.3"; 244 | developmentRegion = en; 245 | hasScannedForEncodings = 0; 246 | knownRegions = ( 247 | en, 248 | Base, 249 | ); 250 | mainGroup = 3E3E0F9621623CD90055258B; 251 | productRefGroup = 3E3E0FA121623CD90055258B /* Products */; 252 | projectDirPath = ""; 253 | projectRoot = ""; 254 | targets = ( 255 | 3E3E0F9F21623CD90055258B /* MetricPrefixNumberFormatter */, 256 | 3E3E0FA821623CD90055258B /* Tests */, 257 | 9A5A7005217DF23000DA5152 /* iOS Example */, 258 | ); 259 | }; 260 | /* End PBXProject section */ 261 | 262 | /* Begin PBXResourcesBuildPhase section */ 263 | 3E3E0F9E21623CD90055258B /* Resources */ = { 264 | isa = PBXResourcesBuildPhase; 265 | buildActionMask = 2147483647; 266 | files = ( 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | 3E3E0FA721623CD90055258B /* Resources */ = { 271 | isa = PBXResourcesBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | 9A5A7004217DF23000DA5152 /* Resources */ = { 278 | isa = PBXResourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | 9A5A7013217DF23100DA5152 /* LaunchScreen.storyboard in Resources */, 282 | 9A5A7010217DF23100DA5152 /* Assets.xcassets in Resources */, 283 | 9A5A700E217DF23000DA5152 /* Main.storyboard in Resources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | /* End PBXResourcesBuildPhase section */ 288 | 289 | /* Begin PBXSourcesBuildPhase section */ 290 | 3E3E0F9C21623CD90055258B /* Sources */ = { 291 | isa = PBXSourcesBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | 639408E8223BD05600D5C7E6 /* MetricPrefixNumberFormatter.swift in Sources */, 295 | 639408EC223BF77800D5C7E6 /* MetricPrefixNumberFormatter+Extension.swift in Sources */, 296 | 639408EA223BF45000D5C7E6 /* MetricPrefix.swift in Sources */, 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | }; 300 | 3E3E0FA521623CD90055258B /* Sources */ = { 301 | isa = PBXSourcesBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | 3E3E0FC721623D6B0055258B /* Tests.swift in Sources */, 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | }; 308 | 9A5A7002217DF23000DA5152 /* Sources */ = { 309 | isa = PBXSourcesBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | 9A5A7009217DF23000DA5152 /* AppDelegate.swift in Sources */, 313 | 9A5A701B217E181700DA5152 /* ExampleViewController.swift in Sources */, 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | /* End PBXSourcesBuildPhase section */ 318 | 319 | /* Begin PBXTargetDependency section */ 320 | 3E3E0FAC21623CD90055258B /* PBXTargetDependency */ = { 321 | isa = PBXTargetDependency; 322 | target = 3E3E0F9F21623CD90055258B /* MetricPrefixNumberFormatter */; 323 | targetProxy = 6382E0E3229312F700DE0410 /* PBXContainerItemProxy */; 324 | }; 325 | 9A5A7021217E1A1100DA5152 /* PBXTargetDependency */ = { 326 | isa = PBXTargetDependency; 327 | target = 3E3E0F9F21623CD90055258B /* MetricPrefixNumberFormatter */; 328 | targetProxy = 6382E0E2229312F700DE0410 /* PBXContainerItemProxy */; 329 | }; 330 | /* End PBXTargetDependency section */ 331 | 332 | /* Begin PBXVariantGroup section */ 333 | 9A5A700C217DF23000DA5152 /* Main.storyboard */ = { 334 | isa = PBXVariantGroup; 335 | children = ( 336 | 9A5A700D217DF23000DA5152 /* Base */, 337 | ); 338 | name = Main.storyboard; 339 | sourceTree = ""; 340 | }; 341 | 9A5A7011217DF23100DA5152 /* LaunchScreen.storyboard */ = { 342 | isa = PBXVariantGroup; 343 | children = ( 344 | 9A5A7012217DF23100DA5152 /* Base */, 345 | ); 346 | name = LaunchScreen.storyboard; 347 | sourceTree = ""; 348 | }; 349 | /* End PBXVariantGroup section */ 350 | 351 | /* Begin XCBuildConfiguration section */ 352 | 3E3E0FB221623CD90055258B /* Debug */ = { 353 | isa = XCBuildConfiguration; 354 | buildSettings = { 355 | ALWAYS_SEARCH_USER_PATHS = NO; 356 | CLANG_ANALYZER_NONNULL = YES; 357 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 358 | CLANG_ENABLE_MODULES = YES; 359 | CLANG_ENABLE_OBJC_ARC = YES; 360 | CLANG_ENABLE_OBJC_WEAK = YES; 361 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 362 | CLANG_WARN_BOOL_CONVERSION = YES; 363 | CLANG_WARN_COMMA = YES; 364 | CLANG_WARN_CONSTANT_CONVERSION = YES; 365 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 366 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 367 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 368 | CLANG_WARN_EMPTY_BODY = YES; 369 | CLANG_WARN_ENUM_CONVERSION = YES; 370 | CLANG_WARN_INFINITE_RECURSION = YES; 371 | CLANG_WARN_INT_CONVERSION = YES; 372 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 373 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 374 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 375 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 376 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 377 | CLANG_WARN_STRICT_PROTOTYPES = YES; 378 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 379 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 380 | CLANG_WARN_UNREACHABLE_CODE = YES; 381 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 382 | CODE_SIGN_IDENTITY = "iPhone Developer"; 383 | COPY_PHASE_STRIP = NO; 384 | CURRENT_PROJECT_VERSION = 1; 385 | DEBUG_INFORMATION_FORMAT = dwarf; 386 | ENABLE_STRICT_OBJC_MSGSEND = YES; 387 | ENABLE_TESTABILITY = YES; 388 | GCC_DYNAMIC_NO_PIC = NO; 389 | GCC_NO_COMMON_BLOCKS = YES; 390 | GCC_OPTIMIZATION_LEVEL = 0; 391 | GCC_PREPROCESSOR_DEFINITIONS = ( 392 | "DEBUG=1", 393 | "$(inherited)", 394 | ); 395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 396 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 397 | GCC_WARN_UNDECLARED_SELECTOR = YES; 398 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 399 | GCC_WARN_UNUSED_FUNCTION = YES; 400 | GCC_WARN_UNUSED_VARIABLE = YES; 401 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 402 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 403 | MTL_FAST_MATH = YES; 404 | ONLY_ACTIVE_ARCH = YES; 405 | SDKROOT = iphoneos; 406 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; 407 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 408 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 409 | SWIFT_VERSION = 4.2; 410 | VERSIONING_SYSTEM = "apple-generic"; 411 | VERSION_INFO_PREFIX = ""; 412 | }; 413 | name = Debug; 414 | }; 415 | 3E3E0FB321623CD90055258B /* Release */ = { 416 | isa = XCBuildConfiguration; 417 | buildSettings = { 418 | ALWAYS_SEARCH_USER_PATHS = NO; 419 | CLANG_ANALYZER_NONNULL = YES; 420 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 421 | CLANG_ENABLE_MODULES = YES; 422 | CLANG_ENABLE_OBJC_ARC = YES; 423 | CLANG_ENABLE_OBJC_WEAK = YES; 424 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 425 | CLANG_WARN_BOOL_CONVERSION = YES; 426 | CLANG_WARN_COMMA = YES; 427 | CLANG_WARN_CONSTANT_CONVERSION = YES; 428 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 429 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 430 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 431 | CLANG_WARN_EMPTY_BODY = YES; 432 | CLANG_WARN_ENUM_CONVERSION = YES; 433 | CLANG_WARN_INFINITE_RECURSION = YES; 434 | CLANG_WARN_INT_CONVERSION = YES; 435 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 436 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 437 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 439 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 440 | CLANG_WARN_STRICT_PROTOTYPES = YES; 441 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 442 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 443 | CLANG_WARN_UNREACHABLE_CODE = YES; 444 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 445 | CODE_SIGN_IDENTITY = "iPhone Developer"; 446 | COPY_PHASE_STRIP = NO; 447 | CURRENT_PROJECT_VERSION = 1; 448 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 449 | ENABLE_NS_ASSERTIONS = NO; 450 | ENABLE_STRICT_OBJC_MSGSEND = YES; 451 | GCC_NO_COMMON_BLOCKS = YES; 452 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 453 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 454 | GCC_WARN_UNDECLARED_SELECTOR = YES; 455 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 456 | GCC_WARN_UNUSED_FUNCTION = YES; 457 | GCC_WARN_UNUSED_VARIABLE = YES; 458 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 459 | MTL_ENABLE_DEBUG_INFO = NO; 460 | MTL_FAST_MATH = YES; 461 | SDKROOT = iphoneos; 462 | SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; 463 | SWIFT_COMPILATION_MODE = wholemodule; 464 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 465 | SWIFT_VERSION = 4.2; 466 | VALIDATE_PRODUCT = YES; 467 | VERSIONING_SYSTEM = "apple-generic"; 468 | VERSION_INFO_PREFIX = ""; 469 | }; 470 | name = Release; 471 | }; 472 | 3E3E0FB521623CD90055258B /* Debug */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | APPLICATION_EXTENSION_API_ONLY = YES; 476 | CLANG_ENABLE_MODULES = YES; 477 | CODE_SIGN_IDENTITY = ""; 478 | CODE_SIGN_STYLE = Automatic; 479 | DEFINES_MODULE = YES; 480 | DYLIB_COMPATIBILITY_VERSION = 1; 481 | DYLIB_CURRENT_VERSION = 1; 482 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 483 | INFOPLIST_FILE = Plist/Framework.plist; 484 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 485 | LD_RUNPATH_SEARCH_PATHS = ( 486 | "$(inherited)", 487 | "@executable_path/Frameworks", 488 | "@loader_path/Frameworks", 489 | ); 490 | PRODUCT_BUNDLE_IDENTIFIER = com.rd.metricprefixnumberformatter; 491 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 492 | SKIP_INSTALL = YES; 493 | SWIFT_VERSION = 5.0; 494 | }; 495 | name = Debug; 496 | }; 497 | 3E3E0FB621623CD90055258B /* Release */ = { 498 | isa = XCBuildConfiguration; 499 | buildSettings = { 500 | APPLICATION_EXTENSION_API_ONLY = YES; 501 | CLANG_ENABLE_MODULES = YES; 502 | CODE_SIGN_IDENTITY = ""; 503 | CODE_SIGN_STYLE = Automatic; 504 | DEFINES_MODULE = YES; 505 | DYLIB_COMPATIBILITY_VERSION = 1; 506 | DYLIB_CURRENT_VERSION = 1; 507 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 508 | INFOPLIST_FILE = Plist/Framework.plist; 509 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 510 | LD_RUNPATH_SEARCH_PATHS = ( 511 | "$(inherited)", 512 | "@executable_path/Frameworks", 513 | "@loader_path/Frameworks", 514 | ); 515 | PRODUCT_BUNDLE_IDENTIFIER = com.rd.metricprefixnumberformatter; 516 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 517 | SKIP_INSTALL = YES; 518 | SWIFT_VERSION = 5.0; 519 | }; 520 | name = Release; 521 | }; 522 | 3E3E0FB821623CD90055258B /* Debug */ = { 523 | isa = XCBuildConfiguration; 524 | buildSettings = { 525 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 526 | CODE_SIGN_IDENTITY = ""; 527 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 528 | CODE_SIGN_STYLE = Automatic; 529 | DEVELOPMENT_TEAM = ""; 530 | INFOPLIST_FILE = Plist/Tests.plist; 531 | LD_RUNPATH_SEARCH_PATHS = ( 532 | "$(inherited)", 533 | "@executable_path/Frameworks", 534 | "@loader_path/Frameworks", 535 | ); 536 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( 537 | "$(inherited)", 538 | "@executable_path/../Frameworks", 539 | "@loader_path/../Frameworks", 540 | ); 541 | PRODUCT_BUNDLE_IDENTIFIER = com.rd.metricprefixnumberformattertests; 542 | PRODUCT_NAME = "$(TARGET_NAME)"; 543 | PROVISIONING_PROFILE_SPECIFIER = ""; 544 | SWIFT_VERSION = 5.0; 545 | }; 546 | name = Debug; 547 | }; 548 | 3E3E0FB921623CD90055258B /* Release */ = { 549 | isa = XCBuildConfiguration; 550 | buildSettings = { 551 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 552 | CODE_SIGN_IDENTITY = ""; 553 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 554 | CODE_SIGN_STYLE = Automatic; 555 | DEVELOPMENT_TEAM = ""; 556 | INFOPLIST_FILE = Plist/Tests.plist; 557 | LD_RUNPATH_SEARCH_PATHS = ( 558 | "$(inherited)", 559 | "@executable_path/Frameworks", 560 | "@loader_path/Frameworks", 561 | ); 562 | "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( 563 | "$(inherited)", 564 | "@executable_path/../Frameworks", 565 | "@loader_path/../Frameworks", 566 | ); 567 | PRODUCT_BUNDLE_IDENTIFIER = com.rd.metricprefixnumberformattertests; 568 | PRODUCT_NAME = "$(TARGET_NAME)"; 569 | PROVISIONING_PROFILE_SPECIFIER = ""; 570 | SWIFT_VERSION = 5.0; 571 | }; 572 | name = Release; 573 | }; 574 | 9A5A7015217DF23100DA5152 /* Debug */ = { 575 | isa = XCBuildConfiguration; 576 | buildSettings = { 577 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 578 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 579 | CODE_SIGN_STYLE = Automatic; 580 | INFOPLIST_FILE = "iOS Example/Info.plist"; 581 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 582 | LD_RUNPATH_SEARCH_PATHS = ( 583 | "$(inherited)", 584 | "@executable_path/Frameworks", 585 | ); 586 | PRODUCT_BUNDLE_IDENTIFIER = "com.rd.ios-example"; 587 | PRODUCT_NAME = "$(TARGET_NAME)"; 588 | SWIFT_VERSION = 5.0; 589 | TARGETED_DEVICE_FAMILY = "1,2"; 590 | }; 591 | name = Debug; 592 | }; 593 | 9A5A7016217DF23100DA5152 /* Release */ = { 594 | isa = XCBuildConfiguration; 595 | buildSettings = { 596 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 597 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 598 | CODE_SIGN_STYLE = Automatic; 599 | INFOPLIST_FILE = "iOS Example/Info.plist"; 600 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 601 | LD_RUNPATH_SEARCH_PATHS = ( 602 | "$(inherited)", 603 | "@executable_path/Frameworks", 604 | ); 605 | PRODUCT_BUNDLE_IDENTIFIER = "com.rd.ios-example"; 606 | PRODUCT_NAME = "$(TARGET_NAME)"; 607 | SWIFT_VERSION = 5.0; 608 | TARGETED_DEVICE_FAMILY = "1,2"; 609 | }; 610 | name = Release; 611 | }; 612 | /* End XCBuildConfiguration section */ 613 | 614 | /* Begin XCConfigurationList section */ 615 | 3E3E0F9A21623CD90055258B /* Build configuration list for PBXProject "MetricPrefixNumberFormatter" */ = { 616 | isa = XCConfigurationList; 617 | buildConfigurations = ( 618 | 3E3E0FB221623CD90055258B /* Debug */, 619 | 3E3E0FB321623CD90055258B /* Release */, 620 | ); 621 | defaultConfigurationIsVisible = 0; 622 | defaultConfigurationName = Release; 623 | }; 624 | 3E3E0FB421623CD90055258B /* Build configuration list for PBXNativeTarget "MetricPrefixNumberFormatter" */ = { 625 | isa = XCConfigurationList; 626 | buildConfigurations = ( 627 | 3E3E0FB521623CD90055258B /* Debug */, 628 | 3E3E0FB621623CD90055258B /* Release */, 629 | ); 630 | defaultConfigurationIsVisible = 0; 631 | defaultConfigurationName = Release; 632 | }; 633 | 3E3E0FB721623CD90055258B /* Build configuration list for PBXNativeTarget "Tests" */ = { 634 | isa = XCConfigurationList; 635 | buildConfigurations = ( 636 | 3E3E0FB821623CD90055258B /* Debug */, 637 | 3E3E0FB921623CD90055258B /* Release */, 638 | ); 639 | defaultConfigurationIsVisible = 0; 640 | defaultConfigurationName = Release; 641 | }; 642 | 9A5A7017217DF23100DA5152 /* Build configuration list for PBXNativeTarget "iOS Example" */ = { 643 | isa = XCConfigurationList; 644 | buildConfigurations = ( 645 | 9A5A7015217DF23100DA5152 /* Debug */, 646 | 9A5A7016217DF23100DA5152 /* Release */, 647 | ); 648 | defaultConfigurationIsVisible = 0; 649 | defaultConfigurationName = Release; 650 | }; 651 | /* End XCConfigurationList section */ 652 | }; 653 | rootObject = 3E3E0F9721623CD90055258B /* Project object */; 654 | } 655 | -------------------------------------------------------------------------------- /MetricPrefixNumberFormatter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MetricPrefixNumberFormatter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MetricPrefixNumberFormatter.xcodeproj/xcshareddata/xcschemes/MetricPrefixNumberFormatter.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /MetricPrefixNumberFormatter.xcodeproj/xcshareddata/xcschemes/iOS Example.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 | -------------------------------------------------------------------------------- /Plist/Framework.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /Plist/Tests.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 |

8 | 9 | MetricPrefixNumberFormatter is an `NSNumberFormatter` subclass designed to format large and small numbers using the [metric prefixes](https://en.wikipedia.org/wiki/Metric_prefix). 10 | This is a must have library, if your app displays potentially big numbers like a number of views, likes, etc, or deals with calculations that may potentially involve very small numbers. 11 | 12 | ``` 13 | 1200 -> 1.2 k 14 | 12300000 -> 12.3 M 15 | 0.0017 -> 1.7 m 16 | ``` 17 | 18 | Main features 19 | * Supports all metric prefixes: from yotta (10^24) to yocto (10^-24). 20 | * Localizable using the `localizationDictionary` property. 21 | * Configurable units and delimiters. 22 | 23 | # Examples 24 | 25 | ```swift 26 | // 1122300 -> 1.12 M 27 | let nf = MetricPrefixNumberFormatter() 28 | nf.minimumFractionDigits = 2 29 | nf.stringWithMetricPrefix(from: 1122300) 30 | ``` 31 | ```swift 32 | // 0.001 -> 1 mA 33 | let nf = MetricPrefixNumberFormatter() 34 | nf.unit = "A" 35 | nf.stringWithMetricPrefix(from: 0.001) 36 | ``` 37 | ```swift 38 | // 1200 -> 1.2KV 39 | let nf = MetricPrefixNumberFormatter() 40 | nf.unit = "V" 41 | nf.delimiter = "" 42 | nf.stringWithMetricPrefix(from: 1200) 43 | ``` 44 | 45 | Since `MetricPrefixNumberFormatter` is a subclass of `NSNumberFormatter` its output can be configured the same way as with `NSNumberFormatter`. A good overview of `NSNumberFormatter` output setup using the `minimum/maximumSignificantDigits`, `minimum/maximumFractionDigits`, and `usesSignificantDigits` properties is presented in [this guide by @samwize](https://samwize.com/2015/11/04/a-guide-to-nsnumberformatter/). 46 | 47 | You can also check out provided example iOS app that shows you how various numbers are formatted by `MetricPrefixNumberFormatter`. 48 | ``` 49 | $ pod try MetricPrefixNumberFormatter 50 | ``` 51 | 52 | ## Requirements 53 | 54 | * iOS 8+ 55 | * Xcode 10 / Swift 4.2 and higher 56 | 57 | ## Installation using CocoaPods 58 | 59 | ```ruby 60 | pod 'MetricPrefixNumberFormatter', '~> 1.0.0' 61 | ``` 62 | 63 | ## License 64 | 65 | MetricPrefixNumberFormatter is available under the MIT license. See LICENSE file for more information. 66 | -------------------------------------------------------------------------------- /Source/MetricPrefix.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetricPrefix.swift 3 | // MetricPrefixNumberFormatter 4 | // 5 | // Created by Rostyslav Dovhaliuk on 16.03.2019. 6 | // Copyright © 2019 Rostyslav Dovhaliuk. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public enum MetricPrefix: Int, CaseIterable { 29 | case yotta = 24 30 | case zetta = 21 31 | case exa = 18 32 | case peta = 15 33 | case tera = 12 34 | case giga = 9 35 | case mega = 6 36 | case kilo = 3 37 | case zero = 0 38 | case milli = -3 39 | case micro = -6 40 | case nano = -9 41 | case pico = -12 42 | case femto = -15 43 | case atto = -18 44 | case zepto = -21 45 | case yocto = -24 46 | 47 | static var latinPrefixes: [MetricPrefix: String] { 48 | return [ 49 | .yotta: "Y", 50 | .zetta: "Z", 51 | .exa: "E", 52 | .peta: "P", 53 | .tera: "T", 54 | .giga: "G", 55 | .mega: "M", 56 | .kilo: "k", 57 | .zero: "", 58 | .milli: "m", 59 | .micro: "μ", 60 | .nano: "n", 61 | .pico: "p", 62 | .femto: "f", 63 | .atto: "a", 64 | .zepto: "z", 65 | .yocto: "y" 66 | ] 67 | } 68 | } 69 | 70 | extension MetricPrefix: Comparable { } 71 | 72 | public func <(lhs:MetricPrefix, rhs:MetricPrefix) -> Bool { 73 | return lhs.rawValue < rhs.rawValue 74 | } 75 | -------------------------------------------------------------------------------- /Source/MetricPrefixNumberFormatter+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetricPrefixNumberFormatter+Extension.swift 3 | // MetricPrefixNumberFormatter 4 | // 5 | // Created by Rostyslav Dovhaliuk on 15.03.2019. 6 | // Copyright © 2019 Rostyslav Dovhaliuk. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public extension MetricPrefixNumberFormatter { 29 | func stringWithMetricPrefix(from number: Double) -> String? { 30 | return stringWithMetricPrefix(from: NSNumber(value: number)) 31 | } 32 | 33 | func stringWithMetricPrefix(from number: Float) -> String? { 34 | return stringWithMetricPrefix(from: NSNumber(value: number)) 35 | } 36 | 37 | func stringWithMetricPrefix(from number: Int) -> String? { 38 | return stringWithMetricPrefix(from: NSNumber(value: number)) 39 | } 40 | 41 | func stringWithMetricPrefix(from number: Int64) -> String? { 42 | return stringWithMetricPrefix(from: NSNumber(value: number)) 43 | } 44 | 45 | func stringWithMetricPrefix(from number: Int32) -> String? { 46 | return stringWithMetricPrefix(from: NSNumber(value: number)) 47 | } 48 | 49 | func stringWithMetricPrefix(from number: Int16) -> String? { 50 | return stringWithMetricPrefix(from: NSNumber(value: number)) 51 | } 52 | 53 | func stringWithMetricPrefix(from number: Int8) -> String? { 54 | return stringWithMetricPrefix(from: NSNumber(value: number)) 55 | } 56 | 57 | func stringWithMetricPrefix(from number: UInt) -> String? { 58 | return stringWithMetricPrefix(from: NSNumber(value: number)) 59 | } 60 | 61 | func stringWithMetricPrefix(from number: UInt64) -> String? { 62 | return stringWithMetricPrefix(from: NSNumber(value: number)) 63 | } 64 | 65 | func stringWithMetricPrefix(from number: UInt32) -> String? { 66 | return stringWithMetricPrefix(from: NSNumber(value: number)) 67 | } 68 | 69 | func stringWithMetricPrefix(from number: UInt16) -> String? { 70 | return stringWithMetricPrefix(from: NSNumber(value: number)) 71 | } 72 | 73 | func stringWithMetricPrefix(from number: UInt8) -> String? { 74 | return stringWithMetricPrefix(from: NSNumber(value: number)) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Source/MetricPrefixNumberFormatter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetricPrefixNumberFormatter.swift 3 | // MetricPrefixNumberFormatter 4 | // 5 | // Created by Rostyslav Dovhaliuk on 16.03.2019. 6 | // Copyright © 2019 Rostyslav Dovhaliuk. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | open class MetricPrefixNumberFormatter: NumberFormatter { 29 | public var unit: String? 30 | public var delimiter: String = " " 31 | public var localizationDictionary: [MetricPrefix: String] = MetricPrefix.latinPrefixes 32 | 33 | public func stringWithMetricPrefix(from number: NSNumber) -> String? { 34 | let numberAsDouble = number.doubleValue 35 | guard !numberAsDouble.isNaN else { return nil } 36 | let prefix: MetricPrefix 37 | let scaledNumber: NSNumber 38 | 39 | if number == 0 { 40 | prefix = .zero 41 | scaledNumber = number 42 | } else { 43 | let orderOfMagnitude = Int(log10(fabs(numberAsDouble))) 44 | let smallerOrEqualPrefixes = MetricPrefix.allCases.filter({ $0.rawValue <= orderOfMagnitude }) 45 | prefix = smallerOrEqualPrefixes.max() ?? MetricPrefix.yocto 46 | scaledNumber = NSNumber(value: numberAsDouble / pow(10.0, Double(prefix.rawValue))) 47 | } 48 | 49 | guard let formattedNumber = string(from: scaledNumber) else { return nil } 50 | if prefix == .zero && (unit == nil || unit == "") { 51 | return formattedNumber 52 | } 53 | return "\(formattedNumber)\(delimiter)\(localizationDictionary[prefix] ?? "")\(unit ?? "")" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tests.swift 3 | // Tests 4 | // 5 | // Created by Rostyslav Dovhaliuk on 16.03.2019. 6 | // Copyright © 2019 Rostyslav Dovhaliuk. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import XCTest 27 | @testable import MetricPrefixNumberFormatter 28 | 29 | class Tests: XCTestCase { 30 | var formatter: MetricPrefixNumberFormatter! 31 | 32 | override func setUp() { 33 | formatter = MetricPrefixNumberFormatter() 34 | formatter.usesSignificantDigits = true 35 | } 36 | 37 | func testFormatter() { 38 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 14000000) , "14 M") 39 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 0.000000000036) , "36 p") 40 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 0.73) , "0.73") 41 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 170000000) , "170 M") 42 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 1e-17) , "10 a") 43 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 0.0009) , "0.9 m") 44 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 2.4e-05) , "24 μ") 45 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 88000000000000) , "88 T") 46 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 760000) , "760 k") 47 | } 48 | 49 | func testDelimiter() { 50 | formatter.delimiter = "" 51 | 52 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 710000) , "710k") 53 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 0.00086) , "0.86m") 54 | } 55 | 56 | func testUnit() { 57 | formatter.unit = "V" 58 | 59 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 2) , "2 V") 60 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 0.00002) , "20 μV") 61 | } 62 | 63 | func testLocalization() { 64 | var dictionary = formatter.localizationDictionary 65 | dictionary[.kilo] = "к" 66 | dictionary[.nano] = "н" 67 | formatter.localizationDictionary = dictionary 68 | 69 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 5400) , "5.4 к") 70 | XCTAssertEqual(formatter.stringWithMetricPrefix(from: 1e-9) , "1 н") 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /iOS Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // iOS Example 4 | // 5 | // Created by Rostyslav Dovhaliuk on 16.03.2019. 6 | // Copyright © 2019 Rostyslav Dovhaliuk. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import UIKit 27 | 28 | @UIApplicationMain 29 | class AppDelegate: UIResponder, UIApplicationDelegate { 30 | var window: UIWindow? 31 | 32 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 33 | return true 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /iOS Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /iOS Example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /iOS Example/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 | -------------------------------------------------------------------------------- /iOS Example/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 | 30 | 36 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /iOS Example/ExampleViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleViewController.swift 3 | // iOS Example 4 | // 5 | // Created by Rostyslav Dovhaliuk on 16.03.2019. 6 | // Copyright © 2019 Rostyslav Dovhaliuk. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import UIKit 27 | import MetricPrefixNumberFormatter 28 | 29 | class ExampleViewController: UIViewController { 30 | @IBOutlet weak var rawNumberLabel: UILabel! 31 | @IBOutlet weak var formattedNumberLabel: UILabel! 32 | 33 | var numberFormatter: NumberFormatter = { 34 | let nf = NumberFormatter() 35 | nf.usesSignificantDigits = true 36 | return nf 37 | }() 38 | var metricPrefixFormatter: MetricPrefixNumberFormatter = { 39 | let nf = MetricPrefixNumberFormatter() 40 | nf.usesSignificantDigits = true 41 | return nf 42 | }() 43 | 44 | @IBAction func generateNumber() { 45 | let number = Double(Int.random(in: 1...100)) * pow(10, Double(Int.random(in: -20...20))) 46 | rawNumberLabel.text = numberFormatter.string(from: NSNumber(value: number)) 47 | formattedNumberLabel.text = metricPrefixFormatter.stringWithMetricPrefix(from: number) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /iOS Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | NSMainStoryboardFile 24 | Main 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RenGate/MetricPrefixNumberFormatter/742feb6e67616c0e51bf55c2096e4e4677981563/logo.png --------------------------------------------------------------------------------