11
votes

Pourquoi mon attribut de données de base transformable n'utilise-t-il pas mon nsvaluetransformer personnalisé?

J'ai une application de données de base avec un modèle de données assez simple. Je souhaite pouvoir stocker des instances de Nsimage dans le magasin persistant sous forme d'objets PNG bitmap Nsdata, pour économiser de l'espace.

à cette fin, j'ai écrit un simple nsvaluetransformer pour convertir une nsimage en format nsdata au format Bitmap PNG. J'inscrise le transformateur de valeur avec ce code dans mon délégué de mon application: p> xxx pré>

dans mon modèle de données, j'ai défini l'attribut image pour être transformable et spécifié pngdatavaluetransformer code> comme nom de transformateur de valeur. p>

Cependant, mon transformateur de valeur personnalisé n'est pas utilisé. Je connais cela comme je l'ai placé des messages de journal dans mon -TransformedValue de ma valeur Transformer: code> et -ReSveretransformedvalue code> non enregistré et que les données enregistrées sur le disque sont enregistrées. Juste un nsimage archivé, pas l'objet PNG Nsdata que cela devrait être. P>

Pourquoi ne fonctionne pas? P>

Voici le code de ma valeur Transformer: P>

@implementation PNGDataValueTransformer

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

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

- (id)transformedValue:(id)value
{
    if (value == nil) return nil;
    if(NSIsControllerMarker(value))
        return value;
    //check if the value is NSData
    if(![value isKindOfClass:[NSData class]])
    {
        [NSException raise:NSInternalInconsistencyException format:@"Value (%@) is not an NSData instance", [value class]];
    }
    return [[[NSImage alloc] initWithData:value] autorelease];
}

- (id)reverseTransformedValue:(id)value;
{
    if (value == nil) return nil;
    if(NSIsControllerMarker(value))
        return value;
    //check if the value is an NSImage
    if(![value isKindOfClass:[NSImage class]])
    {
        [NSException raise:NSInternalInconsistencyException format:@"Value (%@) is not an NSImage instance", [value class]];
    }
    // convert the NSImage into a raster representation.
    NSBitmapImageRep* bitmap    = [NSBitmapImageRep imageRepWithData: [(NSImage*) value TIFFRepresentation]];
    // convert the bitmap raster representation into a PNG data stream
    NSDictionary* pngProperties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:NSImageInterlaced];
    // return the png encoded data
    NSData* pngData             = [bitmap representationUsingType:NSPNGFileType properties:pngProperties];
    return pngData;
}

@end


0 commentaires

6 Réponses :


0
votes

Si rien dans votre code ailleurs, l'explicity utilise la classe pngdatavaluetransformer, la méthode + initialisation + de cette classe ne sera jamais appelée. Spécification du nom de votre modèle de données de base ne le déclenchera pas non plus. Cela essaiera simplement de rechercher un transformateur de valeur pour ce nom, qui retournera nul, car aucune instance de transformateur n'a encore été enregistrée sous ce nom.

Si c'est bien ce qui se passe dans votre cas, ajoutez simplement un appel à [pngdatavaluetransformer Initialiser] quelque part dans votre code avant que votre modèle de données soit accessible, par exemple. Dans la méthode + Initialize de la classe, il s'agit de ce modèle de données. Qui devrait déclencher l'instance de transformateur de valeur créée et enregistrée afin que les données principales puissent y accéder lorsqu'il doit.


1 commentaires

Salut Brian, la méthode + initialisée est dans mon délégué de l'application, pas le transformateur de valeur et je peux définitivement vérifier que c'est appelé. Si je mettais un point d'arrêt dans la méthode de mon nsvaluetransformer, il est définitivement initialisé. Si je définis l'attribut pour être de type "binaire" et appliquer mon transformateur de valeur sur chaque liaison dans IB, cela fonctionne bien. Je ne comprends tout simplement pas pourquoi le transformateur personnalisé n'est pas utilisé lorsque je spécifie le type d'attribut comme transformable.



26
votes

Si je ne me trompe pas, votre transformateur de valeur a une direction inversée. Je fais la même chose dans mon application, en utilisant le code comme ce qui suit: xxx

S'il s'agit de l'iPhone, vous devriez être capable d'échanger dans votre code NSImage aux emplacements appropriés. Je n'ai tout simplement pas testé mon implémentation de Mac.

Tout ce que j'ai fait pour activer cela était de définir la propriété de mon image pour être transformable dans le modèle de données et spécifiez le nom du transformateur. Je n'avais pas besoin d'enregistrer manuellement le transformateur de valeur, comme vous le faites dans votre méthode + initialisation.


1 commentaires

Merci Brad. J'ai essayé cela et cela n'a pas fait de différence, mon transformateur de valeur est juste ignoré.



3
votes

Il semble que l'enregistrement du transformateur n'a aucun effet sur les données de base de Wether utilisera ou non. Je joue avec le code d'échantillon de photolocations et je supprime l'enregistrement du transformateur n'a aucun effet. Tant que votre valeurRANSFormeName est le nom de votre classe et que la mise en œuvre de votre transformateur est incluse dans la cible, elle devrait fonctionner.

S'il n'y a pas d'exécution de code dans le transformateur, le code dans le transformateur n'est pas pertinent. Le problème doit être ailleurs dans la pile de données de base ou dans la Déclaration du transformateur.


1 commentaires

Pareil ici! Avez-vous trouvé une solution?



0
votes

Consultez le code exemple Ici .

Est-ce que cela fait ce que vous voulez? P>

@implementation UIImageToDataTransformer


+ (BOOL)allowsReverseTransformation {
    return YES;
}

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


- (id)transformedValue:(id)value {
    NSData *data = UIImagePNGRepresentation(value);
    return data;
}


- (id)reverseTransformedValue:(id)value {
    UIImage *uiImage = [[UIImage alloc] initWithData:value];
    return [uiImage autorelease];
}


0 commentaires

2
votes

Il s'avère qu'il s'agit d'un bug dans les cadres. Voir cet article par un employé Apple sur la liste de diffusion Cocoa-Dev:

http://lists.apple.com/archives /Cocoa-Dev/2009/dec/msg00979.html


0 commentaires

1
votes

Vous devez enregistrer explicitement votre transformateur pendant l'exécution.

Bon endroit pour le faire consiste à remplacer la méthode d'initialisation de la classe dans votre sous-classe d'entité NSManageDObject. Comme mentionné avant qu'il ne soit connu de bogue de données de base. Voici le code crucial de l'échantillon de code d'emplacement d'Apple, il est testé et fonctionne: http://developer.apple.com/library/ios/ # samplecode / emplacements / introduction / intro.html xxx


2 commentaires

Oui, je le sais et je le fais.


Dans mon cas, c'était exactement le problème. Vous pouvez également vérifier si le nom du transformateur correspond à celui que vous avez déclaré dans le modèle de données et si vous n'avez pas de corps inverse des méthodes: transforméValue et réversetransformedValue.