NSValueTransformer для NSPopupButton в целочисленном атрибуте CoreData

У меня есть приложение CoreData/SQLite с NSPopupButton, представляющим возможные значения для некоторого атрибута объекта (целое число). Он автоматически показывает значение атрибута в базе данных. Пользователь должен иметь возможность присвоить другое значение, поэтому мой код генерирует массив всех возможных значений при запуске. В моем XIB у меня есть NSObject для кнопки и NSArrayController для возможных значений. Привязки сделаны, все работает.

Конечно, использование только чисел не понятно пользователю, поэтому я создал преобразователь значений, чтобы заменить числа словами на всплывающей кнопке: 1=>Красный, 2=>Зеленый, 3=>Синий.

Проблема в том, что только выбранный элемент Popup заменяется словом. И когда я выбираю другое значение с помощью кнопки «Всплывающее окно», чтобы изменить атрибут объекта, оно не сохраняет его. Я вижу это, выбирая другой объект в TableView, затем возвращаясь к измененному, и всплывающее окно будет указывать NoValue.

Я не понимаю, почему. Спасибо за помощь.

Вот код заголовочного файла "ColorOption.h":

#import <Foundation/Foundation.h>

@interface ColorOption : NSArrayController {
    IBOutlet NSPopUpButton *colorPopup;
    NSArray *theNumbers;
}
@property (retain) NSPopUpButton *colorPopup;
@property (readwrite, copy) NSArray *theNumbers;
@end

@interface StatusTransformer : NSValueTransformer {
}
@end

Вот код файла реализации "ColorOption.m":

#import "ColorOption.h"

@implementation ColorOption
@synthesize colorPopup;
@synthesize theNumbers;

-(void)awakeFromNib {
    [self setTheNumbers:[NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2],[NSNumber numberWithInt:3],nil]];
    StatusTransformer *statusTrans = [[[StatusTransformer alloc] init] autorelease];
    [NSValueTransformer setValueTransformer:statusTrans forName:@"StatusTransformer"];
}
@end

@implementation StatusTransformer
+ (Class)transformedValueClass { return [NSString class]; }
+ (BOOL)allowsReverseTransformation { return YES; }
- (id)transformedValue:(id)value {
    switch ([value intValue]) {
        case 1:
        return @"Red";
        break;
        case 2:
        return @"Green";
        break;
        case 3:
        return @"Blue";
        break;
        default:
        return @"";
        break;
    }
}

-(id)reverseTransformedValue:(id)value {
    if ([@"Red" isEqualToString:value]) return [NSNumber numberWithInt:1];
    if ([@"Green" isEqualToString:value]) return [NSNumber numberWithInt:2];
    if ([@"Blue" isEqualToString:value]) return [NSNumber numberWithInt:3];    
    return nil;
}

@end

person Community    schedule 09.09.2011    source источник
comment
Я некоторое время боролся с всплывающими кнопками и преобразователями значений. Не могли бы вы объяснить, какие у вас были привязки в вашем ответе? Я не понимаю, при чем здесь Имена.   -  person rdelmar    schedule 19.09.2012
comment
Привет, Rdelmar, посмотри ответ внизу страницы и напиши, помогло ли тебе это.   -  person    schedule 19.09.2012


Ответы (1)


Я просматриваю свои вопросы и вижу, что этот остался без ответа. Однако тем временем я нашел ответ, который я опубликую сейчас, чтобы он мог помочь другим.

Ошибка, которую я сделал, заключалась в том, что я определил массив целочисленных значений, в то время как я должен был определить массив слов, заполняющих всплывающую кнопку. Вот полное решение:

Заголовочный файл:

#import <Cocoa/Cocoa.h>

@interface ColorOption : NSArrayController {
    IBOutlet NSPopUpButton *colorPopup;
    NSArray *theNames;
}
@property (strong) NSPopUpButton *colorPopup;
@property (readwrite, copy) NSArray *theNames;
@end

@interface StatusTransformer : NSValueTransformer {
}
@end

Файл реализации

#import "ColorOption.h"

@implementation ColorOption
@synthesize colorPopup = _colorPopup;
@synthesize theNames = _theNames;

-(void)awakeFromNib {
    [self setTheNames:[NSArray arrayWithObjects:[NSString stringWithFormat:@"Red"],[NSString stringWithFormat:@"Green"],[NSString stringWithFormat:@"Blue"],nil]];
    StatusTransformer *statusTrans = [[[StatusTransformer alloc] init] autorelease];
    [NSValueTransformer setValueTransformer:statusTrans forName:@"StatusTransformer"];
}
@end

@implementation StatusTransformer
+ (Class)transformedValueClass {
    return [NSString class];
}
+ (BOOL)allowsReverseTransformation {
    return YES;
}
- (id)transformedValue:(id)value {
    switch ([value intValue]) {
        case 1: {
            return @"Red";
            break;
        }
        case 2: {
            return @"Green";
            break;
        }
        case 3: {
            return @"Blue";
            break;
        }
        default: {
            return nil;
            break;
        }
    }
}

-(id)reverseTransformedValue:(id)value {
    if ([@"Red" isEqualToString:value]) return [NSNumber numberWithInt:1];
    if ([@"Green" isEqualToString:value]) return [NSNumber numberWithInt:2];
    if ([@"Blue" isEqualToString:value]) return [NSNumber numberWithInt:3];    
    return nil;
}

@end

Теперь в инспекторе привязок Xcode преобразователь значений должен быть применен к «Значениям содержимого» и «Выбранному объекту» для всплывающей кнопки.

person Community    schedule 04.08.2012
comment
1. Перетащите объект (синий куб) в список объектов вашего Xib. В инспекторе идентификации укажите имя класса, в котором определены ваша всплывающая кнопка и массив (в моем примере это ColorOption. Щелкните его правой кнопкой мыши и свяжите имя всплывающей кнопки (colorPopup) с фактической кнопкой в ​​вашем представлении. - person ; 19.09.2012
comment
2) Добавьте контроллер массива. В его инспекторе Bindings определите Controller Content следующим образом: Content Array -> Bind to name of Object and Model Key Path = theNames. - person ; 19.09.2012
comment
3) Нажмите всплывающую кнопку, чтобы отобразить инспектор привязок, и настройте выбор значений следующим образом: «Содержимое» -> «Привязать к имени контроллера массива и ключу контроллера = аранжированные объекты», затем «Значения содержимого» -> «Привязать к имени контроллера массива и ключу контроллера = аранжированные объекты». и Преобразователь значений = имя преобразователя значений, затем Выбранный объект -> Привязать к имени контроллера массива, связанного с объектом, которому соответствуют данные, и Ключ контроллера = выбор, а Путь ключа модели = имя связанного атрибута объекта и Преобразователь значений = имя Преобразователь Ценности. - person ; 19.09.2012
comment
Я думаю, что уже сделал все это - странно то, что если я регистрирую значение в методе transformValue, он дает мне массив, к которому привязан контроллер массива, а не отдельные значения в этом массиве. Я несколько раз успешно использовал преобразователи значений с табличными представлениями, поэтому я не уверен, что здесь происходит. - person rdelmar; 19.09.2012