I know there are all sorts of questions related to this, but none of the answers answered this.
Anyways, I have a UICollectionView that should be scroll forever, but I can't seem to get insertItemsAtIndexPaths: to work. It raises the error:
*** Assertion failure in -[UICollectionView _endItemAnimations], /SourceCache/UIKit/UIKit-2935.137/UICollectionView.m:3688
Here is my code:
#import "ImageSliderViewController.h"
#define ITEM_CELL_IDENTIFIER #"ItemCell"
#interface ImageSliderViewController ()
#end
#implementation ImageSliderViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupCollectionView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - UICollectionView methods
-(void)setupCollectionView {
self.items = [[NSMutableArray alloc] init];
loadingGap = 5;
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
[self.collectionView registerClass:[ImageSliderCell class] forCellWithReuseIdentifier:ITEM_CELL_IDENTIFIER];
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[flowLayout setMinimumInteritemSpacing:0.0f];
[flowLayout setMinimumLineSpacing:0.0f];
[self.collectionView setPagingEnabled:YES];
[self.collectionView setCollectionViewLayout:flowLayout];
[self loadMorePosts];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.items.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ImageSliderCell *cell = (ImageSliderCell *)[collectionView dequeueReusableCellWithReuseIdentifier:ITEM_CELL_IDENTIFIER forIndexPath:indexPath];
cell.imageTitle.text = [NSString stringWithFormat:#"%ld",(long)indexPath.item];
NSLog(#"%d : %d",indexPath.item,self.items.count-1);
if (indexPath.item >= self.items.count-1) {
[self loadMorePosts];
}
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize size = self.collectionView.frame.size;
size.height = size.height/2;
return size;
}
- (void)loadMorePosts
{
NSLog(#"Loading new items");
NSUInteger loopTill = self.items.count + loadingGap;
NSMutableArray *indexPathsToLoad = [NSMutableArray new];
while (self.items.count < loopTill) {
[indexPathsToLoad addObject:[NSIndexPath indexPathForItem:self.items.count inSection:0]];
NSLog(#"Added section %d",self.items.count);
AsyncImageView *img = [[DatabaseFetcher alloc] getPostWithID:[NSString stringWithFormat:#"%lu",(unsigned long)self.items.count]
inSection:#"features"
withFrame:CGRectMake(0, 0, self.collectionView.frame.size.width, self.collectionView.frame.size.height)];
[self.items addObject:#[img]];
};
[self.collectionView reloadItemsAtIndexPaths:indexPathsToLoad];
}
#end
Thanks in advance!
Update: I updated the code to use reloadItemsAtIndexPaths and some other improvements base on suggestions. Thanks!
[NSIndexPath indexPathForItem:self.items.count inSection:0]
Should be:
[NSIndexPath indexPathForItem:self.items.count - 1 inSection:0]
update
And you should submit all of your insertions at once by building up an NSMutableArray of index paths in your loop and inserting them at the end (as you've done and commented out). Alternatively, you can put your loop inset of a performBatchUpdates block.
thanks for all the answers.
It looks like I had a miscalculation when trying one of the solutions on the other thread. Here's my new solution that works:
-(void)addNewItems
{
NSLog(#"Loading new items");
NSMutableArray *indexPathsToLoad = [NSMutableArray new];
for (int i = 0; i < LOADING_GAP; i++) {
[indexPathsToLoad addObject:[NSIndexPath indexPathForItem:self.items.count inSection:0]];
[self.items addObject:#"Test"];
}
if (self.items.count == LOADING_GAP) {
[self.collectionView reloadData];
} else {
[self.collectionView insertItemsAtIndexPaths:indexPathsToLoad];
}
}
Thank you!
Related
how to bind data from server into collectionview which is inside uitableviewcell using hide and unhide functionality.on tap of uibutton i want to make colectionview visible and hide it again on the tap of button.What happens is when i scroll the tableview the data inside the collectionview skips from one cell to another making the collection view blank.
-(void)arrowButtonTapped:(UIButton *)donwbtn{
myob = [NSString stringWithFormat:#"%li", (long)donwbtn.tag];
NSLog(#"%#",myob);
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:0
inSection:donwbtn.tag];
OppCell* celll = [_tableView cellForRowAtIndexPath:indexPath];
celll.collView.tag=donwbtn.tag;
if ([checkcoll containsObject:myob]) {
[checkcoll removeObject:myob];
celll.collView.hidden = true;
celll.collvwhght.constant=0;
celll.colltop.constant=0;
celll.collbottom.constant=0;
}
else
{
[checkcoll addObject:myob];
celll.collView.hidden = false;
celll.collvwhght.constant=229;
celll.colltop.constant=9;
celll.collbottom.constant=8;
[celll.collView reloadData] ;
}
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
OppCell *cell = (OppCell *)[tableView
dequeueReusableCellWithIdentifier:#"OppCell"];
NSString *theIndexpath = [NSString stringWithFormat:#"%ld",
(long)indexPath.section];
if ([checkcoll containsObject:theIndexpath])
{
cell.collView.hidden = false;
cell.collvwhght.constant=229;
cell.colltop.constant=9;
cell.collbottom.constant=8;
if((![[[_Activitylistarray
objectAtIndex:indexPath.section]
valueForKey:#"OpportunityContactInfoList"]
isKindOfClass:[NSNull class]])&&([[[_Activitylistarray
objectAtIndex:indexPath.section]
valueForKey:#"OpportunityContactInfoList"]count]>0)){
if(cell.contactdetailsarray == nil) {
cell.contactdetailsarray =[[NSMutableArray alloc]init];
for(NSDictionary * contactdict in
[[_Activitylistarray objectAtIndex:indexPath.section]
valueForKey:#"OpportunityContactInfoList"] ){
[cell.contactdetailsarray addObject:contactdict];
[cell.collView reloadData];
}
}
}
}
else
{
cell.collView.hidden = true;
cell.collvwhght.constant=0;
cell.colltop.constant=0;
cell.collbottom.constant=0;
// [cell.contactdetailsarray removeAllObjects];
// [cell.collView reloadData];
}
////Code in UITableViewCell
#import "OppCell.h"
#import "OppsContactCell.h"
#implementation OppCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
[self.collView registerNib:[UINib nibWithNibName:#"OppsContactCell"
bundle:nil] forCellWithReuseIdentifier:#"OppsContactCell"];
self.collView.pagingEnabled = YES;
UICollectionViewFlowLayout * layout=[[UICollectionViewFlowLayout
alloc]init];
layout.scrollDirection=UICollectionViewScrollDirectionHorizontal;
self.collView.collectionViewLayout = layout;
self.collView.decelerationRate =
UIScrollViewDecelerationRateNormal;
// _contactdetailsarray=[NSMutableArray array];
// self.collvwhght.constant=0;
//self.collView.hidden=YES;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (UICollectionViewCell *)collectionView:(UICollectionView
*)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
OppsContactCell *cell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"OppsContactCell"
forIndexPath:indexPath];
cell.contactimgvw.image = [cell.contactimgvw.image
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[cell.contactimgvw setTintColor:[UIColor blackColor]];
cell.numberimgvw.image = [cell.numberimgvw.image
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[cell.numberimgvw setTintColor:[UIColor blackColor]];
cell.emailimgvw.image = [cell.emailimgvw.image
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[cell.emailimgvw setTintColor:[UIColor blackColor]];
if(_contactdetailsarray.count==1){
if(([[[_contactdetailsarray
objectAtIndex:0]valueForKey:#"Designation"]isEqualToString:#""])&&([[[_contactdetailsarray
objectAtIndex:0]valueForKey:#"Department"]isEqualToString:#"" ])){
cell.lbldesignation.text=#"";
}
else{
cell.lbldesignation.text=[NSString stringWithFormat:#"%#,%#",
[[_contactdetailsarray objectAtIndex:0]valueForKey:#"Designation"],
[[_contactdetailsarray objectAtIndex:0]valueForKey:#"Department"]];
}
cell.lblcontatname.text=[[_contactdetailsarray
objectAtIndex:0]valueForKey:#"ContactName"];
cell.lblcontactnumber.text=[[_contactdetailsarray
objectAtIndex:0]valueForKey:#"TelephoneNo"];
cell.lblemail.text=[[_contactdetailsarray
objectAtIndex:0]valueForKey:#"EmailAddress"];
}
else{
if(([[[_contactdetailsarray
objectAtIndex:0]valueForKey:#"Designation"]isEqualToString:#""])&& .
([[[_contactdetailsarray
objectAtIndex:0]valueForKey:#"Department"]isEqualToString:#"" ])){
cell.lbldesignation.text=#"";
}
else{
cell.lbldesignation.text=[NSString stringWithFormat:#"%#,%#",
[[_contactdetailsarray
objectAtIndex:indexPath.section]valueForKey:#"Designation"],
[[_contactdetailsarray
objectAtIndex:indexPath.section]valueForKey:#"Department"]];
}
cell.lblcontatname.text=[[_contactdetailsarray
objectAtIndex:indexPath.row]valueForKey:#"ContactName"];
cell.lblcontactnumber.text=[[_contactdetailsarray
objectAtIndex:indexPath.row]valueForKey:#"TelephoneNo"];
cell.lblemail.text=[[_contactdetailsarray
objectAtIndex:indexPath.row]valueForKey:#"EmailAddress"];
}
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(_collView.bounds.size.width
,_collView.bounds.size.height);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 5;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section{
// return 5;
if(_contactdetailsarray.count==0){
return 0;
}
else{
return _contactdetailsarray.count;
}
}
Thanks & Regards,
Roshan.k
I have UITableView, with CustomCell. In CustomCell there is UICollectionView with CustomUICollectionViewCell.
Everything is created in the way, according to UICollectionView inside CustomTableCell.
Then, let's say I have 12 rows. On the beginning I can see 6 of them.
In CustomUICollectionViewCell, labels are fine, but when I scroll down, to see other cells, CustomUICollectionViewCells labels are not as expected. They are the same as first 6 rows, which are now scrolled up.
Where should I refresh CustomUICollectionViewCells label after scroll?
Example view:
Before scrolling:
After scrolling:
However when debugging, when assigning data to cell, everything is assigned fine.
All code is in the link as it's also my question.
Seems that it's duplicating rows. I guess that it should be reloaded(?).
Added prepareForReuse method, as advised, but didn't help. Now my CustomCellClass looks:
#implementation TemperatureTableViewCell
NSNumberFormatter *decimalStyleFormatter;
- (void)awakeFromNib
{
[super awakeFromNib];
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setItemSize:CGSizeMake(50, 50)];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.collectionView = [[CollectionView alloc] initWithFrame: CGRectZero collectionViewLayout:flowLayout];
[self.collectionView registerClass:[TemperatureItemCollectionViewCell class] forCellWithReuseIdentifier:#"TemperatureItemCollectionCell"];
self.collectionView.showsHorizontalScrollIndicator = NO;
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
[self.contentView addSubview:self.collectionView];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.collection.count;
}
-(void)collectionView:(CollectionView *)collectionView willDisplayCell:(TemperatureItemCollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
TemperatureSensor *temp = self.collection[indexPath.item];
cell.temperatureValue = temp.temperature.stringValue;
cell.tempValTempCollViewCell.text = [NSString stringWithFormat:#"%#°C", cell.temperatureValue];
cell.sensorName.text = temp.sensorName;
cell.imageTempCollViewCell.image = [TemperatureImageHelper getTemperatureIcon:temp];
[self.collectionView reloadData];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TemperatureItemCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"TemperatureItemCollectionCell" forIndexPath:indexPath];
return cell;
}
- (void)setCollectionViewDelegate:(id)dataSourceDelegate indexPath:(NSIndexPath *)indexPath {
self.collectionView.delegate = dataSourceDelegate;
}
#end
And my CustomCollectionViewCell:
#implementation TemperatureItemCollectionViewCell
-(void)awakeFromNib {
[super awakeFromNib];
}
-(void)prepareForReuse {
[super prepareForReuse];
self.imageTempCollViewCell.image = nil;
self.tempValTempCollViewCell.text = nil;
self.sensorName.text = nil;
self.temperatureValue = nil;
}
#end
My TableViewController
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (_tempSensorsDictionary == nil)
return 0;
else {
NSArray *allSensorKeys = [_tempSensorsDictionary allKeys];
return [allSensorKeys count];
}
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(TemperatureTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell setCollectionViewDelegate:self indexPath:indexPath];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
NSArray *nodeNumbers = [_tempSensorsDictionary allKeys];
TemperatureTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath: indexPath];
cell.collection = [_tempSensorsDictionary objectForKey:nodeNumbers[indexPath.row]];
//NSArray *nodeNumbers = [_tempSensorsDictionary allKeys];
if([[UnitNameCache sharedUnitNameCache] getNameForId:nodeNumbers[indexPath.row]] != nil &&
![[[UnitNameCache sharedUnitNameCache] getNameForId:nodeNumbers[indexPath.row]] isEqualToString:#""]) {
NSString *name = [NSString stringWithFormat:#"%# (%#)", [[UnitNameCache sharedUnitNameCache] getNameForId:nodeNumbers[indexPath.row]], nodeNumbers[indexPath.row]];
cell.unitNameLabel.text = name;
} else {
cell.unitNameLabel.text = nodeNumbers[indexPath.row];
}
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 85.0;
}
Because UITableViewCells are reused for performance, caching can sometimes occur. In your TemperatureTableViewCell class you should override prepareForReuse and reset its properties. In your case you should clear the data you are populating it with. I would also keep prepareForReuse in TemperatureItemCollectionViewCell to avoid anymore issues.
- (void)prepareForReuse
{
[super prepareForReuse];
//Reset properties here.
self.collection = nil;
[self.collectionView reloadData];
}
I think this is what's happening. Inside of your child cell (I think it's collectionViewCell) you should reset all the values of the ui elements. Basically you are reusing one cell and you neeed to reset the values of the text or the images on it.
override func prepareForReuse() {
super.prepareForReuse()
titleLabel1.text = nil
image1.image = nil
...
}
I have a problem using custom flow layout, if my sections are empty i got a "EXC_ARTHMETIC(code=EXC_I386_DIV, subcode=0x0)".
I'm using custom FlowLayout to add custom header and custom section background(the crash is related to the background).
some code (please look at layoutAttributesForBackgroundAtSection: to see where the crash happens):
// UIViewController
-(void)loadView
{
[super loadView];
collectionViewFlowLayout *flowLayout = [[collectionViewFlowLayout alloc]init];
flowLayout.sectionInset = UIEdgeInsetsMake(35, 20, 0, 20);
[flowLayout setItemSize:cellSize];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
flowLayout.minimumInteritemSpacing = 0.0f;
self.collectionView = [[UICollectionView alloc]initWithFrame:(CGRectZero) collectionViewLayout:flowLayout];
[self.collectionView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.collectionView setBackgroundColor:[UIColor colorWithRed:246./256. green:246./256. blue:246./256. alpha:1]];
[self.view addSubview:self.collectionView];
[[self.collectionView.topAnchor constraintEqualToAnchor:self.view.topAnchor] setActive:YES];
[[self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] setActive:YES];
[[self.collectionView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor] setActive:YES];
[[self.collectionView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor] setActive:YES];
[self.collectionView registerClass:[collectionViewCell class] forCellWithReuseIdentifier:reuseCellIdentifier];
[self.collectionView registerClass:[sectionHeaderReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:reuseHeaderIdentifier];
[self.collectionView registerClass:[sectionBackgroundReusableView class]
forSupplementaryViewOfKind:KindSectionBackground
withReuseIdentifier:NSStringFromClass([sectionBackgroundReusableView class])];
[self.collectionView setShowsHorizontalScrollIndicator:NO];
[self.collectionView setShowsVerticalScrollIndicator:YES];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 6;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 0;
}
-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionV
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableview = nil;
if (kind == UICollectionElementKindSectionHeader)
{
reusableview = [collectionV dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:reuseHeaderIdentifier forIndexPath:indexPath];
NSString *sectionName = self.shelves[indexPath.section];
[(sectionHeaderReusableView*)reusableview configureWithTitle:sectionName];
}
if (kind == UICollectionElementKindSectionFooter)
{
}
if (kind == KindSectionBackground)
{
reusableview = [collectionView dequeueReusableSupplementaryViewOfKind:sectionBackground
withReuseIdentifier:NSStringFromClass([sectionBackgroundReusableView class])
forIndexPath:indexPath];
}
return reusableview;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return = KHeaderSize;
}
// FloawLayout subclass
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *attributes = [NSMutableArray arrayWithArray:[super layoutAttributesForElementsInRect:rect]];
// 1. get visible sections
NSInteger lastIndex = -1;
for(UICollectionViewLayoutAttributes * attr in attributes) {
lastIndex = attr.indexPath.section;
UICollectionViewLayoutAttributes * attr = [self layoutAttributesForBackgroundAtSection:lastIndex];
[attributes addObject:attr];
}
return attributes;
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath
{
if([kind isEqualToString:KindSectionBackground]) {
return [self layoutAttributesForBackgroundAtSection:indexPath.section];
} else {
return [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
}
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForBackgroundAtSection:(NSUInteger)section
{
NSIndexPath * indexPath =[NSIndexPath indexPathForItem:0
inSection:section];
UICollectionViewLayoutAttributes * attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:KindSectionBackground
withIndexPath:indexPath];
attr.hidden = NO;
attr.zIndex = -1;
// crash happen in the line below.
UICollectionViewLayoutAttributes * firstAttr = [selflayoutAttributesForItemAtIndexPath:indexPath];
CGRect frame;
frame.origin.x = firstAttr.frame.origin.x - self.sectionInset.left;
frame.origin.y = firstAttr.frame.origin.y - self.sectionInset.top;
frame.size.width = self.collectionView.bounds.size.width;
NSUInteger numItems = [self.collectionView numberOfItemsInSection:section];
CGFloat cellsPerLine = floorf(self.collectionView.bounds.size.width / self.itemSize.width);
NSUInteger numLines = ceilf(numItems / (float)cellsPerLine);
frame.size.height = numLines * firstAttr.size.height + (numLines-1)*self.minimumLineSpacing +
self.sectionInset.top + self.sectionInset.bottom;
attr.frame = frame;
return attr;
}
Could you please help to fix this, thank you.
Looks like layoutAttributesForItemAtIndexPath crashes when the section provided in the IndexPath is empty. This is probably a bug since it's supposed to return an optional (at least in swift). I had the same kind of issue and fixed it by checking the number of items in the section (swift example for section 1):
if dataSource.collectionView(collectionView, numberOfItemsInSection: 1) > 0 {
if let layoutAttributes = self.layoutAttributesForItem(at: IndexPath(row: 0, section: 1)) {
// update layoutAttributes or create your background attributes
}
}
One workaround would be to call collectionView.reloadData() in advance before we call any layout methods, this work for me.
I select 5 items in my collection view and i want to delete it. Please help me delete the selected items. I put one button and when i press that button all selected items are delete that i want. My button click code.
- (IBAction)btn_delete:(id)sender {
NSArray *selectedItemsIndexPaths = [self.MyCollectionView indexPathsForSelectedItems];
NSLog(#"Selected images: %#",mySelectedArray);
[self.MyCollectionView deleteItemsAtIndexPaths:selectedItemsIndexPaths];
[self.MyCollectionView reloadData];
}
First remove Objects for DataSource, then try delete cells from Collectionview
-(void)deleteCellInCollectionViewAtIndex:(int)index{
if (self.collectionView) {
[self.collectionView performBatchUpdates:^{
NSIndexPath *cellIndexPath = [NSIndexPath indexPathForRow:index inSection:0] ;
[self.collectionView deleteItemsAtIndexPaths:#[cellIndexPath]];
} completion:nil];
}
}
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#pragma Mark For Collection View Methods
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [patternImageArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"Cell";
PatternViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
NSString *myPatternString = [patternImageArray objectAtIndex:indexPath.row];
cell.ImageView.image = [UIImage imageNamed:myPatternString];
cell.ImageLabel.text = myPatternString;
ind = indexPath.row;
return cell; }
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
PatternViewCell *mySelectedCell = (PatternViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
mySelectedCell.ImageLabel.backgroundColor = [UIColor blueColor];
mySelectedCell.ImageLabel.textColor = [UIColor whiteColor];
[mySelectedArray addObject:indexPath];
i = indexPath.row; }
- (void)viewDidLoad {
[super viewDidLoad];
patternImageArray = [[NSMutableArray alloc]initWithObjects:#"Thar.jpg",#"Thar1.jpg",#"Thar2.jpg",#"Thar3.jpg",#"Thar4.jpg",#"Thar5.jpg",#"Thar6.jpg",#"Thar7.jpg",#"Thar8.jpg", nil];
self.MyCollectionView.multipleTouchEnabled = YES;
mySelectedArray = [[NSMutableArray alloc]init]; }
- (IBAction)btn_delete:(id)sender
{
[self.MyCollectionView reloadData];
NSLog(#"Selected images: %#",mySelectedArray);
}
#end
In your btn_delete: method, add this code
NSArray *selectedItemsIndexPaths = [self.MyCollectionView indexPathsForSelectedItems];
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
for (NSInteger counter = 0; counter < [mySelectedArray count]; counter++) {
NSIndexPath *indexPath = mySelectedArray[counter];
[indexSet addIndex:indexPath.row];
}
[patternImageArray removeObjectsAtIndexes:indexSet];
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:mySelectedArray];
} completion:^(BOOL finished) {
[mySelectedArray removeAllObjects];
}];
In your collectionView:didSelectItemAtIndexPath: method, you should first check if array already contains that indexpath before adding to array.
You can see it below:
if(![mySelectedArray containsObject:indexPath])
[mySelectedArray addObject:indexPath];
When I perform [self.collectionView reloadData];, only my first item is reloaded.
Even though - (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section; is called and stores, for example, two items, then (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath is only called once for the first item.
I have verified that in numberOfItemsInSection the bounds are frame's sizes are big enough to store at least three of my items.
numberOfItemsInSection:2 frame: {{0, 0}, {400, 150}} and bounds {{0, 0}, {400, 150}}
And every UICollectionViewCell is {0, 0}, {400,45} and are stored vertically, as specified in the init method.
I have read there are several bugs with UICollectionView and ios7 but none of the previously described solutions worked for my case. I have already tried with reloadItemsAtIndexPaths and reloadSections but that did not work and sometimes gave me exceptions.
I have also tired to programatically add the items with no success:
[self.collectionView insertItemsAtIndexPaths:#[[NSIndexPath indexPathForItem: (self.currentPeripherals.count -1) inSection:0]]];
This is how my UICollectionViewController looks like:
- (instancetype)init
{
UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setItemSize:CGSizeMake(400, 150)];
[aFlowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
self = [self initWithCollectionViewLayout:aFlowLayout];
if (self) {
self.view.frame=CGRectMake(0,0,400,150);
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.collectionView.backgroundView=[[UIView alloc] initWithFrame:CGRectZero];;
self.view.layer.backgroundColor=[UIColor clearColor].CGColor;
self.collectionView.backgroundColor=[UIColor clearColor];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
}
return self;
}
- (void)sharedInit {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleBTPOSHostDidUpdatePeripheralsNotification:) name:BTPOSHostDidUpdatePeripheralsNotification object:nil];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section
{
return self.currentPeripherals.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
DeviceCell *deviceCell = [cv dequeueReusableCellWithReuseIdentifier:CellID forIndexPath:indexPath];
if(!deviceCell.label)
{
[deviceCell prepareForReuse];
PeripheralTracking *peripheral=self.currentPeripherals[indexPath.item];
[deviceCell configureLabelWithPeripheralTracking:peripheral forItem:indexPath.item];
[deviceCell.contentView addSubview:deviceCell.label];
}
return deviceCell;
}
- (void)handleBTPOSHostDidUpdatePeripheralsNotification:(NSNotification *)notification
{
NSUInteger oldCount = self.currentPeripherals.count;
NSDictionary *trackedPeripherals = notification.userInfo[BTPOSHostDidUpdatePeripheralsNotificationPeripheralsKey];
[self sortPeripheralsDictionary:trackedPeripherals];
[self.collectionView reloadData];
}
And this is how my peripheral devices are sorted:
-(void)sortPeripheralsDictionary:(NSDictionary*)peripheralsDictionary
{
NSMutableArray *dictValues = [[peripheralsDictionary allValues] mutableCopy];
if(dictValues.count>1)
{
[dictValues sortUsingComparator: (NSComparator)^(PeripheralTracking *a, PeripheralTracking *b)
{
NSNumber *RSSI1 = 0;
NSNumber *RSSI2 = 0;
NSComparisonResult result = 0;
if(a.averageRSSI)
{
PeripheralTrackingRSSI doubleRSSIa = a.averageRSSI;
RSSI1 = [NSNumber numberWithDouble:doubleRSSIa];
}
if(b.averageRSSI)
{
PeripheralTrackingRSSI doubleRSSIb = b.averageRSSI;
RSSI2 = [NSNumber numberWithDouble:doubleRSSIb];
}
if(RSSI1 && RSSI2)
{
result = [RSSI2 compare:RSSI1];
}
return result;
}
];
}
self.currentPeripherals = dictValues;
}
You're setting the height of each cell to 150:
[aFlowLayout setItemSize:CGSizeMake(400, 150)]
Try changing that to 45:
[aFlowLayout setItemSize:CGSizeMake(400, 45)]
Or you can implement collectionView:layout:sizeForItemAtIndexPath: if your cell size varies from cell to cell. The reason you're only seeing one call to collectionView:cellForItemAtIndexPath: is that your collection view only has room to display one cell. If you scroll it, you should see the other one.
Try using this :
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
KKMDeviceCell *deviceCell = [cv dequeueReusableCellWithReuseIdentifier:kCellID forIndexPath:indexPath];
if(!deviceCell.label)
{
[deviceCell prepareForReuse];
[deviceCell.contentView addSubview:deviceCell.label];
}
PeripheralTracking *peripheral=self.currentPeripherals[indexPath.item];
[deviceCell configureLabelWithPeripheralTracking:peripheral forItem:indexPath.item];
return deviceCell;
}