1

我坚持应该做一件非常简单的事情:让核心数据实体存储/显示(通过绑定)分配为可转换属性的图像。

我已经阅读了有关 Stack 的许多相关帖子(例如,请参阅此处此处),但在开发示例代码并研究其他文章(例如,参阅此处和此处)之后,我仍然遇到问题。这与我之前的问题有关,我还没有解决。

我创建了一个简单的基于文档的 Core Data App 来演示这个问题。Core Data 托管对象称为“TheEntity”,属性称为“theImageAtt”。Core Data 中定义的实体如下图所示(ImageValueTransformer 是 NSValueTransformer):
在此处输入图像描述

我让 XCode 生成 NSManagedObject 子类头文件和实现文件(我省略了“name”属性的代码以使其更简单):

//  TheEntity.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "ImageValueTransformer.h"
@interface TheEntity : NSManagedObject
@property (nonatomic, retain) NSImage * theImageAtt;
@end
-----------------------
//  TheEntity.m
#import "TheEntity.h"
@implementation TheEntity
@dynamic theImageAtt;
@end

下面是我的“ImageValueTransformer”的头文件和实现文件。Stack 和其他地方有很多这样的例子(tiff rep 是任意的)。

//  ImageValueTransformer.h
#import <Foundation/Foundation.h>
@interface ImageValueTransformer : NSValueTransformer
@end
-------------------------------
//  ImageValueTransformer.m
#import "ImageValueTransformer.h"
@implementation ImageValueTransformer
+ (BOOL)allowsReverseTransformation {return YES;}
+ (Class)transformedValueClass {
    return [NSData class];  // have also tried: return [NSImage class]; 
}
- (id)transformedValue:(id)value {    
    NSData *data = [value TIFFRepresentation]; 
    return data;
}
- (id)reverseTransformedValue:(id)value {
    NSImage *imageRep = [[NSImage alloc] initWithData:value];
    return imageRep;
}
@end

Value Transformer 可以通过在 MyDocument.m 中分配它的一个实例来初始化/注册,但最后,只要将 Transformer 标头导入到 theEntity 标头中(见上文),这并不重要。我已经对此进行了实验,但它并没有消除我在下面遇到的错误。作为参考,之前有关于价值转换器是否需要注册的讨论(参见 CornPuff 和 Brian Webster 的评论)。

回到手头的问题,Apple 的一个很好的代码示例在这里显示了值转换器的替代初始化,我也尝试了该设置。

将其付诸实践,我有一种方法可以加载测试图像并将其分配给 MyDocument.m 中的可转换属性(来自 NSTable 中的选定实体实例):

- (IBAction)addImg:(id)sender {
    NSImage *theImg = [[NSImage alloc] initWithContentsOfFile:@"/Desktop/testImage.jpg"];
    //[theImageView setImage:theImg]; // as a test, this displays ok
    // "theEntities" below are defined as an IBOutlet to my Array Controller:
    [theEntities setValue:theImg forKeyPath:@"selection.theImageAtt"];
    NSLog(@"after setting the image ..."); // this never logs
}

在代码中断的地方归零,下面的行:

[theEntities setValue:theImg forKeyPath:@"selection.theImageAtt"];

给出错误:

Cannot create BOOL from object <4d4d002a 0003717e 8989898a 8a8a8b8b 8b8b8b8b
8a8a8a89 89898888 88878787 8a8a8a89 89898888 88888888 88888889 89898a8a
8a8a8a8a 8b8b8b88 88888787 87898989 8a8a8a89 89898a8a 8a8c8c8c 8b8b8b8a
8a8a8888 .... and so on for the size of the Image array ...

如果我注释掉上面所说的行,那么我的 NSTable 填充得很好(所以绑定和数组控制器看起来不错),但当然 NSImageView 中没有图像。

作为检查,图像转换器中使用的转换代码按预期工作(这与值转换器分开测试):

// Image to Data Conversion:
NSImage *imageIn = [[NSImage alloc] initWithContentsOfFile:@"testImage.jpg"];
NSData *imgData = [imageIn TIFFRepresentation];
NSImage *imageOut = [[NSImage alloc] initWithData:imgData];
[theImageDisplay setImage:imageOut]; 

我在这方面缺少什么?

4

1 回答 1

0

我发现上面报的错误,即

Cannot create BOOL from object ...

使用 Image Well 或 Image Cell(NSImageView 的子类)而不是我之前尝试写入的自定义视图时不会发生。

所以现在我使用默认值转换器而不是自定义值转换器。这是一个可行的解决方案,但从学术上讲,很高兴知道为什么默认的自定义视图在绑定到核心数据属性(在核心日期模型中定义为可转换)时会导致错误。

再深入一点,Image Well 继承自 NSImageView,因此至少有一个区别是它们在“可编辑”属性方面是不同的(Image Wells 是可编辑的,与 Drag-n-Drop 配合得很好)。因此,为了协调这两者,我将自定义视图设置为可编辑,认为这可能会解决问题:

theImageView = [[NSImageView alloc] init];
[theImageView setEditable:YES];

但它必须是别的东西,这并不能解决上面的错误。至少现在,我有一个可行的解决方案。如果其他人遇到这种情况,我希望这些笔记对您有所帮助!

于 2012-02-24T04:25:56.657 回答