Pregunta

Tengo una NSTableView que se une a un NSArrayController. Me gustaría tener una de las columnas de las tablas que muestran el índice de la fila de la tabla. Esto es bastante fácil de hacer cuando se implementa NSTableDataSource ti mismo, pero no puede resolverlo con una vista de tabla ligada. Creo que estoy buscando aquí por algo así como la ruta de la clave @count que me da la cuenta de arrangedObjects (es decir @index) pero esto es claramente ausente.

Dos aclaraciones:

  1. El índice que se muestra en cada fila es el índice de la fila y no relacionado en absoluto a la forma de los datos es en realidad dispuesta en el controlador de modelo o matriz. Por ejemplo, si toda la información es de 10000 artículos a continuación, los índices deben ir de 1 a 10.000, si el usuario introduce un término de búsqueda y la mesa está mostrando sólo 4 de los artículos a continuación, los números deben ir de 1 a 4, incluso si el elementos que se muestran son en realidad de todo el conjunto original.
  2. Necesito esto porque me pidieron que hacer esto por el cliente :-). El cliente necesita una manera de ser capaz de estimar el número de filas antes o después de un cierto fila. Hola podrían, por ejemplo, quieren saber cómo se han añadido muchas filas.
¿Fue útil?

Solución

A mi entender, se podría optar por no obligar a que la columna de la tabla, y el uso de una fuente de datos en su lugar. Recuerdo NSTableView apoya este tipo de operación "modo dual", pero no puedo encontrar ninguna documentación que lo confirme.

Otros consejos

Hace poco práctica esta utilizando una subclase NSRuler que atrae a los números de línea al lado de cada línea en el TableView. Basé el código en algo parecido que he encontrado aquí .

Se puede agregar esto a su tableview usando:

NSScrollView *scrollView = [tableView enclosingScrollView];
TableLineNumberRulerView *lineNumberView = [[TableLineNumberRulerView alloc] initWithTableView:tableView
                                                                           usingArrayController:arrayController];

[scrollView setVerticalRulerView:lineNumberView];
[scrollView setHasVerticalRuler:YES];
[scrollView setRulersVisible:YES];

Aquí está el archivo de interfaz:

//
//  TableLineNumberRulerView
//  Line View Test
//
//  Created by Ben Golding, Object Craft Pty Ltd on 7 May 2014.
//  Based on code by Paul Kim on 9/28/08.


#import <Cocoa/Cocoa.h>

@interface TableLineNumberRulerView : NSRulerView<NSCoding>

@property (strong) NSArrayController *arrayController;

@property (strong) NSFont       *font;
@property (strong) NSColor  *textColor;
@property (strong) NSColor  *alternateTextColor;
@property (strong) NSColor  *backgroundColor;
@property (strong) NSDictionary *textAttributes;
@property (assign) NSUInteger   rowCount;

- (id)initWithTableView:(NSTableView *)tableView  usingArrayController:(NSArrayController *)arrayController;

@end

Aquí está la aplicación:

//
//  TableLineNumberRulerView.m
//  Line View Test
//
//  Created by Ben Golding, Object Craft Pty Ltd on 7 May 2014.
//  Based on code by Paul Kim on 9/28/08.

#import "TableLineNumberRulerView.h"

#define DEFAULT_THICKNESS   22.0
#define RULER_MARGIN        5.0

@implementation TableLineNumberRulerView

@synthesize font;
@synthesize textColor;
@synthesize alternateTextColor;
@synthesize backgroundColor;
@synthesize textAttributes;
@synthesize rowCount;


- (id)initWithTableView:(NSTableView *)tableView usingArrayController:(NSArrayController *)arrayController
{
    NSScrollView *scrollView = [tableView enclosingScrollView];

    if ((self = [super initWithScrollView:scrollView orientation:NSVerticalRuler]) == nil)
        return nil;

    [self setClientView:tableView];

    self.arrayController = arrayController;
    [arrayController addObserver:self forKeyPath:@"arrangedObjects" options:NSKeyValueObservingOptionNew context:nil];

    self.font = [NSFont labelFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
    self.textColor = [NSColor colorWithCalibratedWhite:0.42 alpha:1.0];
    self.alternateTextColor = [NSColor whiteColor];
    self.textAttributes = @{
        NSFontAttributeName: [self font],
        NSForegroundColorAttributeName: [self textColor]
    };

    self.rowCount = [[arrayController arrangedObjects] count];

    return self;
}

- (void)awakeFromNib
{
    [self setClientView:[[self scrollView] documentView]];      // this will be an NSTableView instance
}

- (void)finalize
{
    [self.arrayController removeObserver:self forKeyPath:@"arrangedObjects"];
}

#pragma mark -
#pragma mark Key-Value observing of changes to array controller

/*
 * This picks up changes to the arrayController's arrangedObjects using KVO.
 * We check the size of the old and new rowCounts and compare them to see if the number
 * digits has changed, and if so, we adjust the ruler width.
 */

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"arrangedObjects"]) {
        NSUInteger newRowCount = [[self.arrayController arrangedObjects] count];

        if ((int)log10(self.rowCount) != (int)log10(newRowCount))
            [self setRuleThickness:[self requiredThickness]];
        self.rowCount = newRowCount;
        // we need to redisplay because line numbers may change or disappear in view
        [self setNeedsDisplay:YES];
    }
}


- (CGFloat)requiredThickness
{
    NSUInteger      lineCount = [[self.arrayController arrangedObjects] count],
                    digits = (unsigned)log10((lineCount < 1) ? 1: lineCount) + 1;
    NSMutableString *sampleString = [NSMutableString string];
    NSSize          stringSize;

    for (NSUInteger i = 0; i < digits; i++) {
        // Use "8" since it is one of the fatter numbers. Anything but "1"
        // will probably be ok here. I could be pedantic and actually find the fattest
        // number for the current font but nah.
        [sampleString appendString:@"8"];
    }

    stringSize = [sampleString sizeWithAttributes:[self textAttributes]];

    // Round up the value. There is a bug on 10.4 where the display gets all wonky when scrolling if you don't
    // return an integral value here.
    return ceil(MAX(DEFAULT_THICKNESS, stringSize.width + RULER_MARGIN * 2));
}

- (void)drawHashMarksAndLabelsInRect:(NSRect)aRect
{
    NSTableView *tableView = (NSTableView *)[self clientView];
    NSRect bounds = [self bounds];
    NSRect visibleRect = [[tableView enclosingScrollView] documentVisibleRect];
    NSRange visibleRowRange = [tableView rowsInRect:visibleRect];
    CGFloat yinset = NSHeight([[tableView headerView] bounds]);

    if (backgroundColor != nil) {
        [backgroundColor set];
        NSRectFill(bounds);

        [[NSColor colorWithCalibratedWhite:0.58 alpha:1.0] set];
        [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(bounds) - 0/5, NSMinY(bounds))
                                  toPoint:NSMakePoint(NSMaxX(bounds) - 0.5, NSMaxY(bounds))];
    }

//    NSLog(@"drawHashMarksAndLabelsInRect: bounds %@, ruleThickness %lf", NSStringFromRect(bounds), [self ruleThickness]);

    for (NSUInteger row = visibleRowRange.location; NSLocationInRange(row, visibleRowRange); row++) {
        // Line numbers are internally stored starting at 0
        NSString *labelText = [NSString stringWithFormat:@"%lu", row + 1];
        NSSize stringSize = [labelText sizeWithAttributes:self.textAttributes];
        NSRect rowRect = [tableView rectOfRow:row];
        CGFloat ypos = yinset + NSMinY(rowRect) - NSMinY(visibleRect);

        [labelText drawInRect:NSMakeRect(NSWidth(bounds) - stringSize.width - RULER_MARGIN,
                                         ypos + (NSHeight(rowRect) - stringSize.height) / 2.0,
                                         NSWidth(bounds) - RULER_MARGIN * 2.0, NSHeight(rowRect))
               withAttributes:self.textAttributes];
    }
}

#pragma mark -
#pragma mark NSCoding methods

#define FONT_CODING_KEY         @"font"
#define TEXT_COLOR_CODING_KEY       @"textColor"
#define ALT_TEXT_COLOR_CODING_KEY   @"alternateTextColor"
#define BACKGROUND_COLOR_CODING_KEY @"backgroundColor"

- (id)initWithCoder:(NSCoder *)decoder
{
    if ((self = [super initWithCoder:decoder]) != nil) {
        if ([decoder allowsKeyedCoding]) {
            font = [decoder decodeObjectForKey:FONT_CODING_KEY];
            textColor = [decoder decodeObjectForKey:TEXT_COLOR_CODING_KEY];
            alternateTextColor = [decoder decodeObjectForKey:ALT_TEXT_COLOR_CODING_KEY];
            backgroundColor = [decoder decodeObjectForKey:BACKGROUND_COLOR_CODING_KEY];
        } else {
            font = [decoder decodeObject];
            textColor = [decoder decodeObject];
            alternateTextColor = [decoder decodeObject];
            backgroundColor = [decoder decodeObject];
        }
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
    [super encodeWithCoder:encoder];

    if ([encoder allowsKeyedCoding]) {
        [encoder encodeObject:font forKey:FONT_CODING_KEY];
        [encoder encodeObject:textColor forKey:TEXT_COLOR_CODING_KEY];
        [encoder encodeObject:alternateTextColor forKey:ALT_TEXT_COLOR_CODING_KEY];
        [encoder encodeObject:backgroundColor forKey:BACKGROUND_COLOR_CODING_KEY];
    } else {
        [encoder encodeObject:font];
        [encoder encodeObject:textColor];
        [encoder encodeObject:alternateTextColor];
        [encoder encodeObject:backgroundColor];
    }
}

@end

Si se asume que tu objetivo es replicar el comportamiento de iTunes, a la columna sólo necesita mostrar a 1 (número de filas visibles). En realidad, no necesidad de relacionarse con su modelo en absoluto.

Por lo tanto, dar a su controlador de un generado dinámicamente propiedad de matriz, y que sea dependen en la matriz de objetos de modelo reales

.

Para esta propiedad, implementar el array métodos de acceso , con el getter indexada simplemente computar idx + 1, cuadro ing hacia arriba, y devolver ese objeto. También puede ser necesario para implementar el captador de todo el conjunto para satisfacer KVC.

Asegúrese de que la columna se establece como no editable, y el conjunto de unión a no condicionalmente conjunto enabled. De lo contrario, obtendrá una excepción (por no tener fijadores para esta propiedad) cuando el usuario intenta entrar en un nuevo índice para una fila.

Una nota de precaución: Esto puede causar problemas, como NSTableView no espera que sus columnas que se unen a las matrices discretas; se espera que todos sus columnas en obligarse a diferentes propiedades de los objetos del modelo en una sola matriz. Puede que tenga que obligar a la content de la propia vista de tabla a su gran variedad de objetos del modelo, además de unirse los enlaces de contenido de las columnas, y he tenido problemas con los que antes de .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top