@@ -14,6 +14,7 @@ public struct CurrencyTextField: UIViewRepresentable {
1414 private var isResponder : Binding < Bool > ?
1515 private var tag : Int
1616 private var alwaysShowFractions : Bool
17+ private var numberOfDecimalPlaces : Int
1718
1819 private var placeholder : String
1920
@@ -44,7 +45,7 @@ public struct CurrencyTextField: UIViewRepresentable {
4445 isResponder: Binding < Bool > ? = nil ,
4546 tag: Int = 0 ,
4647 alwaysShowFractions: Bool = false ,
47-
48+ numberOfDecimalPlaces : Int = 2 ,
4849 font: UIFont ? = nil ,
4950 foregroundColor: UIColor ? = nil ,
5051 accentColor: UIColor ? = nil ,
@@ -65,6 +66,7 @@ public struct CurrencyTextField: UIViewRepresentable {
6566 self . isResponder = isResponder
6667 self . tag = tag
6768 self . alwaysShowFractions = alwaysShowFractions
69+ self . numberOfDecimalPlaces = numberOfDecimalPlaces
6870
6971 self . font = font
7072 self . foregroundColor = foregroundColor
@@ -92,7 +94,7 @@ public struct CurrencyTextField: UIViewRepresentable {
9294
9395 // initial value
9496 if let v = self . value {
95- textField. text = v. currencyFormat ( decimalPlaces: self . alwaysShowFractions ? 2 : nil )
97+ textField. text = v. currencyFormat ( decimalPlaces: self . numberOfDecimalPlaces , forceShowDecimalPlaces : self . alwaysShowFractions )
9698 }
9799
98100 // tag
@@ -170,7 +172,7 @@ public struct CurrencyTextField: UIViewRepresentable {
170172 }
171173
172174 public func makeCoordinator( ) -> CurrencyTextField . Coordinator {
173- Coordinator ( value: $value, isResponder: self . isResponder, alwaysShowFractions: self . alwaysShowFractions, onReturn: self . onReturn) { flag in
175+ Coordinator ( value: $value, isResponder: self . isResponder, alwaysShowFractions: self . alwaysShowFractions, numberOfDecimalPlaces : self . numberOfDecimalPlaces , onReturn: self . onReturn) { flag in
174176 self . onEditingChanged ( flag)
175177 }
176178 }
@@ -182,7 +184,7 @@ public struct CurrencyTextField: UIViewRepresentable {
182184 if self . value == nil {
183185 textField. text = nil
184186 } else {
185- textField. text = self . value!. currencyFormat ( decimalPlaces: self . alwaysShowFractions ? 2 : nil )
187+ textField. text = self . value!. currencyFormat ( decimalPlaces: self . numberOfDecimalPlaces , forceShowDecimalPlaces : self . alwaysShowFractions )
186188 }
187189 }
188190
@@ -207,16 +209,24 @@ public struct CurrencyTextField: UIViewRepresentable {
207209 private var isResponder : Binding < Bool > ?
208210 private var onReturn : ( ) -> ( )
209211 private var alwaysShowFractions : Bool
212+ private var numberOfDecimalPlaces : Int
210213 var internalValue : Double ?
211214 var onEditingChanged : ( Bool ) -> ( )
212215 var didBecomeFirstResponder = false
213216
214- init ( value: Binding < Double ? > , isResponder: Binding < Bool > ? , alwaysShowFractions: Bool = false , onReturn: @escaping ( ) -> Void = { } , onEditingChanged: @escaping ( Bool ) -> Void = { _ in } ) {
217+ init ( value: Binding < Double ? > ,
218+ isResponder: Binding < Bool > ? ,
219+ alwaysShowFractions: Bool ,
220+ numberOfDecimalPlaces: Int ,
221+ onReturn: @escaping ( ) -> Void = { } ,
222+ onEditingChanged: @escaping ( Bool ) -> Void = { _ in }
223+ ) {
215224 print ( " coordinator init " )
216225 _value = value
217226 internalValue = value. wrappedValue
218227 self . isResponder = isResponder
219228 self . alwaysShowFractions = alwaysShowFractions
229+ self . numberOfDecimalPlaces = numberOfDecimalPlaces
220230 self . onReturn = onReturn
221231 self . onEditingChanged = onEditingChanged
222232 }
@@ -226,7 +236,7 @@ public struct CurrencyTextField: UIViewRepresentable {
226236 let originalText = textField. text
227237 let text = textField. text as NSString ?
228238 let newValue = text? . replacingCharacters ( in: range, with: string)
229- let display = newValue? . currencyFormat
239+ let display = newValue? . currencyFormat ( decimalPlaces : self . numberOfDecimalPlaces )
230240
231241 // validate change
232242 if !shouldAllowChange( oldValue: textField. text ?? " " , newValue: newValue ?? " " ) {
@@ -293,7 +303,7 @@ public struct CurrencyTextField: UIViewRepresentable {
293303 }
294304
295305 // limits fractions length
296- if newValue. fractions? . count ?? 0 > 2 {
306+ if newValue. fractions? . count ?? 0 > self . numberOfDecimalPlaces {
297307 return false
298308 }
299309
@@ -307,7 +317,7 @@ public struct CurrencyTextField: UIViewRepresentable {
307317 }
308318
309319 public func textFieldDidEndEditing( _ textField: UITextField ) {
310- textField. text = self . value? . currencyFormat ( decimalPlaces: self . alwaysShowFractions ? 2 : nil )
320+ textField. text = self . value? . currencyFormat ( decimalPlaces: self . numberOfDecimalPlaces , forceShowDecimalPlaces : self . alwaysShowFractions )
311321 DispatchQueue . main. async {
312322 self . isResponder? . wrappedValue = false
313323 }
@@ -370,25 +380,24 @@ fileprivate extension String {
370380 return Double ( decimals) ?? 0
371381 }
372382
373- var currencyFormat : String ? {
383+ // args:
384+ // decimalPlaces - the max number of decimal places
385+ func currencyFormat( decimalPlaces: Int ? = nil ) -> String ? {
374386 // uses self.double
375387 // logic for varying the number of fraction digits
376-
377388 guard let double = double else {
378389 return nil
379390 }
380391
381392 let formatter = Formatter . currency
382- let fractionDigits = fractions ? . count ?? 0
393+
383394 // if has fractions, show fractions
384395 if fractions != nil {
385- if fractionDigits == 0 {
386- formatter. maximumFractionDigits = 0
387- } else if fractionDigits == 1 {
388- formatter. maximumFractionDigits = 1
389- } else {
390- formatter. maximumFractionDigits = 2
391- }
396+ // the number of decimal points in the string
397+ let fractionDigits = fractions? . count ?? 0
398+ // limited to the decimalPlaces specified in the argument
399+ formatter. minimumFractionDigits = min ( fractionDigits, decimalPlaces != nil ? decimalPlaces! : 2 )
400+ formatter. maximumFractionDigits = min ( fractionDigits, decimalPlaces != nil ? decimalPlaces! : 2 )
392401
393402 let formatted = formatter. string ( from: NSNumber ( value: double) )
394403
@@ -397,33 +406,37 @@ fileprivate extension String {
397406 return " \( formatted) . "
398407 }
399408
400- return formatted
401- } else {
402- formatter. maximumFractionDigits = 0
403- let formatted = formatter. string ( from: NSNumber ( value: double) )
404409 return formatted
405410 }
411+
412+ formatter. maximumFractionDigits = 0
413+ let formatted = formatter. string ( from: NSNumber ( value: double) )
414+ return formatted
406415 }
407416}
408417
409418fileprivate extension Double {
410- func currencyFormat( decimalPlaces: Int ? = nil ) -> String ? {
419+ // args:
420+ // decimalPlaces - number of decimal places
421+ // forceShowDecimalPlaces - whether to force show fractions
422+ func currencyFormat( decimalPlaces: Int ? = nil , forceShowDecimalPlaces: Bool = false ) -> String ? {
411423 let formatter = Formatter . currency
412424 var integer = 0.0
413-
414- // if decimal places specified
415- if let decimalPlaces = decimalPlaces {
416- formatter. maximumFractionDigits = 2
425+ let d = decimalPlaces != nil ? decimalPlaces! : 2
426+
427+ if forceShowDecimalPlaces {
428+ formatter. minimumFractionDigits = d
429+ formatter. maximumFractionDigits = d
417430 } else {
418- // format to 2 decimal places if there's fractions
431+ // show fractions if exist
419432 let fraction = modf ( self , & integer)
420433 if fraction > 0 {
421- formatter. maximumFractionDigits = 2
434+ formatter. maximumFractionDigits = d
422435 } else {
423436 formatter. maximumFractionDigits = 0
424437 }
425438 }
426-
439+
427440 return formatter. string ( from: NSNumber ( value: self ) )
428441 }
429442}
0 commit comments