Понимание MeasurementFormatter
Класс MeasurementFormatter
предоставляет отформатированные и локализованные представления единиц измерения и измерений. Обращаясь к глобальной аудитории, вы должны представить эти данные в местных единицах. Предположим, ваше приложение показывает конечному пользователю расстояние между двумя точками. Предположим, что расстояние в имперских единицах: футы, ярды и мили. Обращаясь к глобальной аудитории, вы должны представить эти данные в местных единицах. Учтите следующее:
The distance between New York and Paris is 3,626.81 miles
На французском языке вы хотели бы не только перевести текст строки, но также и содержащиеся в ней единицы измерения:
La distance entre New York et Paris est de 5 836,78 km
Вместо того чтобы пытаться написать свои собственные служебные классы для выполнения этих преобразований, вы должны использовать возможности Apple’s Foundation.
Вверх и работает
При работе с измерениями расстояний MeasurementFormatter
отлично работает с нулевой конфигурацией. К тому времени, когда пользователь установит ваше приложение, его устройство будет иметь локаль по умолчанию. Работая с приведенным выше измерением расстояния, мы можем преобразовать в локализованный стандарт пользователя:
// distance in user 's default locale // this would print with different formats in various locales: // 3626.81 miles for en_US // 5.836 , 77 km for en_IT // 5 836 , 77 km for en_FR // 5 , 836.77 km for en_JP // To find out your locale: NSLocale.current import Foundation let distanceInMiles = Measurement(value: 3626.81 , unit: UnitLength.miles) MeasurementFormatter(). string (from: distanceInMiles)
Учитывая простоту, становится ясно, что использование MeasurementFormatter
— это путь. Как разработчик, вы должны привыкнуть всегда использовать средства форматирования Foundation для представления данных. Это приведет к будущему коду и меньше рефакторингу.
Понимание языков
Языки в программировании описывают лингвистические, культурные и технологические соглашения и стандарты. Большинство единиц измерения подпадают под одну из трех систем: британская имперская, обычная для США или метрическая (система СИ). Примеры информации, инкапсулированной в локаль, могут включать:
- Символы, используемые в цифрах и валюте, например:
- 1 200,99 и 1 200,99 долларов США
- 1 200,99 и € 1,234,567,89 в FR
- Форматирование дат, например:
- Порядок дат: ММ / ДД / ГГГГ против ДД / ММ / ГГГГ
- Представление даты: 23 ноября 2016 г. или 23.11.2016 г.
- Наименование международных праздников
- Единицы измерения, например:
- Империал против Метрических измерений
- Написание таких (метров, метров и т. Д.)
- Сокращения как «кал» против «C» для калорий
Хотя мы можем привыкнуть к нашему собственному набору мер и символов, многие регионы мира привыкли к своим собственным. Правописание, сокращения и символы различаются в зависимости от страны и языка. Это делает для очень сложного набора правил и преобразований. Вот лишь краткий пример некоторых изменений в единицах, с которыми обычно работает Foundation:
- Наименование и орфография единиц
- например: метры, метро, метры, метры и т. д.
- Размер единиц
- Например: галлон США (0,26 л), галлон Imperial (0,22 л)
- Сокращения единиц
- например: кал, ккал, кал или с
- Натуральные размеры
- Например: футы против миль, метры против километров
Вы также можете установить локаль и сохранить предпочтения пользователя. Вот пример того, как вы можете использовать это в реальном мире, основываясь на коде сверху:
import Foundation // Create a local variable instance of MeasurementFormatter which we can reuse and configure let formatter = MeasurementFormatter() let distanceInMiles = Measurement( value : 3626.81 , unit: UnitLength.miles) // You should collect this for UIPickerView or similar input // and replace "en_FR" with the result of the picker // This will save the string to the "locale" key in device storage UserDefaults.standard. set ( "en_FR" , forKey: "locale" ) // From this point on , we want to refer to the saved preference // If the User default is nil, we failover to "en_FR" let localeIdentifier = UserDefaults.standard.object(forKey: "locale" ) ?? "en_FR" // Last we initiate our Locale class with this identifier let locale = Locale(identifier: localeIdentifier as ! String) // Optionally set the `locale` property of our instance. // If we do not set this, it will default to the user 's device locale formatter.locale = locale formatter.string(from: distanceInMiles) // prints "5 836,77 km"
Ваше приложение должно позволять пользователю глобально устанавливать свои предпочтения локализации. Это особенно важно при работе с данными. Разработчики часто полагаются на настройки устройства пользователя, но это может вызвать проблемы. Например: представьте себе экспата США, живущего во Франции. Их устройство может быть установлено на французском языке, поскольку они могут знать язык. Это все еще может быть проблематичным, поскольку они могут не иметь представления о метрических измерениях над имперскими. Желательно иметь настройки локализации для каждого приложения.
Стиль блока
Свойство unitStyle
MeasurementFormatter
является самым базовым из них. Это свойство ожидает регистр из перечисления UnitStyle
которое обеспечивает следующее:
-
.short
- Форматирует единицу измерения как кратчайшую сокращенную версию или символ.
- Например: 10 футов будут отформатированы как 10 ‘
-
.medium
- Это значение по умолчанию, если ничего не указано.
- Форматирует единицу измерения как сокращение
- Например: 10 футов будут отформатированы как 10 футов
-
.long
- Форматирует единицу измерения в полностью письменной форме.
- Например: 10 футов будут отформатированы как 10 футов
import Foundation // You can optionally set the `unitStyle` property // Expects enum case from `MeasurementFormatter.UnitStyle` // Defaults to `.medium` // You can simply pass the case value : `.long` // or you can write it out as shown below let formatter = MeasurementFormatter() let distanceInMiles = Measurement( value : 3626.81 , unit: UnitLength.miles) formatter.unitStyle = MeasurementFormatter.UnitStyle.long formatter.string( from : distanceInMiles) // 3 , 626.81 miles
Параметры блока
Свойство unitOptions
похоже на свойство unitStyle
. Также ожидается случай перечисления и значения:
-
.providedUnit
— отображает предоставленную единицу измерения и не выполняет преобразования. -
.naturalScale
— делает для нас немного магии. Apple наметила типичные единицы измерения для более удобочитаемых значений. Например, человек не может описать 10 футов как 0,00189394 миль. Таким образом, свойство naturalScale обычно подходит для преобразования этого измерения. -
.temperatureWithoutUnit
— довольно.temperatureWithoutUnit
. Иногда вы можете захотеть использовать или отображать температуру без единицы измерения. Это установлено отдельно от других, поскольку преобразования температуры, как правило, остаются неизменными или являются обычными.
let formatter = MeasurementFormatter() // Working with meters and evaluating the results let distanceInMeters = Measurement( value : 2 , unit: UnitLength.meters) formatter. string ( from : distanceInMeters) // prints "0,002 kilometres" // However, we can see the class is aware of the original unit of measure formatter. string ( from : UnitLength.meters) // prints "metres" // Optionally set the `unitOptions` property // This can be: .providedUnit, .naturalScale, or .temperatureWithoutUnit // Options provided by MeasurementFormatter.UnitOptions // This defaults to a privately defined format if unset formatter.unitOptions = .naturalScale formatter. string ( from : distanceInMeters) // prints "2 metres"
Форматирование чисел
При работе с мерой нередко меняют форматирование чисел. Свойство numberFormatter существует именно по этой причине. Класс, аналогичный классу MeasurementFormatter
— это класс NumberFormatter
. Они работают бок о бок, чтобы дать вам более детальный контроль над выводом строки. Мы можем создать экземпляр и настроить NumberFormatter
а затем установить наш MeasuremFormatter.numberFormatter
на наш экземпляр NumberFormatter
:
import Foundation let formatter = MeasurementFormatter() formatter .unitOptions = .naturalScale formatter .unitStyle = .long formatter .locale = Locale(identifier: "en_FR" ) let distanceInMeters = Measurement(value: 2 , unit: UnitLength .meters ) // 2.0 m // Optionally set the `numberFormatter` property // Expects an instance of `NumberFormatter` // You could set the `NumberFormatter .numberStyle ` property to: // .none // .decimal // .currency // .percent // .scientific // .spellOut // Defaults to .decimal if unset let numberFormatter = NumberFormatter() numberFormatter .numberStyle = .spellOut formatter .numberFormatter = numberFormatter formatter .string (from: distanceInMeters) // two meters
Это дает нам детальный контроль для широкого спектра приложений.
Нюансы и готчы
Преобразование измерений является простой арифметикой, а представление — нет. Основные библиотеки не всегда будут следовать соглашениям, которые вы можете ожидать. Основная документация и исходный код Swift написаны разработчиками во многих странах. Таким образом, многие комментарии и результаты, похоже, имеют небольшие несоответствия.
Несоответствие в именах единиц
Вы можете найти «метры», написанные как «метры», несмотря на то, что локаль остается прежней. Я считаю, что это просто упущение, и некоторые участники сообщества открыли радары, чтобы исправить эти проблемы в будущих версиях Swift.
Натуральный масштаб не идеален
Вы можете обнаружить, что свойство naturalScale
конвертируется за пределы naturalScale
диапазонов. В своем собственном развитии я обнаружил, что дюймы переходят в футы наоборот, порой я не ожидал. Однако, несмотря на эти нюансы, я бы доверял Apple 99% времени, а не занимался крайними случаями. Эти библиотеки продолжают развиваться и улучшаться с каждым выпуском.
Завершение
Класс MeasurementFormatter
является одним из самых простых служебных классов в среде Foundation. Несмотря на то, что это более базовый класс, он мощный и очень простой в освоении.