简体   繁体   中英

Cocoa Bindings - NSTableView - Swapping Values

Is an NSValueTransform subclass a good choice for displaying Core Data attributes into UI views displaying:

  1. A number string like (0,1,2,3,etc) into a string such as (Pending, Completed, Frozen, In progress, etc)
  2. A number string like (0,1) into a app-based image (red.png if 0, green.png if 1)

Here's what Core Data displays for the two attributes, timer and status:

在此处输入图片说明

Here is what I want to be displayed instead, without changing the values in Core Data:

在此处输入图片说明

If not to use NSValueTransformer, in what other way is this possible?

I do not want to see the data permanently converted, only for the benefit of less data stored in Core Data and better UI view items.

I have also tried to modify the attributes in the managed object class (with out KVO notification) with no luck.

Yes, NSValueTransformer subclasses work just fine for this purpose.

You can also add read-only computed properties to your managed object class, and that should work, too. Those properties can even be added by a category in the controller code, if they don't make sense as part of the model code.

For example:

+ (NSSet*) keyPathsForValuesAffectingStatusDisplayName
{
    return [NSSet setWithObject:@"status"];
}
- (NSString*) statusDisplayName
{
    NSString* status = self.status;
    if ([status isEqualToString:@"0"])
        return @"Pending";
    else if ([status isEqualToString:@"1"])
        return @"Completed";
    // ...
}

The +keyPathsForValuesAffectingStatusDisplayName method lets KVO and bindings know that when status changes, so does this new statusDisplayName property. See the docs for +keyPathsForValuesAffectingValueForKey: to learn how that works.

I ended up using what at first appeared to be blocking the display of different info in those cells, using:

#pragma mark - Table View Delegate

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    /*  tableColumn = (string) @"AutomaticTableColumnIdentifier.0"
                row = (int)    0          */
    NSString *identifier = [tableColumn identifier];
    NSTableCellView *cellView = [tableView makeViewWithIdentifier:identifier owner:self];

    NSManagedObject *item = [self.itemArrayController.arrangedObjects objectAtIndex:row];

    if ([identifier isEqualToString:@"AutomaticTableColumnIdentifier.0"]) {
        /*  subviews returns array with  0 = Image View &
                                         1 = Text Field      */
        /*  First, set the correct timer image  */
        ...  logic  ...
        NSImageView *theImage = (NSImageView *)[[cellView subviews] objectAtIndex:0];
        theImage.image = [NSImage imageNamed:@"green.gif"];

        /*  Second, display the desired status  */
        NSTextField *theTextField = (NSTextField *)[[result subviews] objectAtIndex:1];
        ...  logic  ...
        theTextField.stringValue = @"Pending";
    }

    return cellView;
}

Apple's documentation states (somewhere) that bindings with an Array Controller can work in combination with manually populating the table view cells. It seems best and easiest to start with bindings and then refine display values manually.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM