1

Mon NSCollectionView dessine mes éléments NSCollection les uns sur les autres. MISE À JOUR: J'ai ajouté un exemple de projet GitHub Sample ProjectNSCollectionView dessine NSCollectionViewItems l'un sur l'autre

MISE À JOUR: Cela a quelque peu changé When the app first launches it looks like this

MISE À JOUR Mon exemple actuel a deux vues qui sont actuellement là-bas propres fichiers nib, avec NScollectionViewItem objets dédiés, ils sont actuellement les mêmes pour les tests. J'ai fondamentalement un NSCollectionViewItem qui a pour enfant une vue avec le NSTextField dedans. Avec toutes les contraintes.

Pour la vue de la collection, elle est configurée en tant que contrôleur de grille, et idéalement, j'aimerais avoir une colonne.

Afin de le charger avec des données que je fait mon ViewController le NSCollectionViewDataSource, et mis en œuvre le - (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section et - (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath

CODE MISE À JOUR complet Code inclus:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // Do any additional setup after loading the view. 

    [collectionView registerClass:ItemOne.class forItemWithIdentifier:@"Item1"]; 
    [collectionView registerClass:ItemTwo.class forItemWithIdentifier:@"Item2"]; 

    cellArray = [@[@"Item1", @"Item2", @"Item1", @"Item2", @"Item1"] mutableCopy]; 
} 


- (void)setRepresentedObject:(id)representedObject { 
    [super setRepresentedObject:representedObject]; 

    // Update the view, if already loaded. 
} 

#pragma mark - NSCollectionViewDatasource - 
- (NSInteger)collectionView:(NSCollectionView *)collectionView 
numberOfItemsInSection:(NSInteger)section { 

    // We are going to fake it a little. Since there is only one section 
    NSLog(@"Section: %ld, count: %ld", (long)section, [cellArray count]); 

    return [cellArray count]; 
} 

- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView 
itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath { 

    NSLog(@"IndexPath: %@, Requested one: %ld", indexPath, [indexPath item]); 
    NSLog(@"Identifier: %@", [cellArray objectAtIndex:[indexPath item]]); 

    NSCollectionViewItem *theItem = [collectionView makeItemWithIdentifier:[cellArray objectAtIndex:[indexPath item]] forIndexPath:indexPath]; 

    return theItem; 
} 

MISE À JOUR Le ItemOne et les classes ItemTwo sont toutes deux des classes vides, la plume de chacune a un NSCollectionViewItem qui à son tour a une vue, avec étiquette. La vue est connectée au NSCollectionViewItem par la propriété de vue dans NSCollectionViewItem. Il n'y a aucune contrainte, sauf pour celles par défaut

La grille NSCollectionView est configuré comme suit:

Mise en page: Grille Dimensions: Lignes Max: 0 colonnes Max: 1 min Taille de l'item: Largeur: 250 Hauteur: 150 Max Taille de l'article: Largeur: 250 Hauteur: 150

Ceci est le code pour mettre en place le tout, à ce stade ne pas le lier à une source de données.

Il semble que peu importe ce que je change les paramètres ou même en changeant le type de CollectionView à Flow ne change rien, il semble identique.

Je l'ai abordé comme un problème AutoLayout parce qu'à l'origine il y avait quelques problèmes de mise en page automatique, mais ceux qui ont tous été résolus.

Toute aide serait grandement appréciée.

+0

Avons fait quelques progrès! J'ai retiré les NSCollectionViewItems du storyboard et les ai mis dans leurs propres plumes avec des classes personnalisées. J'ai enregistré les classes et changé ma matrice pour inclure l'identifiant. Qui charge les deux vues dans deux colonnes distinctes, même si la grille est définie sur une colonne. Dès que je fais défiler la vue, les deux NSCollectionViewItems redeviennent un. – Tempus

+0

J'ai essayé votre code et cela fonctionne. Que se passe-t-il lorsque vous supprimez toutes les contraintes des éléments? Comment avez-vous mis en place la disposition de la grille? – Willeke

+0

Il semble que j'aurais pu penser à tout faux. J'ai donc une version de travail dans le GitHub Repo, mais cela fonctionne avec Flow et non Grid, et Grid n'a jamais fonctionné de la manière dont je m'y attendais. Et je suis capable de créer une seule colonne, en rendant la taille de l'objet aussi grande que la taille de la vue. Donc, c'est un peu travailler. Cependant, je veux voir si je peux avoir des vues avec des hauteurs différentes – Tempus

Répondre

1

Le tableau de données doit contenir des données au lieu de NSCollectionViewItem s. Dans collectionView:itemForRepresentedObjectAtIndexPath: vous appelez makeItemWithIdentifier:forIndexPath:. Appelez registerClass:forItemWithIdentifier: ou registerNib:forItemWithIdentifier: pour enregistrer votre classe ou votre plume.

Plus d'informations dans la documentation de NSCollectionView, collectionView:itemForRepresentedObjectAtIndexPath: et makeItemWithIdentifier:forIndexPath:.

EDIT:

Il y a deux façons de fournir un NSCollectionViewItem.

registerClass:forItemWithIdentifier:. Lorsque la vue de collection a besoin d'un nouvel élément, elle instaure cette classe. NSCollectionViewItem est une sous-classe de NSViewController et NSViewController cherche une plume avec le même nom que la classe. Le NSCollectionViewItem est le propriétaire de la plume.

registerNib:forItemWithIdentifier:. Lorsque la vue de collection a besoin d'un nouvel élément, elle charge cette pointe. Le NSCollectionViewItem est un objet de premier niveau dans la plume.

Vous avez mélangé registerClass:forItemWithIdentifier: avec un xib pour une utilisation avec registerNib:forItemWithIdentifier:. Utilisez registerNib:forItemWithIdentifier: ou corrigez le xib.

+0

Merci pour les commentaires Willeke. J'ai eu la même pensée. Je l'ai donc changé, de sorte que NSCollectionViewItems sont dans des fichiers nib séparés avec des classes dédiées. Dans le View Controller, j'inscris les identifiants et change le tableau en un tableau des identifiants.Dans le 'itemForRepresentedObjectAtIndex' je' makeItemWithIdentifier' et quand l'application charge d'abord tous les éléments sont séparés, mais dès que je fais une action de défilement, ils se combinent les uns sur les autres. Donc pas encore tout à fait là, il semble que le scrollview ne grandisse pas. – Tempus

+0

Bonne prise! Même si je l'ai fait fonctionner le Xib était incorrect que j'ai réparé. Et maintenant je pense que ça peut être utilisé de toute façon. J'ai encore échangé le type de grille, en raison de la fonctionnalité supplémentaire du type de flux – Tempus

+0

J'ai mis à jour le repo avec vos suggestions, et j'ai corrigé les fichiers xib alors maintenant on devrait travailler. – Tempus

0

Je l'ai compris.

et ont fait un repo github avec une version de travail Working Version of Collection View Sample Application

chose d'abord. Merci à la capture de Willeke de la façon dont le xib d'origine a été configuré, j'ai pu faire fonctionner le type de grille. Mais à la fin, la vue agrandie est un meilleur type de vue si vous pouvez la faire faire ce que vous voulez, parce qu'elle supporte les sections, et les distances entre les vues etc. Donc même si j'ai commencé à utiliser le type de grille que je vais implémenter le type Grow dans mon application.

J'ai donc accompli une seule vue de colonne en utilisant le type Grow.

Mes critères de succès sont les suivants:

  • Qu'il peut supporter des hauteurs de vue non uniforme (chaque vue personnalisée peut avoir sa propre hauteur)
  • Qu'il y ait une seule colonne, et chaque affichage personnalisé agrandit si la taille de la vue augmente.

Sur le code source:

@interface ViewController() 
@property NSMutableArray *cellArray; 
@property (weak) IBOutlet NSCollectionView *collectionView; 

@end 

@implementation ViewController 

@synthesize cellArray; 
@synthesize collectionView; 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // Do any additional setup after loading the view. 

    [collectionView registerClass:ItemOne.class forItemWithIdentifier:@"Item1"]; 
    [collectionView registerClass:ItemTwo.class forItemWithIdentifier:@"Item2"]; 

    cellArray = [@[@"Item1", @"Item2", @"Item1", @"Item2", @"Item1"] mutableCopy]; 
} 


- (void)setRepresentedObject:(id)representedObject { 
    [super setRepresentedObject:representedObject]; 

    // Update the view, if already loaded. 
} 

#pragma mark - NSCollectionViewDatasource - 

- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)collectionView { 
    return 1; 
} 

- (NSInteger)collectionView:(NSCollectionView *)collectionView 
numberOfItemsInSection:(NSInteger)section { 

    // We are going to fake it a little. Since there is only one section 
    NSLog(@"Section: %ld, count: %ld", (long)section, [cellArray count]); 

    return [cellArray count]; 
} 

- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView 
itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath { 

    NSLog(@"IndexPath: %@, Requested one: %ld", indexPath, [indexPath item]); 
    NSLog(@"Identifier: %@", [cellArray objectAtIndex:[indexPath item]]); 

    NSCollectionViewItem *theItem = [collectionView makeItemWithIdentifier:[cellArray objectAtIndex:[indexPath item]] forIndexPath:indexPath]; 

    theItem.representedObject = [cellArray objectAtIndex:[indexPath item]]; 

    return theItem; 
} 

#pragma mark - NSCollectionViewDelegate - 
- (NSSize)collectionView:(NSCollectionView *)collectionView 
       layout:(NSCollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 
    NSLog(@"%@", indexPath); 

    NSSize size = NSMakeSize(438, 150); 
    NSInteger width = 0; 
    NSInteger height = 0; 
    NSString *label = [cellArray objectAtIndex:[indexPath item]]; 

    NSRect collectionFrame = [collectionView frame]; 

    width = collectionFrame.size.width; 

    // TODO: This needs to be based on the actual value of the view instead of hardcoding a number in. 
    if ([label isEqualToString:@"Item1"]) { 
     height = 114; 
    } else if ([label isEqualToString:@"Item2"]) { 
     height = 84; 
    } 

    size = NSMakeSize(width, height); 

    return size;  
} 

@end 

Et là, vous l'avez. La mise en œuvre n'était pas trop mauvaise. Chacune des vues personnalisées qui apparaissent dans NSCollectionView sont définies dans leurs propres fichiers NSCollectionViewItem et .xib, elles sont donc facilement modifiables.

La seule partie qui est fragile est l'endroit où je calcule la hauteur de chaque vue, et il est seulement fragile parce que je suis paresseux dans ma mise en œuvre dans l'exemple d'application. Dans l'implémentation actuelle, je vais les récupérer dynamiquement à partir des vues réelles, afin qu'elles ne soient pas liées à un nombre statique.