Reputation: 691
I have a table view that has 3 rows in it. When one of the rows is tapped, the row height expands to show a UICollectionView with 3 cells in it.
I want the row to reduce height again when one of the collection view cells is tapped. This is what I've attempted:
//customCell.m
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
ProductViewController *productView = [[ProductViewController alloc]init];
[productView collapseRow];
}
//ProductViewController.m
@property NSIndexPath *selectedRow;
- (void)collapseRow {
menuCell *cell = (menuCell *)[self.tableView cellForRowAtIndexPath:self.selectedRow];
[self.tableView beginUpdates];
self.selectedRow = nil;
[self.tableView endUpdates];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView beginUpdates];
if ([indexPath compare:self.selectedRow] == NSOrderedSame) {
self.selectedRow = nil;
} else {
self.selectedRow = indexPath;
}
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; {
if ([indexPath compare:self.selectedRow] == NSOrderedSame)
return 105;
else
return 50;
}
Am i doing anything wrong here? I know that the table view is updating when I tap a collection view cell, but it's not checking against the currently open row and setting the height using that.
Upvotes: 0
Views: 105
Reputation: 5967
The things we have a ViewController(ProductViewController)
, containing an instance of UITableView
, the cells of table view are created in CustomCell class.
1) Since ProductViewController
has the instance of UITableView
, so using that instance ProductViewController
can call methods on UITableView
and it's cells.
2) Also, while creating table view we set the delegate and dataSource of tableview as
tableView.delegate = self;
tableView.dataSource = self;
self is nothing but the reference of the class in which table view is being created(in your case it's ProductViewController
)
you implement the tableView's delegate and dataSource method in the ProductViewController
class
and what the table view does, if it needs to call a method on your class ProductViewController
' instance it uses the reference contained in it's delegate and dataSource properties, which is nothing but the reference of ProductViewController
. So calling the method using delegate/dataSource by table view will execute the methods in ProductViewController
(if the method exists there).
3) Now as you have created a class called CustomCell
, using which you create the custom cells and add on the table view, the table can call methods on the cell's instance but if you need the other way round(cell calling the method of table view or instance of ProductViewController
, you can't do so since the cell does not know the reference/address of the ProductViewController
), so to call a method on the instance of ProductViewController
which contains the table view and cell, the cell should know the address of the ProductViewController
. And to provide the cell with the reference/ address of ProductViewController we use the concept of delegation as used by UITableView in 2 point point above.
You can use the below delegation pattern implementation to meet the requirement of point 3-
In CustomCell.h
class declare a delegate as
@protocol CustomCellDelegate;
@interface CustomCell : UITableViewCell {
//declare member variables
...
id<CustomCellDelegate> cellDelegate;
}
...
@property (nonatomic, assign) id<CustomCellDelegate> cellDelegate;
...
// method declarations
@end
@protocol CustomCellDelegate <NSObject>
- (void)collapseRow;
@end
in CustomCell.m
#import "CustomCell.h"
@implementation CustomCell
@synthesize cellDelegate = _ cellDelegate;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
// methods to create cells
// methods to create collection view and it's items
// collection view item selection handler
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// using delegate will call the method collapseRow in ProductViewController
[self. cellDelegate collapseRow];
}
@end
Also, adopt the delegate in ProductViewController.h
as
#import "CustomCell.h"
@interface ProductViewController:UIViewController < CustomCellDelegate >
and in in ProductViewController.m
when you are creating the cell as
CustomCell *cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
pass the reference of ProductViewController instance as
cell.cellDelegate = self;
Upvotes: 1
Reputation: 5967
I think the actual problem for you lies in this method
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
ProductViewController *productView = [[ProductViewController alloc]init];
[productView collapseRow];
}
In the above method you are creating a new instance of ProductViewController
using ProductViewController *productView = [[ProductViewController alloc]init];
and this will call the collapseRow, but as it's not on the instance of the previous ProductViewController
class so the row of the table contained in the previous instance will not get collapsed.
In above method you should use delegation pattern, when you are creating the cells for the collection view than during cell creation just pass the reference of ProductViewController
instance(using delegation) and when any collection view cell is selected, just use the same delegate(which contains the reference of ProductViewController instance) to call the collapseRow method on the correct class rather than allocating the new one.
Upvotes: 1
Reputation: 5967
You can also use
- (void)collapseRow
{
NSArray* indexArray = [NSArray arrayWithObjects:self.selectedRow, nil];
self.selectedRow = nil;
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationNone];
}
Upvotes: 1
Reputation: 2371
This should work:
- (void)collapseRow {
NSIndexPath *selectedRow = self.selectedRow;
[self.tableView beginUpdates];
self.selectedRow = nil;
[self.tableView reloadRowsAtIndexPaths:@[selectedRow] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
Or you could simply:
- (void)collapseRow {
self.selectedRow = nil;
[self.tableview reloadData];
}
but that would cause all the cells to be reloaded, so it's not as efficient.
Upvotes: 0