UITableView and UICollectionView interaction ios? - ios

Please can anyone help me to achieve something like this-
(developing for iPad iOS7) In UIViewController i have UITableView & UICollectionView(like splitViewController).I just want to change image in UICollectionView when i tap on UITableViewCell.(I am using button over tableViewCell and collecting index in NSInteger).
Please help me to achieve this,I am trying from so many days,but can't achieve till now. :(
Here is the code what i have done till now.
In my viewDidLoad:
self.collectionViewImages=[[NSMutableArray alloc]initWithObjects:#"1.jpg",#"2.jpg",#"3.jpg",nil] ;
Then in CollectionViewMethods:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return [_collectionViewImages count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell"
forIndexPath:indexPath];
NSString *collectionViewImageName=[self.collectionViewImages objectAtIndex:indexPath.row];
UIImageView * collectionImage = (UIImageView*)[myCell viewWithTag:11];
collectionImage.image =[UIImage imageNamed:collectionViewImageName];
return myCell;
}
Then on ButtonClick(ofTableViewCell)--
(i am collecting tag of each button in NSInteger and using that property in numberOfItemsInSection like this,
-(void)btnTapped:(id)sender{
int tag= [(UIButton *)sender tag];
NSLog(#"Button Pressed%d",tag);
_buttonIndex=tag;
//_buttonIndex is NSInteger property
//If i add object in NSMutableArray and call reloadData my UI hangs here only.
//If I empty my NSMutableArray and add new objects in it and then call reloadData, I am getting NSRangeException.
}
And now i am using this property in numberOfItemsInSection as...
if (_buttonIndex==1){
[collectionImage setImage:[UIImage imageNamed:[_array1 objectAtIndex:indexPath.row]]];
//My _array1 has 4 objects and my collectionViewImages array has 7 objects.
}
i am getting error message as
*** Terminating app due to uncaught exception 'NSRangeException',
reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 3]'

Its crashing because you are trying to get an item from the array at index 4. But there are only indexes: 0,1,2,3.
Double check the contents of array1 on line (if it crashes here):
[collectionImage setImage:[UIImage imageNamed:[_array1 objectAtIndex:indexPath.row]]];
Otherwise find the other place where you call objectAtIndexand check if it crashes there.

Related

Inserting a New Cell Into A UICollectionView

I’m trying to add in a new cell into my collection view, only if it has more than one item already in it. I have no worked much with collection views, and research in the docs and this site had not helped solve this issue yet. So, on my cellForItemAtIndexPath method, I do a check to see if it is populated. If not, I add the cell, like so:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if (self.myArray.count != 0) {
return self.myArray.count + 1;
}
else {
return self.myArray.count;
}
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyNormalCollectionViewCellS *cells = (MyNormalCollectionViewCells *) [collectionView dequeueReusableCellWithReuseIdentifier:#"MyNormalCollectionViewCells” forIndexPath:indexPath];
cell.clipsToBounds = NO;
DataClass *data = [self.myArray objectAtIndex:indexPath.row];
[cells configureMyNormalCellsWith:data];
if (0 < self.myArray.count) {
UICollectionViewCell *deleteCell = [UICollectionViewCell new];
deleteCell.backgroundColor = [UIColor yellowColor];
NSArray *newData = [[NSArray alloc] initWithObjects:deleteCell, nil];
[self.myArray addObjectsFromArray:newData];
NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
[self.myCollectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
return deleteCell;
}
return cell;
}
For some reason, I have an assertion being thrown, stating:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid
number of items in section 0. The number of items contained in an
existing section after the update (7) must be equal to the number of
items contained in that section before the update (6), plus or minus
the number of items inserted or deleted from that section (0 inserted,
0 deleted) and plus or minus the number of items moved into or out of
that section (0 moved in, 0 moved out).'
Of course, the number usually varies, but it's always angry about that extra cell. Everything is fine up until I try and add it in. Now, being unfamiliar with collection views and after browsing related questions upon this site, I decided it was time to ask the pros.
Does anyone know how I should change this code in order to accomplish what I'm trying to do?
Don't modify data source in collectionView:cellForItemAtIndexPath:. Return different number of items in - collectionView:numberOfItemsInSection: instead:
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section {
if (self.dataArray.count > 0) {
return self.dataArray.count + 1;
}
else {
return 0;
}
}
In collectionView:cellForItemAtIndexPath: you should return your "normal" cell for "normal" item, and "extra" cell for that extra one, depending on the value of indexPath.row. For example:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row < self.dataArray.count) { // if indexPath.row is within data array bounds
// dequeue, setup and return "normal" cell
} else { // this is your "+1" cell
// dequeue, setup and return "extra" cell
}
}

iOS Populate table with mutablearray data

I have a JSON file: http://astrodeer.com.au/ingredients.php which has been been parsed in. I created two NSMutableArrays, one for the ingredients and one for the ratings for each product listed.
First of all I have populated my first table with the product name/brand:
When a user clicks on an item, it takes them to this page where I am attempting to populate the table with the ingredient names and their corresponding ratings.
This is what I have so far. I am getting an error at "numberOfRowsInSection"
"Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 4 beyond bounds [0 .. 3]'"
Ideally I am going to change the UIImage depending on the rating number using an if statement. But at the moment I am struggling to work out how to get the ingredient name to display.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section {
return [_selectedProduct.ingredientsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"ingredientsCell";
UITableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *ingLabel = (UILabel *)[myCell viewWithTag:1];
UIImage *ingRating = (UIImage *)[myCell viewWithTag:2];
ingLabel.text = _selectedProduct.ingredientsArray[indexPath.row];
return myCell;
}

-[__NSArrayM objectAtIndex:] Issue

I have a little bit problem with -[__NSArrayM objectAtIndex:]: index 6 beyond bounds [0 .. 4]' How can I show (null) If I don't have data.
Here's code
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
if ([[bookList objectAtIndex:indexPath.item]quiz_url]==[[bookList objectAtIndex:6]quiz_url]) {// This one is problem, I have `objectAtIndex:` only 0 - 5 .
// quiz_all = [[bookList objectAtIndex:indexPath.item]quiz_url];
_getQuiz6 = [[bookList objectAtIndex:6]quiz_url];
NSLog(#" test quiz6 = %#",_getQuiz6); //It's possible? Can I print `(null)` if no data.
}
...
and
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [bookList count];
}
I don't have data [[bookList objectAtIndex:6]quiz_url] on webservice.
There's plenty of ways you could go around this. One way to deal with it, is using "placeholder" objects to pad the content, for example, NSNull. Or you could modify your Book object and add a property like isLoaded.
Whatever method you choose, then (sticking with the NSNull);
- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Whatever code you have
Book *book = [bookList objectAtIndex:indexPath.item];
// NSNull is a singleton, you can safely do pointer comparison
if (book == [NSNull null])
{
// Show loading or something in the cell
cell.loadingOrSomething = YES;
// Return the cell here
return cell;
}
// book wasn't NSNull, then proceed with the rest of stuff
NSURL *url = [book quiz_url];
cell.loadingOrSomething = NO;
return cell;
}
You can use a category if you want. Somewhere in a header include this:
#interface NSArray (custom)
-(id)quizURLAtIndex:(int)index;
#end
and in a .m file you add this:
#implementation NSArray (custom)
-(id)quizURLAtIndex:(int)index{
if(index >= self.count) return nil;
else return [[self objectAtIndex:index] quiz_url];
}
#end
And from now on, whenever you want, you can call [bookList quizURLAtIndex:indexPath.item] instead of [[bookList objectAtIndex:indexPath.row] quiz_url]

How to change data of UICollectionView on button click ios?

I am trying to change UICollectionViewCell data on button click(in iPad)?
How to achieve this?
How to send different array count to numberOfItemsInSection on button Click?
In my viewDidLoad:
self.collectionViewImages=[[NSMutableArray alloc]initWithObjects:#"1.jpg",#"2.jpg",#"3.jpg",nil] ;
Then in CollectionViewMethods:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return [_collectionViewImages count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell"
forIndexPath:indexPath];
NSString *collectionViewImageName=[self.collectionViewImages objectAtIndex:indexPath.row];
UIImageView * collectionImage = (UIImageView*)[myCell viewWithTag:11];
collectionImage.image =[UIImage imageNamed:collectionViewImageName];
return myCell;
}
Then on ButtonClick--
(As there are 4-5 buttons i am collecting tag of each button in NSInteger and using that property in numberOfItemsInSection like this,
-(void)btnTapped:(id)sender{
int tag= [(UIButton *)sender tag];
NSLog(#"Button Pressed%d",tag);
_buttonIndex=tag;
//_buttonIndex is NSInteger property
//If i add object in NSMutableArray and call reloadData my UI hangs here only.
//If I empty my NSMutableArray and add new objects in it and then call reloadData, I am getting NSRangeException.
}
And now i am using this property in numberOfItemsInSection as...
if (_buttonIndex==1){
[collectionImage setImage:[UIImage imageNamed:[_array1 objectAtIndex:indexPath.row]]];
//My _array1 has 4 objects and my collectionViewImages array has 7 objects.
}
i am getting error message as
*** Terminating app due to uncaught exception 'NSRangeException',
reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 3]'
well you keep two array with a BOOL and based on taps you relload the UicollectionView first keep two array
Declare BOOL
BOOL isChangeData;
Ex :
self.collectionViewImages=[[NSMutableArray alloc]initWithObjects:#"1.jpg",#"2.jpg",#"3.jpg",nil] ;
self.collectionViewImages1=[[NSMutableArray alloc]initWithObjects:#"4.jpg",#"5.jpg",#"6.jpg",nil] ;
isChangeData = TRUE;
First time set original Data as Datasource
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
if(isChangeData){
isChangeData = false;
return [_collectionViewImages1 count];
}
else{
isChangeData = TRUE;
return [_collectionViewImages count];
}
}
in button action Make BOOL true and reload UICOllectionView
-(IBAction)changeData:(id)sender {
[self.CollectionView reloadData];
}
Hope this Works if i did any mistake pls correct me.
I believe you're just simply asking how to add/remove data from a UICollectionView through an IBAction. You would just add an object to your UICollectionView's datasource and reload. Here is an example of adding something:
-(IBAction)addObject:(id)sender {
[self.objectArray addObject:#"new object"];
[self.myCollectionView reloadData];
}

UICollectionView insertSections error - NSInvalidArgumentException reason setObjectForKey object cannot be nil UICollectionViewItemKey

I'm getting an error using a UICollectionView as follows:
2013-11-29 17:29:07.832 Clients[34200:70b]
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** setObjectForKey: object cannot be nil
(key: <_UICollectionViewItemKey: 0x8da14f0>
Type = DV ReuseID = (null) IndexPath = (null))'
And the code is as follows, where I essentially have two NSMutableArrays -- one containing all entries and the other used to reduce the entries to one section -- in this bit, I'm adding all the missing sections back in (hope that makes sense).
[self.collectionView performBatchUpdates:^{
NSString *selectedMarketSector = [[[[_marketSectors objectAtIndex:0] clients] objectAtIndex:0] clientMarketSector];
NSMutableIndexSet *insertSections = [[NSMutableIndexSet alloc] init];
for (TBMarketSector* sector in _allMarketSectors) {
if (![[[[sector clients] objectAtIndex:0] clientMarketSector ] isEqualToString:selectedMarketSector]) {
[insertSections addIndex:[_allMarketSectors indexOfObject:sector]];
}
}
_marketSectors = [self.allMarketSectors mutableCopy];
[self.collectionView insertSections:insertSections];
} completion:^(BOOL finished) {
[self setLayoutStyle:TBLayoutStacks animated:YES];
}];
The line that 'appears' to be causing the problem is the [self.collectionView insertSections:insertSections]; but I'm wondering if there is something weird going on elsewhere...
Thanks for any assistance you can provide.
Believe it or not, it seems this particular issue is actually relating to a UICollectionElementKindSectionFooter that I don't want.
I should have mentioned that this only started being a problem with iOS7 (not the first problem I've had with Collection Views after switching to iOS 7 either).
Anyway, my custom UICollectionViewFlowLayout implemented the - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath method and was returning some attributes for all supplementary views.
To fix this particular problem, I needed to add the following:
if ([kind isKindOfClass:[UICollectionElementKindSectionFooter class]])
return nil;
Thanks.
This kind of crash can be if in method
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
You try to get in dequeueReusableSupplementaryView(ofKind: - view of type elementKindSectionHeader, when kind is elementKindSectionFooter.
Check is nib register for current kind.
Thanks.

Resources