From 3111532e9382d752fbf7d73b9eea034e7e6bdcfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Lef=C3=A8vre=20Marino?= Date: Tue, 4 Sep 2018 22:43:32 -0300 Subject: [PATCH 1/4] add expected unit test behavior --- FormatTests/NumberFormatterTests.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/FormatTests/NumberFormatterTests.swift b/FormatTests/NumberFormatterTests.swift index e0aa0b0..278a3d3 100644 --- a/FormatTests/NumberFormatterTests.swift +++ b/FormatTests/NumberFormatterTests.swift @@ -54,6 +54,17 @@ class NumberFormatterTests: XCTestCase { XCTAssertEqual(formattedNumber, "3,14") } + /** + Separator + */ + + func testCommaSeparator() { + let number = 1000000 + let formattedNumber = number.format(Separator.comma, spacing: 3) + XCTAssertEqual(formattedNumber, "1.000.000") + } + + /** Currency */ From 2349ddfa8e2e83aa9ee81d7231a95bd14a4cd884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Lef=C3=A8vre=20Marino?= Date: Tue, 4 Sep 2018 22:44:38 -0300 Subject: [PATCH 2/4] add NumberFormatter separator type --- Format.xcodeproj/project.pbxproj | 4 +++ Format/Separator.swift | 52 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 Format/Separator.swift diff --git a/Format.xcodeproj/project.pbxproj b/Format.xcodeproj/project.pbxproj index 23cd5a5..ccad299 100644 --- a/Format.xcodeproj/project.pbxproj +++ b/Format.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 34C74C121C0533E400B4342B /* ColorFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C74C111C0533E400B4342B /* ColorFormatterTests.swift */; }; 34C74C141C05392D00B4342B /* NumberFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C74C131C05392D00B4342B /* NumberFormatterTests.swift */; }; 34FA3E471C5FB80A000442D3 /* Mass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34FA3E461C5FB80A000442D3 /* Mass.swift */; }; + D5FC8FF6213F68A200610D99 /* Separator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FC8FF5213F68A200610D99 /* Separator.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -59,6 +60,7 @@ 34C74C111C0533E400B4342B /* ColorFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorFormatterTests.swift; sourceTree = ""; }; 34C74C131C05392D00B4342B /* NumberFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberFormatterTests.swift; sourceTree = ""; }; 34FA3E461C5FB80A000442D3 /* Mass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mass.swift; sourceTree = ""; }; + D5FC8FF5213F68A200610D99 /* Separator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Separator.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -143,6 +145,7 @@ 345E9B731BF8826100A88BD7 /* Currency.swift */, 345E9B751BF88CF900A88BD7 /* General.swift */, 34FA3E461C5FB80A000442D3 /* Mass.swift */, + D5FC8FF5213F68A200610D99 /* Separator.swift */, ); name = Numbers; sourceTree = ""; @@ -279,6 +282,7 @@ files = ( 345E9B7D1BF892F900A88BD7 /* AddressExtensions.swift in Sources */, 345E9B741BF8826100A88BD7 /* Currency.swift in Sources */, + D5FC8FF6213F68A200610D99 /* Separator.swift in Sources */, 340E40E71BFB3C200054B560 /* ColorFormatter.swift in Sources */, 345E9B781BF88F4500A88BD7 /* Constants.swift in Sources */, 341F272E1BFA3D7800D83C8B /* AddressFormatter.swift in Sources */, diff --git a/Format/Separator.swift b/Format/Separator.swift new file mode 100644 index 0000000..61de67c --- /dev/null +++ b/Format/Separator.swift @@ -0,0 +1,52 @@ +// +// Separator.swift +// Format +// +// Created by Felipe Lefèvre Marino on 9/4/18. +// Copyright © 2018 Roy Marmelstein. All rights reserved. +// + +import Foundation + +/** + * Separator formatting enum + */ +public enum Separator: NumberFormatter, NumberFormatterCustomLocaleAvailable { + + /// Comma separator with given spacing + case comma(spacing: Int) + /// Dot separator with given spacing + case dot(spacing: Int) + /// white space separator with given spacing + case space(spacing: Int) + /// semicolon separator with given spacing + case semicolon(spacing: Int) + /// custom separator with given spacing + case custom(separator: String, spacing: Int) + + /// Modifier + public var modifier: String { + switch self { + case .comma: + return "," + case .dot: + return "." + case .space: + return " " + case .semicolon: + return ";" + case .custom(let separator, _): + return separator + } + } + + /// Type enum + public var type: NumberFormatterType { + return .separator + } + + /// NSNumberFormatter style + public var style: Foundation.NumberFormatter.Style? { + return .none + } +} From a0f0b67ff4343a42dc84fd58018c29b1532ed19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Lef=C3=A8vre=20Marino?= Date: Tue, 4 Sep 2018 23:07:51 -0300 Subject: [PATCH 3/4] format number with separator and spacing --- Format/NumberFormatter.swift | 15 +++++++++++++++ FormatTests/NumberFormatterTests.swift | 20 +++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Format/NumberFormatter.swift b/Format/NumberFormatter.swift index 87bd8b7..ee02cca 100644 --- a/Format/NumberFormatter.swift +++ b/Format/NumberFormatter.swift @@ -20,6 +20,7 @@ public enum NumberFormatterType { case currency case decimal case general + case separator case mass } @@ -94,6 +95,20 @@ open class NumberFormat { formattedString = distanceFormatter.string(fromDistance: distance) } } + if let separatorFormatter = formatter as? Separator { + switch separatorFormatter { + case .comma(let spacing), + .dot(let spacing), + .semicolon(let spacing), + .space(let spacing), + .custom(_, let spacing): + + nsFormatter.groupingSize = spacing + } + nsFormatter.usesGroupingSeparator = true + nsFormatter.groupingSeparator = separatorFormatter.modifier + formattedString = nsFormatter.string(from: number) + } guard let finalString = formattedString else { return "" } diff --git a/FormatTests/NumberFormatterTests.swift b/FormatTests/NumberFormatterTests.swift index 278a3d3..8c95a91 100644 --- a/FormatTests/NumberFormatterTests.swift +++ b/FormatTests/NumberFormatterTests.swift @@ -60,10 +60,28 @@ class NumberFormatterTests: XCTestCase { func testCommaSeparator() { let number = 1000000 - let formattedNumber = number.format(Separator.comma, spacing: 3) + let formattedNumber = number.format(Separator.comma(spacing: 3)) + XCTAssertEqual(formattedNumber, "1,000,000") + } + + func testDotSeparator() { + let number = 1000000 + let formattedNumber = number.format(Separator.dot(spacing: 3)) XCTAssertEqual(formattedNumber, "1.000.000") } + func testCustomSeparator() { + let number = 1000000 + let formattedNumber = number.format(Separator.custom(separator: "|", spacing: 3)) + XCTAssertEqual(formattedNumber, "1|000|000") + } + + func testCustomSpacing() { + let number = 1000000 + let formattedNumber = number.format(Separator.comma(spacing: 2)) + XCTAssertEqual(formattedNumber, "1,00,00,00") + } + /** Currency From 3baa5a26602d6030a71e7f29bf0bfd2312005ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Lef=C3=A8vre=20Marino?= Date: Tue, 4 Sep 2018 23:22:44 -0300 Subject: [PATCH 4/4] remove unecessary singleton avoiding NumberFormat as singleton we improve memory management and also skip problems when reusing variables as nsFormatter --- Format/NumberExtensions.swift | 4 ++-- Format/NumberFormatter.swift | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Format/NumberExtensions.swift b/Format/NumberExtensions.swift index c6a3b0f..eeea760 100644 --- a/Format/NumberExtensions.swift +++ b/Format/NumberExtensions.swift @@ -50,12 +50,12 @@ public protocol NumberFormatProvider { extension NumberFormatProvider { public func format(_ formatter: NumberFormatter) -> String { - let formattedNumber = NumberFormat.sharedInstance.format(formatNumber(), formatter: formatter) + let formattedNumber = NumberFormat().format(formatNumber(), formatter: formatter) return formattedNumber } public func format(_ formatter: NumberFormatterCustomLocaleAvailable, locale: Locale) -> String { - let formattedNumber = NumberFormat.sharedInstance.format(formatNumber(), formatter: formatter, locale: locale) + let formattedNumber = NumberFormat().format(formatNumber(), formatter: formatter, locale: locale) return formattedNumber } } diff --git a/Format/NumberFormatter.swift b/Format/NumberFormatter.swift index ee02cca..b409001 100644 --- a/Format/NumberFormatter.swift +++ b/Format/NumberFormatter.swift @@ -38,8 +38,6 @@ public protocol NumberFormatterCustomLocaleAvailable: NumberFormatter {} /// Number format class open class NumberFormat { - static let sharedInstance = NumberFormat() - var nsFormatter = Foundation.NumberFormatter() let distanceFormatter = MKDistanceFormatter()