Запись пользовательского преобразователя значения

Платформа Основы обеспечивает несколько встроенных преобразователей значения. Вы создаете свои собственные преобразователи значения путем разделения на подклассы NSValueTransformer.

NSValueTransformer подкласс должен, как минимум, реализовать transformedValueClass, allowsReverseTransformation и transformedValue: методы. Если Ваш пользовательский преобразователь значения поддерживает обратные трансформации, необходимо также реализовать reverseTransformedValue: метод.

Как пример, мы создадим NSValueTransformer подкласс, FahrenheitToCelsiusTransformer, это преобразовывает Температуры по Фаренгейту в Шкалу Цельсия. Этот преобразователь значения также обратим, в состоянии преобразовать температуры по шкале Цельсия назад в Шкалу Фаренгейта.

Объявление возвращенного класса значения

Подкласс преобразователя значения должен реализовать transformedValueClass метод класса. Этот метод возвращает класс объекта что transformedValue: возвраты метода.

FahrenheitToCelsiusTransformer класс возвращает NSNumber, как показано в Перечислении 1.

Перечисление 1  Фаренгейт к Цельсия transformedValueClass реализация

+ (Class)transformedValueClass
{
    return [NSNumber class];
}

Разрешение обратных трансформаций

NSValueTransformer подклассы должны также реализовать allowsReverseTransformation метод класса. Реализация подкласса должна возвратиться YES если преобразователь значения обратим.

Фаренгейт к преобразователю значения Цельсия обратим, таким образом, allowsReverseTransformation возвраты реализации YES, как показано в Перечислении 2.

Перечисление 2  Фаренгейт к Цельсия allowsReverseTransformation реализация

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

Преобразование значения

transformedValue: метод реализует трансформацию фактического значения. Это передало объект преобразовать и возвращает результат трансформации. Результатом должен быть экземпляр класса, возвращенного transformedValueClass.

Для максимальной гибкости, реализации transformedValue: должен быть подготовлен обработать множество различных классов как значение. Фаренгейт к преобразователю Цельсия может обработать значения обоих NSString и NSNumber классы, при помощи floatValue метод для преобразования значения в скаляр.

Результат, возвращающийся, когда значение nil зависит от того, что преобразователь значения пытается сделать. Фаренгейт к реализации Цельсия transformedValue:, показанный в Перечислении 3, возвратах nil в этом случае.

Перечисление 3  Фаренгейт к Цельсия transformedValue реализация

- (id)transformedValue:(id)value
{
    float fahrenheitInputValue;
    float celsiusOutputValue;
 
    if (value == nil) return nil;
 
    // Attempt to get a reasonable value from the
    // value object.
    if ([value respondsToSelector: @selector(floatValue)]) {
    // handles NSString and NSNumber
        fahrenheitInputValue = [value floatValue];
    } else {
        [NSException raise: NSInternalInconsistencyException
                    format: @"Value (%@) does not respond to -floatValue.",
        [value class]];
    }
 
    // calculate Celsius value
    celsiusOutputValue = (5.0/9.0)*(fahrenheitInputValue - 32.0);
 
    return [NSNumber numberWithFloat: celsiusOutputValue];
}

Реверс, преобразовывающий значение

Если NSValueTransformer разделите трансформации реверса поддержек на подклассы, это должно реализовать reverseTransformedValue: метод.

Необходимо соблюдать осторожность при реализации обратимых преобразователей значения, чтобы гарантировать, что реверсирование не приводит к потере точности. Во многих случаях, передавая результат transformedValue: к reverseTransformedValue: должен возвратить объект с тем же значением как исходный объект.

Фаренгейт к реализации Цельсия reverseTransformedValue: показан в Перечислении 4. Единственная значительная разница между этим и transformedValue: реализация является температурной формулой преобразования.

Перечисление 4  Фаренгейт к Цельсия reverseTransformedValue реализация

- (id)reverseTransformedValue:(id)value
{
    float celsiusInputValue;
    float fahrenheitOutputValue;
 
    if (value == nil) return nil;
 
    // Attempt to get a reasonable value from the
    // value object.
    if ([value respondsToSelector: @selector(floatValue)]) {
    // handles NSString and NSNumber
        celsiusInputValue = [value floatValue];
    } else {
        [NSException raise: NSInternalInconsistencyException
                    format: @"Value (%@) does not respond to -floatValue.",
        [value class]];
    }
 
    // calculate Fahrenheit value
    fahrenheitOutputValue = ((9.0/5.0) * celsiusInputValue) + 32.0;
 
    return [NSNumber numberWithDouble: fahrenheitOutputValue];
}