Setting Medium and Long Measurement Symbols in Swift 3

Setting medium and long measurement symbols in Swift 3

Short answer - you can't. The API does not provide any facility that allows you to provide different symbols for the three unit styles.

For custom units, the MeasurementFormatter only has the one symbol used when defining the custom unit.

Keep in mind that the need is for much more than just three different possible symbols for the three different unit styles. You would actually need three different string formats because some units might have a space or other punctuation, some might not. Some might appear before the value while some appear after the value.

And then there is the issue of localizing the unit. The Foundation framework provides all of this information for all supported languages so MeasurementFormatter can show all three unit styles for all supported languages for all predefined units.

Since the API does support custom units but not the ability to provide unit style specific symbols, I would suggest filing an enhancement request with Apple.

Custom measurement unit

Since the conversion is not linear, you will need to create your own UnitConverter subclass:

class UnitConverterInverse: UnitConverter {
var coefficient: Double

init(coefficient: Double) {
self.coefficient = coefficient
}

override func baseUnitValue(fromValue value: Double) -> Double {
return coefficient / value
}

override func value(fromBaseUnitValue baseUnitValue: Double) -> Double {
return coefficient / baseUnitValue
}
}

extension UnitSpeed {
static let minutesPerKilometer = UnitSpeed(symbol: "min/km",
converter: UnitConverterInverse(coefficient: 1000.0 / 60.0))
}

let velocity = Measurement(value: 60, unit: UnitSpeed.milesPerHour)

let velocity2 = velocity.converted(to: .minutesPerKilometer)

print(velocity2)
0.621371192237334 min/km

How do I set the size of a SF Symbol in SwiftUI?

SF Symbols are similar to fonts, thus:

.font(.system(size: 60))

How to format a Double into Currency - Swift 3

You can use this string initializer if you want to force the currency to $:

String(format: "Tip Amount: $%.02f", tipAmount)

If you want it to be fully dependent on the locale settings of the device, you should use a NumberFormatter. This will take into account the number of decimal places for the currency as well as positioning the currency symbol correctly. E.g. the double value 2.4 will return "2,40 €" for the es_ES locale and "¥ 2" for the jp_JP locale.

let formatter = NumberFormatter()
formatter.locale = Locale.current // Change this to another locale if you want to force a specific locale, otherwise this is redundant as the current locale is the default already
formatter.numberStyle = .currency
if let formattedTipAmount = formatter.string(from: tipAmount as NSNumber) {
tipAmountLabel.text = "Tip Amount: \(formattedTipAmount)"
}

Determine user's Temperature Unit setting on iOS 10 (Celsius / Fahrenheit)

There is this article by Alexandre Colucci that I found: http://blog.timac.org/?tag=nslocaletemperatureunit

First, expose the NSLocaleTemperatureUnit NSLocaleKey:

FOUNDATION_EXPORT NSLocaleKey const NSLocaleTemperatureUnit;

Then check the unit with this:

temperatureUnit = [[NSLocale currentLocale] objectForKey:NSLocaleTemperatureUnit]

Or Swift (2.3):

if let temperatureUnit = NSLocale.currentLocale().objectForKey(NSLocaleTemperatureUnit) {
...
}

It will return a string which is either "Celcius" or "Fahrenheit".

But there is an issue: it's not backwards compatible with iOS versions earlier than 10. If you run your app on an iOS 9 or earlier device, you'll get an error "dyld: Symbol not found: _NSLocaleTemperatureUnit" during app startup.

The solution is to use weak linking for the NSLocaleTemperatureUnit variable definition. Like this:

FOUNDATION_EXPORT NSLocaleKey const NSLocaleTemperatureUnit  __attribute__((weak_import));

This will let the app pass the dyld checks. But now you will have to check for the OS version before using NSLocaleTemperatureUnit, or your app will crash with an exception.

if #available(iOS 10,*) {
if let temperatureUnit = NSLocale.currentLocale().objectForKey(NSLocaleTemperatureUnit) {
...
}
}

EDIT:

I tried it in my app, but Apple rejected the app for it when I uploaded it to Testflight. So they definitely don't want us to use the setting for our own formatter classes. I find that pretty annoying.



Related Topics



Leave a reply



Submit