Formatting numbers in Swift.

Tram Ho

  • Number is an important type that we encounter a lot in everyday programming work. We run into number everywhere from sizing and layout for UI to conditional event .
  • Working with number is one of the main jobs that computers are created, but sometimes for people to be able to communicate with the computer, number must be converted to format that humans can read and understand to ensure their integrity. precise as well as tight on request.

1 / Solving the decimal problem:

  • If the request is simple, we can use a string literal to initialize a number from the String form as follows:

  • The method works well and is accessible and gives us complete control over the values ​​of number , but to increase mobility in our intended use we may need other methods and formats when doing so. constantly changing number values.
  • For an example we will implement a Metric type that allows us to associate a Double type with the name , value , and description :

  • To make a Double number easier to read, we can convert it from Double to String by being able to customize the decimal position to ensure the output is always consistent:

  • We have a problem here when if number is integer then the output will still display a decimal point, eg number 42 will output 42.00 .
  • The workaround is that we will filter and remove number after the decimal point if they are 0 as follows:

  • The above code works fine but not very neat and this is not an approach for all use cases, since in different languages ​​there will be different methods of representing number and we It is impossible to just handle individual cases for each language.

2 / Using NumberFormatter:

  • Using NumberFormatter in Foundation to solve the above problem of number after decimals like DateFormatter formatting Date values ​​is a better choice because NumberFormatter has provided us with all the necessary tools for us to do. work with number .
  • With NumberFormatter we can work with each number with decimals or without decimals and display the exact number to each number after the decimal point we want like 42 , 42.1 , 42.22 :

  • Another benefit we get when using NumberFormatter is that it will automatically use the Locale we are using for formatting. For example, in some countries the number 69969.69 will be formatted as 69 969,69 instead of 69,969.69 . The above complicated cases can all be handled easily and automatically.
  • Not in all cases we can use Locale , we need to further customize the decimalSeparator and groupingSeparator as follows:

  • In this case we want our formatting formats to conform to each region in use. We need to create additional static property so we can reuse the Metric value :

3 / Domain-specific numbers:

  • Depending on the type of app we are working with, we will have a chance to deal with domain-specific . In that case we would need to include number ‘s description rather than just its value :
  • We work with the shopping app and we use Double to represent the Price struct to describe product prices:

  • The question is how can we format the Price instance for each user in different country with different Locale :
  • This is a case where NumberFormatter proved extremely useful including full-support for Locale as well as the ability to customize numberStyle and currency as follows

  • The result we get here will be the pricing for each country using different Locale , for example price 3.14 in Sweden using SEK currency will be displayed as follows
    • Sweden : 3,14 kr
    • Spain : 3.14 SEK
    • US : SEK 3.14
    • France : SEK 3,14
  • Besides price we often encounter the case of number values ​​displayed according to measurement parameters. For example, we want to focus on the top speed achieved by a car like topSpeed :

  • In this case, to accurately topSpeed , Double not the optimal choice but instead we can always use Measurement with a phantom type UnitSpeed :

  • While instantiating the Vehicle instance we may have to specify a unit of measure for topSpeed to avoid ambiguity. Because Measurement has a built-in formatter , we can easily handle this problem:

  • We need to keep in mind that when constructing Measurement we will be simultaneously using encoded and decoded so we will need Codeable to Measurement to ensure when our values ​​are not in JSON that we can download from the app server . In this case we’ll need to add the unified units of measure for the decoded process to work properly:

  • We can now use property wrapper to encapsulate the conversion between Double and Measurement with a single type :

  • When ever we collect or benefit them we can now mark the topSpeed property with @KilometersPerHour :

  • We have now secured a safe and efficient use of Measurement from the above implementation for the proper formatting and conversion for the features we need when developing app when encoding and decoding data model .
Share the news now

Source : Viblo