I am new to Objective-C, I have a function which accepts NSArray as a parameter now I want to store that array in a local var in my function and then populate collection view through that array, ps I'll also have to update cellForItemAtIndexPath delegate method in the same class.
This is the method in the tableView's Cell class. Here I've embedded a collectionView in the cell.
-(void)initCellWithSetsArray:(NSArray *)setsArray{
NSMutableArray *setArray = [NSMutableArray array];
}
This is where i am calling this method which accept the array in cellForRowAt tableView's delegate method.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
[cell initCellWithSetsArray :self.setsHistoryArray];
}
So i need to update the collectionView based on the array parsed in the func when called in cellForRowAtIndexPath. I hope you guys get the picture now.
You need to add a property to your cell class to hold the array:
#property (strong, nonatomic) NSArray *setsArray;
-(void) setSetsArray(NSArray *)sets {
_setsArray = sets;
[self.collectionView reloadData];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section {
return [self.setsArray count];
}
You can use this array in your cellForItemAt method in your cell class.
Also, in your cell classes prepareForReuse you should clear the existing array and reload the collection view:
-(void)prepareForReuse {
self.setsArray = nil;
[self.collectionView reloadData];
}
Then you can simply assign the property in your cellForRowAt::
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MyCellClass *cell = (MyCellClass *)[tableView dequeueReusableCellWithIdentifier:"MyCellIdentifier" forIndexPath:indexPath];
cell.setsArray = self.setsHistoryArray; // Note: This looks wrong; - you should normally use indexPath.row to get the right data for this row
return cell;
}
Try this ;
pragma mark CollectionView
-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return arrNames.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"areacell" forIndexPath:indexPath];
UILabel *lblName = (UILabel *)[cell viewWithTag:101]; // set tag in storyboard for this label
lblName.text = arrNames[indexPath.item];
return cell;
}
Related
I've got a table view and this method to find the indexPath of a subview of one of its cells...
- (NSIndexPath *)indexPathContainingView:(UIView *)view {
while (view && ![view isKindOfClass:[UITableViewCell self]]) {
view = view.superview;
}
UITableViewCell *cell = (UITableViewCell *)view;
return (cell)? [self.tableView indexPathForCell:cell] : nil;
}
I call with a subview of the topmost cell (which is visible, the table view has not been scrolled), and, with a breakpoint on the return line, I get this perplexing result in lldb...
cell looks good. The cell's table view matches my tableView (there's some intermediate UITableViewWrapperView as the direct superview). But see how indexPathForCell: returns nil? I am certain that the cell is visible.
I don't think it matters, but the subview of the cell I begin with is a UICollectionView, and I'm calling this on the collection view's datasource methods.
Any ideas?
EDIT more context...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// do stuff to setup the cell
// now reload the collection view that it contains
UICollectionView *collectionView = (UICollectionView *)[cell viewWithTag:33];
[collectionView reloadData];
return cell;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
NSIndexPath *indexPath = [self indexPathContainingView:collectionView];
return // get my model from the index path and return the count of an array it contains
// but here's the problem. index path is nil here
}
Assuming you are using storyboards and if you are willing to change the approach you are using a possible solution would be (And a cleaner solution in my opinion):
Drag an outlet of your UICollectionView inside your cell into the UITableViewCell. In your storyboard again set the delegate and dataSource of the UICollectionView to your class by dragging the outlet. Of course you will have to use a custom UITableViewCell
In your cellForRowAtIndexPath for the UITableView set the tag of the the UICollectionView to be your indexPath.row. Now in your numberOfItemsInSection you can access the UICollectionView tag property and it will contain the indexPath.row of the UITableViewCell you are trying to access and hence you can access your model.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// do stuff to setup the cell
// now reload the collection view that it contains
cell.collectionView.tag = indexPath.row;
[cell.collectionView reloadData];
return cell;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
// get my model from the index path and return the count of an array it contains
Model *model = dataArray[collectionView.tag];
return model.count;
}
I am working with the UICollectionView inside UITableViewCell. I am done with adding the contents and I am able to see the UICollectionView inside UITableViewCell.
But now I don't know how to check which cell of UICollectionView is tapped inside the which row of UITableView.
So if anybody knows how to recognize it pls help.
Thanks in advance.
#pragma mark
#pragma mark - UITableViewDelegate and UITableViewDatasource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 15;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CellForCollectionView *cell = [tableView dequeueReusableCellWithIdentifier:#"CellForCollectionView"];
if (cell == nil) {
cell = [[CellForCollectionView alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CellForCollectionView"];
}
cell.categoryCollectionView.delegate = self;
cell.categoryCollectionView.dataSource = self;
[cell.categoryCollectionView registerNib:[UINib nibWithNibName:#"CollectionCellForCategory" bundle:nil] forCellWithReuseIdentifier:#"CollectionCellForCategory"];
cell.lblCategoryName.text = [NSString stringWithFormat:#" Category %d",indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
#pragma mark
#pragma mark - UIcollectionViewDelegate and UIcollectionViewDatasource
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 15;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionCellForCategory *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionCellForCategory" forIndexPath:indexPath];
cell.imagCategory.layer.borderColor = [[UIColor blackColor]CGColor];
cell.imagCategory.layer.borderWidth = 1.0f;
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"%ld",(long)indexPath.row);
NSLog(#"%ld",(long)indexPath.section);
}
You can subclass UICollectionView and add a variable to track the indexPath of the tableViewCell
In your tableViewCell change the collectionView type to your custom collectionView
Set the variable in "cellForRowAtIndexPath" method of UITableViewDatasource
Custom collectionView:
#interface IndexedCollectionView : UICollectionView
#property (nonatomic, strong) NSIndexPath* parentIndexpath;
#end
Your custom tableViewCell (approx.)
#interface CellForCollectionView : UITableViewCell
#property (nonatomic, weak) IBOutlet IndexedCollectionView* categoryCollectionView;
#end
UITableViewDataSource method implementation:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CellForCollectionView *cell = [tableView dequeueReusableCellWithIdentifier:#"CellForCollectionView"];
if (cell == nil) {
cell = [[CellForCollectionView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CellForCollectionView"];
}
cell.categoryCollectionView.delegate = self;
cell.categoryCollectionView.dataSource = self;
[cell.categoryCollectionView registerNib:[UINib nibWithNibName:#"CollectionCellForCategory" bundle:nil] forCellWithReuseIdentifier:#"CollectionCellForCategory"];
cell.lblCategoryName.text = [NSString stringWithFormat:#" Category %d",indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.categoryCollectionView.parentIndexpath = indexPath;
return cell;
}
A bit off-topic, but in case someone has the same problem as myself having collection view cells touch inside tableview work and reached this question looking for an answer :
It does work with all the default settings. So, make sure you don't have another touch gesture in your view controller (such as a tap gesture like me) blocking the touch from reaching the collection view cell.
If you have such a gesture recognizer, and you want to keep it, you need to set its "cancelTouchesInView" property to false. And that's all. You don't need to implement the IUGestureRecognizerDelegate functions to have it work (although that may be different if you have multiple gesture recognizer and not just one).
It's simple. Add tag to each cell of UITableView in "cellForRowAtIndexPath:" method i.e
cell.tag = indexPath.row
same goes for the CollectionViewCell inside the UICollectionView
Let say you have a tableView with 2 rows and which is having 2 collectionViews respectively.
row1 of UITableView will have tag 0 and other one will have tag 1.
Now when the user clicks on the collectionViewCell inside the collectionView which is inside a UITableViewCell
Now, if you click the first collectionViewCell of the collectionView inside the first UITableViewCell
You will get the cell tag as 0 and as you already know that self.tag i.e is the tableViewCell is 0
Now, if you click the first collectionViewCell of the collectionView inside the 2nd UITableViewCell
You will get the cell tag as 0 and as you already know that self.tag i.e is the tableViewCell is 1
I think this was what you needed.Do let me know if it's clear to you.. Thanks :)
I am making a tableView inside custom 'UICollectionViewCell' and inside my ViewController I have an array containing data to be displayed in TableView at each row.
Therefore, I want to pass the data of this array to custom cell (containing tableview delegates methods).
I am doing like this but its not helping.
Inside "GroupCollectionViewCell.m"
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *groupTableIdentifier = #"DeptGroupTable";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:groupTableIdentifier];
if (cell == nil) {
}
RoadmapViewController *vc = [[RoadmapViewController alloc] init];
cell.textLabel.text =[vc.grouplist objectAtIndex:indexPath.row];
return cell;
}
And inside "RoadViewController.m"
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
GroupCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[GroupCollectionViewCell alloc] init];
// [cell.groupData addObjectsFromArray:_grouplist];
//:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
Note - groupList if the array which I want to pass and groupData is a blank array inside custom cell.
Create one MutableArray object inside your CollectionViewCell and one method like this
#property (strong, nonatomic) NSMutableArray *arrObj;
-(void)loadTableData(NSMutableArray*)arr {
self.arrObj = arr;
[self.tableView reloadData];
//Now used this arrObj in your delegate and datasource method
}
After that call this function from cellForItemAtIndexPath like this way
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
GroupCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[GroupCollectionViewCell alloc] init];
// [cell.groupData addObjectsFromArray:_grouplist];
//:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[cell loadTableData:arr];
return cell;
}
Hope this will help you.
If you use alloc init to create RoadmapViewController and get grouplist from that, it is obviously that your vc.grouplist will return nil.
Remove these two lines:
RoadmapViewController *vc = [[RoadmapViewController alloc] init];
cell.textLabel.text =[vc.grouplist objectAtIndex:indexPath.row];
And do this:
cell.textLabel.text =[_groupData objectAtIndex:indexPath.row];
And in "RoadViewController.m" add this method:
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(GroupCollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
cell.groupData = _groupList;
[collectionView reloadData];
}
I have added tableview on top of UIViewController and I have also implemented the UITableViewDataSource and UITableViewDelegate methods
For some reason, I am not getting the value out of didSelectRowAtIndexPath. I get the expected value of indexPath.row but the selectedCell.textLabel.text returns nil.
I am not able to figure out what may be the problem. I am using the dynamic table.
//Array of multiple objects is filled through the delegated arrays and the arrays are properly filled.
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return _arrayForMultipleObjects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
array = [[NSMutableArray alloc]init];
// Configure the cell...
_singleSelectionLabel= (UILabel *) [cell viewWithTag:2];
_singleSelectionLabel.text=[self.arrayForMultipleObjects objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *valu ;
NSLog(#"%i count",indexPath.row);
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
NSLog(#"%#",cellText);
//Here cellText is null
if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryNone)
{ [tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;
valu = cellText;
}
NSLog(#"%#",valu);
}
If you are using storyboard then the default cell style of table cells is Custom which gives you a blank cell where you can add other types of controls to it.
If you dragged a label onto the cell and changed its text, then you are likely using a Custom style of UITableViewCell.
The property textLabel is only available on cells of types other than Custom, such as Basic, or Detailed.
Please double check if this is the case for you.
Edit: As ready suggested you can fetch the text like this:
self.arrayForMultipleObjects[indexPath.row]
I have a UICollectionView whose all cells contains a UITableView. My UICollectionView delegate / datasource methods are handled by a view controller (let's say TTCollectionViewController), and tableViews are handled directly by collection view cells (TTCollectionViewCell).
In order to change some label colors, I need to keep track of each selected rows on my tableViews so i did something like that :
//
// TTCollectionViewCell.m
//
[...]
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// keep track of selected drugs
if (![self.selectedDrugIndexPaths containsObject:indexPath])
{
[self.selectedDrugIndexPaths addObject:indexPath];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TTTableViewCell *contentCell = [tableView dequeueReusableCellWithIdentifier:#"test"];
if (contentCell == nil)
contentCell = [[TTTableViewCell alloc] init];
[...]
// test
if ([self.selectedDrugIndexPaths containsObject:indexPath]) {
contentCell.drugLabel.textColor = [UIColor grayColor];
} else {
contentCell.drugLabel.textColor = [UIColor blackColor];
}
}
[...]
But here's the thing : with the dequeue reusable thing, my collectionView is messing up all my tracks (on scrolling, selected rows on table 1 become selected on table 3 for example).
I know it's a bad idea to don't use dequeuereusable (i don't even know if it's possible to not use it), but is there something similar that i can do ?
Do anyone have already implement this kind of case ?
Thx in advance.
EDIT :
Here's my cellForRow... methods of my collectionView as you asked for :
///
/// TTCollectionController.m
///
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
TTCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.data = [self.data objectAtIndex:indexPath.row];
return cell;
}