No estoy seguro de que haya mucha información para crear una vista de colección mediante programación y sin enlaces, pero aquí va.
Introducción
Hay esencialmente cuatro componentes cuando se utiliza una vista de colección:
- Vista: una subclase de
NSView
, responsable de mostrar la información;
- La vista de la colección en sí;
- Controlador de vista: una subclase de
NSCollectionViewItem
que sirve como prototipo del elemento de vista de colección;
- Modelo: una matriz de objetos.
Por lo general, una vista está diseñada en Interface Builder, y un modelo está mediado por enlaces Cocoa.
Hacerlo mediante programación:
Constantes
static const NSSize buttonSize = {80, 20};
static const NSSize itemSize = {100, 40};
static const NSPoint buttonOrigin = {10, 10};
Ver
Ésta es una vista estándar (una vista personalizada en el Interface Builder jerga) que contiene un botón. Tenga en cuenta que la vista tiene un tamaño fijo.
@interface BVView : NSView
@property (weak) NSButton *button;
@end
@implementation BVView
@synthesize button;
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:(NSRect){frameRect.origin, itemSize}];
if (self) {
NSButton *newButton = [[NSButton alloc]
initWithFrame:(NSRect){buttonOrigin, buttonSize}];
[self addSubview:newButton];
self.button = newButton;
}
return self;
}
@end
Vista Controlador (Prototipo)
Normalmente, un controlador de vista carga su vista desde un archivo semilla. En los casos excepcionales en que el controlador de vista no obtiene su vista desde un archivo de punta, el desarrollador debe enviarlo -setView:
antes de que -view
sea recibido por el controlador de vista, o anular -loadView
. El siguiente código hace esto último.
Los controladores de vista reciben el objeto modelo correspondiente a través de -setRepresentedObject:
. Lo he reemplazado para actualizar el título del botón cada vez que cambia el objeto del modelo. Tenga en cuenta que esto se puede lograr mediante el uso de enlaces Cocoa sin ningún código en absoluto.
Tenga en cuenta que ninguno de este código es específico para las vistas de colección: es el comportamiento del controlador de vista general.
@interface BVPrototype : NSCollectionViewItem
@end
@implementation BVPrototype
- (void)loadView {
[self setView:[[BVView alloc] initWithFrame:NSZeroRect]];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
[[(BVView *)[self view] button] setTitle:representedObject];
}
@end
Modelo
Una simple matriz de cadenas que representan los títulos de botón:
@property (strong) NSArray *titles;
self.titles = [NSArray arrayWithObjects:@"Case", @"Molly", @"Armitage",
@"Hideo", @"The Finn", @"Maelcum", @"Wintermute", @"Neuromancer", nil];
linterna Vista
Hasta ahora, la única relación que se ha establecido es la vista (BVView
) utilizado por el prototipo de artículo (BVPrototype
). La vista de la colección debe ser informada del prototipo que debería estar utilizando así como del modelo del que se obtienen los datos.
NSCollectionView *cv = [[NSCollectionView alloc]
initWithFrame:[[[self window] contentView] frame]];
[cv setItemPrototype:[BVPrototype new]];
[cv setContent:[self titles]];
código fuente completo para el Delegado de aplicación
#import "BVAppDelegate.h"
static const NSSize buttonSize = { 80, 20 };
static const NSSize itemSize = { 100, 40 };
static const NSPoint buttonOrigin = { 10, 10 };
@interface BVView : NSView
@property (weak) NSButton *button;
@end
@implementation BVView
@synthesize button;
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:(NSRect){frameRect.origin, itemSize}];
if (self) {
NSButton *newButton = [[NSButton alloc]
initWithFrame:(NSRect){buttonOrigin, buttonSize}];
[self addSubview:newButton];
self.button = newButton;
}
return self;
}
@end
@interface BVPrototype : NSCollectionViewItem
@end
@implementation BVPrototype
- (void)loadView {
[self setView:[[BVView alloc] initWithFrame:NSZeroRect]];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
[[(BVView *)[self view] button] setTitle:representedObject];
}
@end
@interface BVAppDelegate()
@property (strong) NSArray *titles;
@end
@implementation BVAppDelegate
@synthesize window = _window;
@synthesize titles;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.titles = [NSArray arrayWithObjects:@"Case", @"Molly", @"Armitage",
@"Hideo", @"The Finn", @"Maelcum", @"Wintermute", @"Neuromancer", nil];
NSCollectionView *cv = [[NSCollectionView alloc]
initWithFrame:[[[self window] contentView] frame]];
[cv setItemPrototype:[BVPrototype new]];
[cv setContent:[self titles]];
[cv setAutoresizingMask:(NSViewMinXMargin
| NSViewWidthSizable
| NSViewMaxXMargin
| NSViewMinYMargin
| NSViewHeightSizable
| NSViewMaxYMargin)];
[[[self window] contentView] addSubview:cv];
}
@end
La documentación sobre NSCollectionView es sorprendentemente mala. Cualquiera que entienda cómo funciona esta bestia mítica y pueda compartir sus conocimientos está ayudando a los desarrolladores de Objective-C en todas partes. Muchas gracias. – Tronathan
Bavarious, ¿puedo pedirle que muestre cómo sincronizar la vista de colección con una matriz mutable de elementos? – brigadir
@Bavarious - gracias por una gran respuesta. –