Search code examples
cocoanstableviewnstablecolumnnsimagecell

Core Data Image Won't Load Into NSTableView Image Cell


In my code I am storing an image into my Core Data model (works fine). If I set up my view to have an NSImageView and bind its Data to Controller Key: selection and modelKeyPath: myImagePath, it works. It will show each image for the selected row.

I then create a new column in my NSTableView and drag an image cell onto the column. However, I cannot get my Core Data bindings to have the image show up in the cell. I have tried binding both value and data, but no luck.

Since I am sure the image is stored properly, what am I doing wrong in my binding to prevent the image from showing up in the table cell?

Thanks so much.

(My background: new Cocoa developer who has recently gone through the entire Hillegass book.)


Solution

  • I'm not sure what is happening to cause your problem but there's an easy way to find out. Hook up an NSValueTransformer to the binding. Then in that transformer you can log stuff to find out if you're passing a nil value, or you can transform your data value into an NSImage and pass that back… basically you can do whatever you want in the transformer class. Here's one I use on image data in a core-data model.

    @interface DataToImageTransformer : NSValueTransformer {
    
    }
    
    @end
    
    
    @implementation DataToImageTransformer
    
    + (Class)transformedValueClass {
        return [NSImage class];
    } // the class of the return value from transformedValue:
    
    + (BOOL)allowsReverseTransformation {
        return YES;
    } // if YES then must also have reverseTransformedValue:
    
    - (id)transformedValue:(id)value {
        if (value == nil || [value length] < 1) return nil;
        NSImage* i = nil;
        if ([value isKindOfClass:[NSData class]]) {
            i = [NSKeyedUnarchiver unarchiveObjectWithData:value];
        }
        return i;
    }
    
    - (id)reverseTransformedValue:(id)value {
        if (value == nil) return nil;
        NSData* d = nil;
        if ([value isKindOfClass:[NSImage class]]) {
            d = [NSKeyedArchiver archivedDataWithRootObject:value];
        }
        return d;
    }
    
    @end
    

    In AppController class you initialize the transformer:

    + (void)initialize {
        DataToImageTransformer *transformer = [[DataToImageTransformer alloc] init];
        [NSValueTransformer setValueTransformer:transformer forName:@"DataToImageTransformer"];
        [transformer release];
    }
    

    Then in Interface Builder you put "DataToImageTransformer" in for the binding. Now you have control over the binding and can do as I explained earlier in the transformer class. Note that I'm using NSKeyedArchiver to convert an NSImage to data and back again but you can use tiffRepresentation or any other method you want in its place.