图像的核心数据可转换属性出现问题

发布于 2025-01-08 07:50:02 字数 3998 浏览 1 评论 0原文

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

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

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

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

//  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”的头文件和实现文件。堆栈和其他地方有很多这样的例子(tiff 表示是任意的)。

//  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

值转换器可以通过在 MyDocument.m 中分配它的实例来初始化/注册,但最终,只要将转换器标头导入到 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]; 

我在这方面缺少什么?

I am stuck on what is supposed to be a very simple thing to do: have a Core Data Entity store / display (through bindings) an image assigned as a transformable attribute.

I've read many related posts on the Stack (e.g., see here and here), but am still having trouble with it, after having developed sample code and researched other articles (e.g., see here as well as here). This is related to my earlier question, which I still have not resolved.

I created a simple doc-based Core Data App to demonstrate the problem. The Core Data managed object is called "TheEntity" and the attribute "theImageAtt." The entity as defined in Core Data is shown below (ImageValueTransformer is the NSValueTransformer):
enter image description here

I let XCode generate the NSManagedObject subclass header and implementation files (I left out the code for the "name" attribute to make it simpler):

//  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

Below are the header and implementation files for my "ImageValueTransformer." Lots of examples of this on the Stack and elsewhere (the tiff rep is arbitrary).

//  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

The Value Transformer can be initialized / registered by allocating an instance of it in MyDocument.m, but in the end, it doesn't matter that much as long as the transformer header is imported into the theEntity Header (see above). I have experimented with this and it does not remove the error I get below. For reference, there is earlier discussion on whether or not the value transformer needs to be registered (see the comments by CornPuff and Brian Webster).

Back to the problem at hand, a good code example from Apple is here which shows an alternative initialization of the value transformer, I tried that setup too.

Putting this into action, I have a method to load a test image and assign it to the transformable attribute in MyDocument.m (from a selected Entity instance in an 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
}

Zeroing-in on where the code breaks, the line below:

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

gives the error:

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 ...

If I comment out the said line above then my NSTable populates just fine (so the bindings and array controller seem ok), but of course with no image in the NSImageView.

As a check, the conversion code used in the Image Transformer works as expected (this is tested separately from the value transformer):

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

What am I missing on this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

羁绊已千年 2025-01-15 07:50:02

我发现上面报告的错误,即

Cannot create BOOL from object ...

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

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

进一步深入研究,图像井继承自 NSImageView,因此至少有一个区别是它们在“可编辑”属性方面是不同的(图像井是可编辑的,可以很好地与拖放配合使用)。因此,为了协调这两者,我将自定义视图设置为可编辑,认为这可能会解决问题:

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

但它一定是其他东西,这不能解决上面的错误。至少现在,我有一个可行的解决方案。如果其他人遇到这个问题,我希望这些笔记能有所帮助!

I found that the error reported above, namely,

Cannot create BOOL from object ...

does not occur when using an Image Well or Image Cell (subclasses of NSImageView) rather than the Custom View that I was trying to write to earlier.

So for now I'm using the default value transformer rather than a custom value transformer. This is a workable solution, but academically speaking, it would be nice to know why the default Custom View led to errors when binding to a Core Data attribute (defined as transformable in the Core Date Model).

Digging into this a little further, the Image Well inherits from NSImageView, so at least one difference is that they are distinct with regard to the "editable" property (Image Wells are editable which plays well with Drag-n-Drop). So in an attempt to reconcile these two, I set my Custom View to editable, thinking that this might resolve the problem:

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

But it must be something else, this does not resolve the error above. For now at least, I have a workable solution. Should others encounter this, I hope these notes are helpful!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文