Actualización inválida: número inválido de elementos en UICollectionView


Estoy perplejo en esto. Este es mi escenario. En mi Appdelegate, estoy creando

  1. Una instancia de un controlador de vista que se presentará modalmente para recopilar dos datos del usuario
  2. Un controlador tableView
  3. Un controlador de navegación que init con el controlador tableview como su rootview
    controlador
  4. Un CollectionViewController, tenga en cuenta que estoy registrando la clase para la celda aquí también.
  5. Un controlador UITabBarController que añadir el controlador de navegación a como la primera vista y el
    collectionview a como la segunda vista.. El TabBarCOntorller se establece como el rootview de la ventana.

Aquí está el código:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:   
(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.evc = [[WTAEntryControllerViewController alloc] init];
WTATableView *tv = [[WTATableView alloc] initWithNibName:@"WTATableView" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc]    
initWithRootViewController:tv];
nav.tabBarItem.title = NSLocalizedString(@"Birthday List", nil);
nav.tabBarItem.image = [UIImage imageNamed:@"birthdaycake"];
WTACollectionViewController *cv = [[WTACollectionViewController alloc] 
initWithCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init]];
[cv.collectionView registerClass:[UICollectionViewCell class] 
forCellWithReuseIdentifier:CellIdentifier];
cv.collectionView.backgroundColor = [UIColor whiteColor];
NSLog(@"cv instance %@", cv);
UITabBarController *tabController = [[UITabBarController alloc] init];
tabController.viewControllers = @[nav, cv];
self.window.rootViewController = tabController;
[self.window makeKeyAndVisible];
return YES
}

La vista de tabla tiene un botón de la barra de navegación que presenta el controlador de vista del modelo. El controlador de vista modal tiene un botón que toma los valores de un campo de texto y un datepicker y los envía al centro de notificaciones predeterminado con los valores en el diccionario userInfo. La vista de la Tabla contorller se suscribe a la notificación, pone el diccionario userInfo en un MutableArray y actualiza la tabla. Eso funciona bien.

El problema es con la collectionView. collectionView recibe la notificación y llama a un método de destino para manejar la notificación. Estoy tratando de tomar el diccionario userInfo de la notificación y agregar una nueva celda a la collectionView.

PERO...

Cuando la collectionview recibe la notificación recibo el error:

'Actualización inválida: número inválido de elementos en la sección 0. El número de elementos contenidos en una sección existente después de la actualización (1) debe ser igual al número de elementos contenidos en esa sección antes de la actualización (1), más o menos el número de elementos insertados o eliminados de esa sección (1 insertado, 0 eliminado) y más o menos el número de elementos movidos dentro o fuera de esa sección (0 movido, 0 movido).'

Aquí está el código para el collectionView:

#import "WTACollectionViewController.h"
#import "UIColor+WTAExtensions.h"
#import "WTAAppDelegate.h"
#import "WTAEntryControllerViewController.h"

@interface WTACollectionViewController () <UICollectionViewDelegateFlowLayout>
@property (strong, nonatomic) NSMutableArray *birthdays;
@end

@implementation WTACollectionViewController

-(id)initWithCollectionViewLayout:(UICollectionViewLayout *)layout{

NSLog(@"Calling init on Collection");
if(!(self = [super initWithCollectionViewLayout:layout])){
    return nil;
}

self.birthdays = [NSMutableArray array];

NSLog(@"Count of Birthdays at init %ld", (long)[self.birthdays count] );
self.title = NSLocalizedString(@"Birthday Grid", nil);
self.tabBarItem.image = [UIImage imageNamed:@"package"];
NSLog(@"cv instance getting notif %@", self);
[[NSNotificationCenter defaultCenter]
 addObserver:self
 selector:@selector(handleNotification:)
 name:@"BirthdayAdded"
 object:nil];
 return self;

}


-(void)handleNotification:(NSNotification *)notification
{
[self.birthdays addObject:[notification userInfo]];
NSLog(@"Count of birthdays when the notification is received: %ld", (long)         
[self.birthdays count]);
[self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:   
(self.birthdays.count -1) inSection:0]]];
}

- (void)viewDidLoad
{
[super viewDidLoad];

NSLog(@"Calling View Did Load on Collection");
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {

return 1;

}

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

NSLog(@"Count of birthdays in  the number of items in section: %ld", (long)  
[self.birthdays count]);
return [self.birthdays count];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView    
cellForItemAtIndexPath:(NSIndexPath *)indexPath {

NSLog(@"Calling the cell for index path method");

NSDictionary *dict = [[NSMutableDictionary alloc] init];
dict = self.birthdays[indexPath.item];

UICollectionViewCell *cell = [collectionView   
dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
NSAssert(cell != nil, @"Expected a Cell");

cell.contentView.backgroundColor = [UIColor randomColor];
return cell;

}

#define GAP (1.0f)

-(CGSize)collectionView:(UICollectionView *)collectionView layout:   
(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath   
*)indexPath {


CGFloat edgeLength = self.collectionView.frame.size.width / 4.0f - GAP;
return (CGSize) {.width = edgeLength, .height = edgeLength};
}

-(CGFloat)collectionView:(UICollectionView *)collectionView layout:   
(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:    
(NSInteger)section{

return GAP;
}

-(CGFloat)collectionView:(UICollectionView *)collectionView layout:   
(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:  
(NSInteger)section{

return GAP;
}
@end

I apreciaría mucho a cualquiera que pueda señalar cualquier cosa aquí.....

Author: Tommy Alexander, 2013-10-05

5 answers

Es un error al usar insertItemsAtIndexPaths en un UICollectionView vacío. Solo haz esto:

if (self.birthdays.count == 1) {
    [self.collectionView reloadData];
} else {
    [self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:   (self.birthdays.count -1) inSection:0]]];
}

(No puedo creer que esto todavía esté roto en iOS8.)

 53
Author: Timothy Moose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-04 04:34:14

Es un error en UICollectionView incluso en iOS 11, pero no existe en UITableView, muy fácil de reproducir: Supongamos que el siguiente código SWIFT está funcionando:

addItemInDataSource()
collectionView!.insertItems(at: [IndexPath(item: position, section: 0)])

Cámbialo a:

collectionView!.reloadData()    // <-- This new line will make UICollection crash...

addItemInDataSource()
collectionView!.insertItems(at: [IndexPath(item: position, section: 0)])

Se bloqueará...

UICollectionView perderá la pista del número original de elementos en alguna condición, simplemente agregue una línea ficticia antes de que el comando insertItems evite este tipo de bloqueo:

collectionView!.reloadData()

collectionView!.numberOfItems(inSection: 0) //<-- This code is no used, but it will let UICollectionView synchronize number of items, so it will not crash in following code.
addItemInDataSource()
collectionView!.insertItems(at: [IndexPath(item: position, section: 0)])

Espero que pueda ayudar en su situación.

 14
Author: Michael Su,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-15 03:35:42

Tuve el mismo error cuando inserté elementos en una collectionView con una sola sección.

He hecho el arreglo de Timoteo, pero no fue suficiente. De hecho, el collectionView ya había actualizado sus datos cuando intenté insertar nuevos elementos. El uso de collectionView numberOfItemsInSection resuelve el problema.

[self.collectionView performBatchUpdates:^{
        NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
        for (NSUInteger i = [self.collectionView numberOfItemsInSection:0]; i < self.elements.count ; i++)
        {
            [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
        }

        [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
    } completion:nil];
 12
Author: vmeyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-02 12:37:28

En mi caso, numberOfItemsInSection estaba siendo llamado dos veces desde self.performBatchUpdates (una vez para el número ANTES, otra para el número DESPUÉS) porque estaba tratando de insertar algo en collectionView antes de que el controlador de vista hubiera terminado de cargar.

La solución es agregar guard isViewLoaded else { return } antes de llamar a self.performBatchUpdates.

 0
Author: p-sun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-16 17:48:07

En cuanto a mí, el problema estaba relacionado con el Conjunto de índices - dónde insertar secciones. 1. He insertado Secciones 0..

Por lo tanto, la última sección todavía esperaba el número de filas de la Sección 9. Pero en la fuente de datos-que estaba en el índice 19.

CollectionView?.insertSections (IndexSet (integersIn: startIndex..

 0
Author: Naloiko Eugene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-01 11:31:18