Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
169 views
in Technique[技术] by (71.8m points)

ios - Invalid update: invalid number of items on UICollectionView

I am stumped on this. Here is my scenario. In my Appdelegate, I am creating

  1. An instance of a view controller that will be presented modally to collect two pieces of data from the user
  2. A tableView controller
  3. A navigation controller that I init with the tableview controller as its rootview
    controller
  4. A collectionviewController, note that I am registering the class for the cell here as well.
  5. A UITabBarController that I add the navigation controller to as the first view and the
    collectionview to as the second view.. The TabBarCOntorller is set as the rootview of the window.

Here is the code:

 - (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
}

The tableview has a navbar button that presents the model view controller. The modal view controller has a button that takes the values from a textField and a datepicker and posts that to the default notification center with the values in the UserInfo dictionary. The tableView contorller subscribes to the notification, puts the UserInfo dictionary in a MutableArray and updates the table. That works fine.

The problem is with the CollectionVIew. The collectionVIew receives the notification and calls a target method to handle the notification. I am trying to take the UserInfo dictionary from the notification and add a new cell to the collectionView.

BUT...

When the collectionview receives the notification I get the error:

'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (1) must be equal to the number of items contained in that section before the update (1), plus or minus the number of items inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'

Here is the code for the 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 would so much appreciate anyone who can point anything out here.....

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's a bug with using insertItemsAtIndexPaths on an empty UICollectionView. Just do this:

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

(Can't believe this is still broken in iOS8.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...