uicollectionview cells not showed after updates as per requirement after reload data - ios

i have a products catalogue that is shown in collection view, User may change the category or sub category for new products and they are populating in collection view perfectly.
now user may choose the quantity of any specific product in numbers as 1, 2, 3 or more to buy.
for this i set UIButton action in collection view cell to take users input in UITextfield inside Cell.
all works perfectly, actually i have different number of products as per Category wise, and most of the time i have to scroll to see products in collection view.
when ever the quantity of any product or more than one products are set they are just perfect as i want in each Cell.
** Updated Problem:**
if i change the category or sub category to see other products in collection view now this condition never satisfies in both uibutton action method and in cellForItemAtIndexPath method.
here is problem:
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{} // this condition is creating problem on category or sub category change.
that how i am working:
Custom CollectionView class
#interface MyCell : UICollectionViewCell
#property (retain, nonatomic) UIButton *btn1;
#property (retain, nonatomic) UITextField *txt1;
#end
implementation
#implementation MyCell
#synthesize btn1, txt1;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
CGRect btn1Rect = CGRectMake(190, 230 , 35 , 35);
btn1 = [[UIButton alloc] initWithFrame:btn1Rect];
btn1.tag=11;
[btn1 setBackgroundImage:[UIImage imageNamed:#"BtnPlus.png"] forState:UIControlStateNormal];
//btn1.layer.borderWidth = 1.0f;
CGRect txt1Rect = CGRectMake(143, 230 , 45 , 30);
txt1 = [[UITextField alloc] initWithFrame:txt1Rect];
txt1.tag=13;
txt1.font=[UIFont fontWithName:#"Superclarendon" size:18];
txt1.textAlignment = NSTextAlignmentCenter;
txt1.textColor = [UIColor blueColor];
//txt1.layer.borderWidth = 1.0f;
}
return self;
}
in ViewController implementation
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CellID" forIndexPath:indexPath];
[[cell btn1] addTarget:self action:#selector( btnPlus:event:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:cell.btn1];
cell.txt1.text = #"0";
for (i = 0; i < [updatedCodes count]; i++)
{
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
}
[cell.contentView addSubview:cell.txt1];
return cell;
}
the UIButton Action Method is
-(void)btnPlus:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:myCollection];
btnIndex = [myCollection indexPathForItemAtPoint: currentTouchPosition];
MyCell *cell = (MyCell*)[myCollection cellForItemAtIndexPath:btnIndex];
NSString *newCode = [code objectAtIndex:btnIndex.row];
NSString *newQty = cell.txt1.text;
if ([updatedCodes containsObject:newCode])
{
for (i = 0; i < [updatedCodes count]; i ++)
{
if ([updatedCodes objectAtIndex:i] == newCode)
{
qnty = [newQty integerValue];
qnty = qnty + 1;
cell.txt1.text = [NSString stringWithFormat:#"%d", qnty];
newQty = cell.txt1.text;
[updatedQty replaceObjectAtIndex:i withObject:newQty];
}
}
if (![indexPaths containsObject:btnIndex])
{
[indexPaths addObject:btnIndex];
}
}
else
{
[updatedCodes addObject:newCode];
qnty = [newQty integerValue];
qnty = qnty + 1;
cell.txt1.text = [NSString stringWithFormat:#"%d", qnty];
newQty = cell.txt1.text;
[updatedQty addObject:newQty];
if (![indexPaths containsObject:btnIndex])
{
[indexPaths addObject:btnIndex];
}
}
[myCollection reloadItemsAtIndexPaths:indexPaths];
}
NOTE:
Code, indexPaths ,updatedCodes and updatedQty are NSMutableArrays
Any suggestion / Help about this problem will be greatly appreciated.
waiting for swift help….. :(

The problem is here
if ([indexPaths count] > 0)
{
for (i = 0; i < [updatedCodes count]; i++)
{
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
}
}
As when this array has records it will go in within this IF statement and will skip the else statement where you are actually setting your cell.txt1.text = #"0". Easiest fix would be to put next line of code just before the for loop
cell.txt1.text = #"0";
Like this
if ([indexPaths count] > 0)
{
cell.txt1.text = #"0";
for (i = 0; i < [updatedCodes count]; i++)
{
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
}
}

answering your own question may be not good but i figured out my problem and resolve it myself
so posting here the issue for some one else who is suffering in same problem….
this is all i change in my code
in view controller implemention
if ([code objectAtIndex:indexPath.row] == [updatedCodes objectAtIndex:i])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
with this
if ([[code objectAtIndex:indexPath.row] isEqualToString:[updatedCodes objectAtIndex:i]])
{
cell.txt1.text = [updatedQty objectAtIndex:i];
}
and same change in Button Action method as
if ([newCode isEqualToString:[updatedCodes objectAtIndex:i]])
{
// do something
}

Related

Selecting multiple cells in a UICollectionView

What I'm trying to achieve is something like the video length editor of, say, WhatsApp: you can modify the length by dragging the beginning or the ending of the reel.
I need to be able to select the cells by dragging a finger trough the collection view, then if you touch the last or the first selected cell and drag again, the selection should adjust.
EDIT:
I've been able to do almost all I needed, but there's still something that's not right.
I ended up using a long press gesture recognizer that's triggering the "editing mode" after 0.3 seconds.
The problems are: sometimes only the first time entering the "editing mode" you can't really edit anything, so you'll have to release the long press and start again.
I had to lock the editing direction because I was not able to make it work both ways. That means that if you enter the editing mode and start moving left, for example, you can't move back to the right.
This is my code so far:
ReservationViewController.m
#import "ReservationViewController.h"
#import "RoomTest.h"
#interface ReservationCollectionViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *timeLbl;
#property (weak, nonatomic) IBOutlet UIView *upLine;
#property (weak, nonatomic) IBOutlet UIView *leftLine;
#property (weak, nonatomic) IBOutlet UIView *bottomLine;
#property (weak, nonatomic) IBOutlet UIView *rightLine;
#end
#implementation ReservationCollectionViewCell
#end
#interface ReservationViewController ()
#property (strong, nonatomic) NSMutableArray *cellsArray;
#property (strong, nonatomic) NSMutableArray *selectedIndexes;
#property (strong, nonatomic) NSArray *orderedIndexes;
#property (strong, nonatomic) NSIndexPath *startPath;
#property (nonatomic) BOOL dirLockAddSelection;
#property (nonatomic) BOOL dirLockDelSelection;
#property (weak, nonatomic) IBOutlet UILabel *resultLbl;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSString *selectedRoom;
#property (weak, nonatomic) IBOutlet UILabel *roomLbl;
#property (nonatomic) BOOL gestureActivated;
#end
#implementation ReservationViewController
- (void)viewDidLoad {
[super viewDidLoad];
_cellsArray = [[NSMutableArray alloc] initWithCapacity:96];
_selectedIndexes = [[NSMutableArray alloc] init];
_startPath = [[NSIndexPath alloc] init];
_selectedRoom = [NSString new];
// Test data
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<5; i++) {
RoomTest *temp = [[RoomTest alloc] init];
temp.start = #"05:00";
temp.end = #"08:30";
temp.room = [NSString stringWithFormat:#"%d00",i+1];
[tempArray addObject:temp];
}
// End of test data
_rooms = [[NSArray alloc] initWithArray:tempArray];
NSDateComponents *components= [[NSDateComponents alloc] init];
[components setSecond:00];
[components setMinute:00];
[components setHour:00];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *zeroDate = [calendar dateFromComponents:components];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm"];
NSString *test = [df stringFromDate:zeroDate];
for (int i=0; i<1440; i+=15) {
[_cellsArray addObject:test];
[components setMinute:15];
zeroDate = [calendar dateByAddingComponents:components toDate:zeroDate options:0];
test = [df stringFromDate:zeroDate];
}
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] init];
[longPressRecognizer addTarget:self action:#selector(didLongPress:)];
longPressRecognizer.minimumPressDuration = 0.3;
[_collectionView addGestureRecognizer: longPressRecognizer];
}
- (void)didLongPress: (UILongPressGestureRecognizer *)gesture {
if (UIGestureRecognizerStateBegan == gesture.state) {
_gestureActivated = YES;
CGPoint location = [gesture locationInView:_collectionView];
_startPath = [_collectionView indexPathForItemAtPoint:location];
NSLog(#"Start: %ld", (long)_startPath.row);
} else if (UIGestureRecognizerStateChanged == gesture.state) {
CGPoint location = [gesture locationInView:_collectionView];
NSIndexPath *indexPath = [_collectionView indexPathForItemAtPoint:location];
NSLog(#"Changed: %ld", (long)indexPath.row);
if ([_orderedIndexes count] == 0 && ![_selectedIndexes containsObject:#(indexPath.row)]) {
[_selectedIndexes addObject:#(indexPath.row)];
[_collectionView reloadData];
} else {
NSNumber *first = (NSNumber*)[_orderedIndexes firstObject];
NSNumber *last = (NSNumber*)[_orderedIndexes lastObject];
if ((_startPath.row == [first intValue] && indexPath.row < _startPath.row) || (_startPath.row == [last intValue] && indexPath.row > _startPath.row)) {
if (![_selectedIndexes containsObject:#(indexPath.row)] && indexPath.row != _startPath.row && !_dirLockDelSelection) {
[_selectedIndexes addObject:#(indexPath.row)];
_dirLockAddSelection = YES;
}
} else if ((_startPath.row == [first intValue] && indexPath.row > _startPath.row)) {
if ([_selectedIndexes containsObject:#(indexPath.row-1)] && [_selectedIndexes count] > 0 && !_dirLockAddSelection) {
[_selectedIndexes removeObject:#(indexPath.row-1)];
_dirLockDelSelection = YES;
}
} else if ((_startPath.row == [last intValue] && indexPath.row < _startPath.row)) {
if ([_selectedIndexes containsObject:#(indexPath.row+1)] && [_selectedIndexes count] > 0 && !_dirLockAddSelection) {
[_selectedIndexes removeObject:#(indexPath.row+1)];
_dirLockDelSelection = YES;
}
}
NSArray *visibleCells = [_collectionView indexPathsForVisibleItems];
NSSortDescriptor *rowDescriptor = [[NSSortDescriptor alloc] initWithKey:#"row" ascending:YES];
NSArray *sortedRows = [visibleCells sortedArrayUsingDescriptors:#[rowDescriptor]];
if (indexPath == [sortedRows lastObject]) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0];
[_collectionView scrollToItemAtIndexPath:newPath atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
} else if (indexPath == [sortedRows firstObject]) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:0];
[_collectionView scrollToItemAtIndexPath:newPath atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}
NSIndexPath *temp = [sortedRows lastObject];
NSLog(#"Current Row: %ld - Visible Cell Row: %ld", (long)indexPath.row, (long)temp.row);
[_collectionView reloadData];
}
} else if(UIGestureRecognizerStateEnded == gesture.state) {
CGPoint location = [gesture locationInView:_collectionView];
NSIndexPath *indexPath = [_collectionView indexPathForItemAtPoint:location];
NSLog(#"End: %ld", (long)indexPath.row);
_orderedIndexes = [_selectedIndexes sortedArrayUsingSelector:#selector(compare:)];
_dirLockAddSelection = NO;
_dirLockDelSelection = NO;
_gestureActivated = NO;
[_collectionView reloadData];
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 100.0;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_rooms count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:#"tableCellReserve" forIndexPath:indexPath];
RoomTest *room = _rooms[indexPath.row];
cell.textLabel.text = room.room;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
RoomTest *selRoom = _rooms[indexPath.row];
_selectedRoom = selRoom.room;
for (RoomTest *test in _rooms) {
if ([_selectedRoom isEqualToString:test.room]) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[_cellsArray indexOfObject:test.start] inSection:0];
int start = [_cellsArray indexOfObject:test.start];
int end = [_cellsArray indexOfObject:test.end];
_selectedIndexes = [[NSMutableArray alloc] init];
for (NSString *time in _cellsArray) {
if ([_cellsArray indexOfObject:time] >= start && [_cellsArray indexOfObject:time] <= end) {
[_selectedIndexes addObject:#([_cellsArray indexOfObject:time])];
}
}
[_collectionView reloadData];
[_collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}
}
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 96;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
ReservationCollectionViewCell *cell = [_collectionView dequeueReusableCellWithReuseIdentifier:#"reserveCell" forIndexPath:indexPath];
cell.upLine.hidden = YES;
cell.leftLine.hidden = YES;
cell.bottomLine.hidden = YES;
cell.rightLine.hidden = YES;
if ((indexPath.row % 2) == 0) {
cell.timeLbl.text = _cellsArray[indexPath.row];
} else {
cell.timeLbl.text = #"";
}
int first = [[_selectedIndexes valueForKeyPath:#"#min.intValue"] intValue];
int last = [[_selectedIndexes valueForKeyPath:#"#max.intValue"] intValue];
if ([_selectedIndexes count] > 0) {
if (indexPath.row == first && indexPath.row == last) {
cell.leftLine.layer.borderColor = [UIColor redColor].CGColor;
cell.leftLine.layer.borderWidth = 2.0;
cell.leftLine.hidden = NO;
cell.upLine.hidden = NO;
cell.bottomLine.hidden = NO;
cell.rightLine.hidden = NO;
cell.rightLine.layer.borderColor = [UIColor redColor].CGColor;
cell.rightLine.layer.borderWidth = 2.0;
} else if (first == indexPath.row) {
cell.leftLine.layer.borderColor = [UIColor redColor].CGColor;
cell.leftLine.layer.borderWidth = 2.0;
cell.leftLine.hidden = NO;
cell.upLine.hidden = NO;
cell.bottomLine.hidden = NO;
cell.rightLine.hidden = YES;
} else if (last == indexPath.row){
cell.leftLine.hidden = YES;
cell.upLine.hidden = NO;
cell.bottomLine.hidden = NO;
cell.rightLine.hidden = NO;
cell.rightLine.layer.borderColor = [UIColor redColor].CGColor;
cell.rightLine.layer.borderWidth = 2.0;
} else if ([_selectedIndexes containsObject:#(indexPath.row)]) {
cell.leftLine.hidden = YES;
cell.rightLine.hidden = YES;
cell.upLine.hidden = NO;
cell.bottomLine.hidden = NO;
}
if (_gestureActivated && (first == indexPath.row || last == indexPath.row)) {
cell.leftLine.layer.borderWidth = 4.0;
cell.rightLine.layer.borderWidth = 4.0;
} else {
cell.leftLine.layer.borderWidth = 2.0;
cell.rightLine.layer.borderWidth = 2.0;
}
}
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(50.0, _collectionView.bounds.size.height);
}
-(IBAction)onOKBtnPressed:(id)sender {
if ([_selectedIndexes count] > 0) {
// if (_delegate != nil) {
int first = [[_selectedIndexes valueForKeyPath:#"#min.intValue"] intValue];
int last = [[_selectedIndexes valueForKeyPath:#"#max.intValue"] intValue];
// NSArray *temp = [[NSArray alloc] initWithObjects:_cellsArray[first], _cellsArray[last], nil];
// [_delegate onSelectionEnded:temp];
_resultLbl.text = [NSString stringWithFormat:#"Selected %# from %# to %#", _selectedRoom, _cellsArray[first], _cellsArray[last]];
// }
}
}
#end
The view controller contains a vertical table view on the left that's showing the rooms' numbers, and on its right there's the collection view showing the timeline.
When a cell is selected, I'm just drawing some lines in the cell to show that is selected.
Any help to solve my problems is very welcome, and so will be any suggestions about the code I wrote so far.
I've solved almost all the problems I had. The only thing I don't like now is the "auto scroll" of the collection view when the user is selecting cells and drags the finger on the edge of the screen.
The collection view is supposed to scroll, while the user keeps he's finger on the screen, and the selection has to continue.
As I got it now it works, but the scrolling is not smooth and I don't like it at all.
This is the modified -didLongPress method:
- (void)didLongPress: (UILongPressGestureRecognizer *)gesture {
if (UIGestureRecognizerStateBegan == gesture.state) {
_gestureActivated = YES;
CGPoint location = [gesture locationInView:_collectionView];
_startPath = [_collectionView indexPathForItemAtPoint:location];
_lastIndex = _startPath;
_orderedIndexes = [_selectedIndexes sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"Start: %ld", (long)_startPath.row);
} else if (UIGestureRecognizerStateChanged == gesture.state) {
CGPoint location = [gesture locationInView:_collectionView];
NSIndexPath *indexPath = [_collectionView indexPathForItemAtPoint:location];
NSLog(#"Changed: %ld", (long)indexPath.row);
if ([_orderedIndexes count] == 0 && ![_selectedIndexes containsObject:#(indexPath.row)]) {
[_selectedIndexes addObject:#(indexPath.row)];
} else {
NSNumber *first = (NSNumber*)[_orderedIndexes firstObject];
NSNumber *last = (NSNumber*)[_orderedIndexes lastObject];
if (_startPath.row == [last intValue] || _startPath.row == [first intValue]) {
if ([_selectedIndexes count] == 0) {
[_selectedIndexes addObject:#(indexPath.row)];
}
if ((_lastIndex.row - indexPath.row) == 1 || (_lastIndex.row - indexPath.row) == -1) {
if (![_selectedIndexes containsObject:#(indexPath.row)]) {
[_selectedIndexes addObject:#(indexPath.row)];
} else if ([_selectedIndexes containsObject:#(indexPath.row)] && [_selectedIndexes containsObject:#(_lastIndex.row)]) {
[_selectedIndexes removeObject:#(_lastIndex.row)];
}
}
_lastIndex = indexPath;
//Auto-scroll collectionview if touch is on the first or last visible cells
NSArray *visibleCells = [_collectionView indexPathsForVisibleItems];
NSSortDescriptor *rowDescriptor = [[NSSortDescriptor alloc] initWithKey:#"row" ascending:YES];
NSArray *sortedRows = [visibleCells sortedArrayUsingDescriptors:#[rowDescriptor]];
if (indexPath == [sortedRows lastObject]) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0];
if (newPath.row <= [_cellsArray count]-1) {
[_collectionView scrollToItemAtIndexPath:newPath atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
}
} else if (indexPath == [sortedRows firstObject]) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:0];
if (newPath.row >= 0) {
[_collectionView scrollToItemAtIndexPath:newPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}
}
}
}
} else if(UIGestureRecognizerStateEnded == gesture.state) {
CGPoint location = [gesture locationInView:_collectionView];
NSIndexPath *indexPath = [_collectionView indexPathForItemAtPoint:location];
NSLog(#"End: %ld", (long)indexPath.row);
_orderedIndexes = [_selectedIndexes sortedArrayUsingSelector:#selector(compare:)];
_gestureActivated = NO;
}
[_collectionView reloadData];
}

How to apply rating stars into UITableViewCells

Hi I want apply rating stars into UITableViewCell.
Is any sample available for it?
I tried some code but it's not working.
Please help.
My Code:
#import "ViewController.h"
#import "starsInCell.h"
#interface ViewController ()
{
starsInCell *cell;
NSMutableArray *mainArray,*BtnsArray;
}
#end
#implementation ViewController
#synthesize TableList;
- (void)viewDidLoad {
[super viewDidLoad];
TableList.delegate = self;
TableList.dataSource = self;
mainArray = [[NSMutableArray alloc] initWithObjects:#"",#"", #"",#"",#"",nil];
BtnsArray = [[NSMutableArray alloc] initWithObjects:#"false",#"false",#"false",#"false",#"false", nil];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return mainArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"Cell";
cell =[TableList dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"starsInCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
//cell.textLabel.text = #"1";
//cell.backgroundColor = [UIColor orangeColor];
NSString *btn1str = [BtnsArray objectAtIndex:0];
NSString *btn2str = [BtnsArray objectAtIndex:1];
NSString *btn3str = [BtnsArray objectAtIndex:2];
NSString *btn4str = [BtnsArray objectAtIndex:3];
NSString *btn5str = [BtnsArray objectAtIndex:4];
[self setImages:btn1str :cell.btn1];
[self setImages:btn2str :cell.btn2];
[self setImages:btn3str :cell.btn3];
[self setImages:btn4str :cell.btn4];
[self setImages:btn5str :cell.btn5];
[cell.btn1 addTarget:self action:#selector(btn1Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn2 addTarget:self action:#selector(btn2Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn3 addTarget:self action:#selector(btn3Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn4 addTarget:self action:#selector(btn4Clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.btn5 addTarget:self action:#selector(btn5Clicked:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80;
}
-(void)btn1Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn2Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn3Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn4Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)btn5Clicked:(UIButton*)button{
NSLog(#"Action performed");
//NSLog(#"button position is =====> %d",mainArray.count);
CGPoint buttonPosition = [button convertPoint:CGPointZero toView:TableList];
NSIndexPath *indexPath = [TableList indexPathForRowAtPoint:buttonPosition];
int buttonValue = button.tag;
NSString *string1 = [BtnsArray objectAtIndex:buttonValue];
for (int i=0; i < mainArray.count; i++) {
if (indexPath.row == i){
if ([string1 isEqualToString:#"false"]){
[BtnsArray replaceObjectAtIndex:buttonValue withObject:#"true"];
}else{
for (int i = buttonValue+1; i < BtnsArray.count; i++){
[BtnsArray replaceObjectAtIndex:i withObject:#"false"];
}
}
break;
}
}
[TableList reloadData];
}
-(void)setImages:(NSString*)string1 :(UIButton*)button1{
if ([string1 isEqualToString:#"false"]){
[button1 setImage:[UIImage imageNamed:#"Star1.png"] forState:UIControlStateNormal];
}else{
[button1 setImage:[UIImage imageNamed:#"Star2.png"] forState:UIControlStateNormal];
}
}
#end
I would recommend you to do this yourself only if you are new in development and you want to build your logic, so instead of using any readymade library you can follow below steps.
First add 5 buttons on your cell and set bordered star image for each buttons default state and then change buttons state to Selected and set filled star image. (Do same for 5 buttons). After you done this make sure you change all buttons state to Default.
Add action buttonStarRatingsClicked for all 5 buttons.
Create outlet collection buttonCollectionStarRatings for each button in starsInCell class.
Add below method in your viewController which is showing tableView having stars on each cell.
- (IBAction)buttonStarRatingsClicked:(id)sender {
UIButton *buttonStarRatings = (UIButton*) sender;
//Here you will need to get cell to access buttonCollectionStarRatings
UITableViewCell *cell = (UITableViewCell*) [[buttonStarRatings superView] superView];
//Check is clicked button is selected
if ([buttonStarRatings isSelected]) {
if (buttonStarRatings.tag == 0) { //Check is clicked button is first button
//Check if Next button of selected button is selected
if ([cell.buttonCollectionStarRatings[buttonStarRatings.tag+1] isSelected]) {
#autoreleasepool {
for (int i = (int)buttonStarRatings.tag+1; i < [cell.buttonCollectionStarRatings count]; i++) {
UIButton *buttonStarRating = cell.buttonCollectionStarRatings[i];
[buttonStarRating setSelected:NO];
}
}
} else {
//If selected button is first button and is selected then do not take any action as atlease one star should be selected.
}
} else if (buttonStarRatings.tag == 4) { //Check is clicked button is last button
[buttonStarRatings setSelected:NO];
} else { //Selected button is one of the button between first and last
//Check if Next button of selected button is selected
if ([cell.buttonCollectionStarRatings[buttonStarRatings.tag+1] isSelected]) {
#autoreleasepool {
for (int i = (int)buttonStarRatings.tag; i < [cell.buttonCollectionStarRatings count]; i++) {
UIButton *buttonStarRating = cell.buttonCollectionStarRatings[i];
[buttonStarRating setSelected:NO];
}
}
} else {
[buttonStarRatings setSelected:NO];
}
}
} else {
if (buttonStarRatings.tag == 0) { //Check is clicked button is first button
[buttonStarRatings setSelected:YES];
} else if (buttonStarRatings.tag == 4) { //Check is clicked button is last button
#autoreleasepool {
for (UIButton *buttonStarRating in cell.buttonCollectionStarRatings) {
[buttonStarRating setSelected:YES];
}
}
} else { //Selected button is one of the button between first and last
#autoreleasepool {
for (int i = 0; i <= (int)buttonStarRatings.tag; i++) {
UIButton *buttonStarRating = cell.buttonCollectionStarRatings[i];
[buttonStarRating setSelected:YES];
}
}
}
}
}
The above part will allow you to select star ratings on each cell, next step is managing the selected stars on each cell while scrolling the table.

tableview crash with '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

I got a problem.
I have a TableView in my ViewController. This TableView has 5 rows with textFields. The height of each row is 156 pixels. also I have button "Save", and after click I want save all my data to NSMutableArray in following method, but in result I got an error.
What should I do in this way?
thank you
my method example:
- (void) saveDataToArray
{
carCellTableViewCell * cell;
_carNewPrices = [[NSMutableArray alloc] init];
for (int i = 0; i < 5; i++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carPrices addObject:cell.priceText.text];
}
}
and here is cellForRowAtIndexPath:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
carCellTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.nameLabel.text = [_carNames objectAtIndex:indexPath.row];
cell.priceLabel.text = [NSString stringWithFormat:#"$%#/day",[_carPrices objectAtIndex:indexPath.row]];
cell.infoLabl.text = [_carInfos objectAtIndex:indexPath.row];
switch (indexPath.row) {
case 0:
{
[cell.img setImage:[UIImage imageNamed:#"rolls.jpg"]];
return cell;
}
case 1:
{
[cell.img setImage:[UIImage imageNamed:#"bentley.jpg"]];
return cell;
}
case 2:
{
[cell.img setImage:[UIImage imageNamed:#"mercedes.jpg"]];
return cell;
}
case 3:
{
[cell.img setImage:[UIImage imageNamed:#"bmw.jpg"]];
return cell;
}
case 4:
{
[cell.img setImage:[UIImage imageNamed:#"skoda.jpg"]];
}
default:
break;
}
return cell;
}
additional:
in my tableviewCell i have a label, and a textfield. when i click on "Save" i want save all my data from textField and send it to label.
here is all code from .m file:
#import "carListViewController.h"
#import "carCellTableViewCell.h"
#import "UserSingleton.h"
#import "CheckInternetConnection.h"
#define getCarList #"http:mylink.php" //changed
#define setCarList #"http:mylink.php" //changed
#interface carListViewController ()
#property (weak, nonatomic) IBOutlet UIBarButtonItem *editButtonOutler;
- (IBAction)editButtonOnClick:(id)sender;
#property BOOL editOrSave;//0 when edit, 1 when save
#property UserSingleton * userInfo;
#property NSMutableArray *json;
#property NSMutableArray * carNames;
#property NSMutableArray * carPrices;
#property NSMutableArray * carInfos;
#property NSMutableArray * carNewPrices;
- (void) setData;
#property (weak, nonatomic) IBOutlet UITableView *meTableView;
- (void) saveDataToArray;
- (void) getDataOfCars;
#end
#implementation carListViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"List of cars";
// Do any additional setup after loading the view.
}
- (void) viewWillAppear:(BOOL)animated
{
CheckInternetConnection * checkInternet = [[CheckInternetConnection alloc] init];
if (![checkInternet isInternetAvailable])
[self.navigationController popViewControllerAnimated:YES];
_userInfo = [UserSingleton sharedInstance];
if (_userInfo.priority == 2)
{
_editButtonOutler.enabled = YES;
_editButtonOutler.title = #"Edit";
}
else
{
_editButtonOutler.enabled = NO;
_editButtonOutler.title = #"";
}
_editOrSave = NO;
[self getDataOfCars];
[_meTableView reloadData];
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
carCellTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.nameLabel.text = [_carNames objectAtIndex:indexPath.row];
cell.priceLabel.text = [NSString stringWithFormat:#"$%#/day",[_carPrices objectAtIndex:indexPath.row]];
cell.infoLabl.text = [_carInfos objectAtIndex:indexPath.row];
switch (indexPath.row) {
case 0:
{
[cell.img setImage:[UIImage imageNamed:#"rolls.jpg"]];
return cell;
}
case 1:
{
[cell.img setImage:[UIImage imageNamed:#"bentley.jpg"]];
return cell;
}
case 2:
{
[cell.img setImage:[UIImage imageNamed:#"mercedes.jpg"]];
return cell;
}
case 3:
{
[cell.img setImage:[UIImage imageNamed:#"bmw.jpg"]];
return cell;
}
case 4:
{
[cell.img setImage:[UIImage imageNamed:#"skoda.jpg"]];
}
default:
break;
}
return cell;
}
- (IBAction)editButtonOnClick:(id)sender {
if (_editOrSave == 0)
{
_editOrSave = 1;
_editButtonOutler.title = #"Save";
carCellTableViewCell * cell;
for (int i = 0; i < 5; i ++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.priceLabel.hidden = YES;
cell.priceText.hidden = NO;
cell.priceText.text = [[_json objectAtIndex:i] objectForKey:#"cost"];
}
}
else if (_editOrSave == 1)
{
_editOrSave = 0;
carCellTableViewCell * cell;
for (int i = 0; i < 5; i ++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.priceLabel.hidden = NO;
cell.priceText.hidden = YES;
[self saveDataToArray];
[self setData];
//cell.priceLabel.text = [_carPrices objectAtIndex:i];
}
_editButtonOutler.title = #"Edit";
}
[self getDataOfCars];
[_meTableView reloadData];
}
- (void) getDataOfCars
{
_carInfos = [[NSMutableArray alloc] init];
_carNames = [[NSMutableArray alloc] init];
_carPrices = [[NSMutableArray alloc] init];
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:getCarList] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];
_json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
carCellTableViewCell * cell;
for (int i = 0; i < _json.count; i ++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carNames addObject:[[_json objectAtIndex:i] objectForKey:#"name"]];
[_carPrices addObject:[[_json objectAtIndex:i] objectForKey:#"cost"]];
[_carInfos addObject:[[_json objectAtIndex:i] objectForKey:#"about"]];
}
}
- (void) setData{
for (int i = 0; i < 5; i ++)
{
NSMutableString * postString = [NSMutableString stringWithFormat:setCarList];
[postString appendString:[NSString stringWithFormat:#"?id=%d", i+1]];
[postString appendString:[NSString stringWithFormat:#"&cost=%#", [_carPrices objectAtIndex:i]]];
[postString setString:[postString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:postString]];
[request setHTTPMethod:#"POST"];
NSURLConnection * postConnection;
postConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
}
- (void) saveDataToArray
{
carCellTableViewCell * cell;
_carNewPrices = [[NSMutableArray alloc] init];
for (int i = 0; i < 5; i++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carPrices addObject:cell.priceText.text];
}
}
#end
it seems that an error is caused because not all cells are visible in the screen. after my scroll down now even last cell has changed after my onclick on edit button.
how to resovle this problem?
It's upside-down to fill an array with what's in a UITableView. The way to do that is the other way around.
In other words, somewhere else in your code you determine what's in the priceText label. If it's a static table, then the information might be in IB, or if you're implementing tableview:cellForRowAtIndexPath:, you're looking up the priceText there.
Put those values in the priceArray.
Your edit helped. This line:
[NSString stringWithFormat:#"$%#/day",[_carPrices objectAtIndex:indexPath.row]];
Is your friend, so:
NSMutableArray *newArrayOfStrings = [NSMutableArray array];
for (int i=0; i<_carPrices.count; i++) {
NSString *str = [NSString stringWithFormat:#"$%#/day",_carPrices[i]];
[newArrayOfStrings addObject:str];
}
Edit again. More code and comments, more clarity:
Declare that your vc implements the UITextFieldDelegate, and declare a property to keep your edited prices:
#interface MyViewController <UITextFieldDelegate>
#property (nonatomic, strong) NSMutableArray *editedStrings;
// initialize this with the carPrices after you get these from JSON
self.editedStrings = [_carPrices mutableCopy]; // if they are NSNumbers
// if they are strings, you'll need a deeper copy:
self.editedStrings = [NSMutableArray array];
for (NSString *str in _carPrices) {
[self.editedStrings addObject:[str copy]];
}
In cellForRowAtIndexPath, make your vc the delegate, and tag the textFields, so you know which one is being edited:
cell.priceLabel.delegate = self;
cell.priceLabel.tag = indexPath.row;
Then implement the delegate method for when the user edits:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSInteger index = textField.tag;
NSString *candidateString = [textField.text stringByReplacingCharactersInRange:range withString:string];
[self.editedStrings replaceObjectAtIndex:index withObject: candidateString];
return YES;
}
Add a breakpoint to the line [_carPrices addObject:cell.priceText.text] and you'll see that at some index, the text will be nil. I can't tell you why will it be nil, since I don't know how you're creating the cell.

SKSTableView Scrolling Issue

I am currently using this custom/ expandable tableview code called SKSTableView which can be found at Here
Here's the issue, when I fill the table with over 10 rows, the UI Locks up and the scrolling begins to be extremely laggy. I can't seem to be able to track down the issue, but I am thinking it has something to do with reusing the cell.
Here's some code that will hopefully help.
-SKSTableView hasn't changed
-Below is the implementation in the actual file /Home Screen of app
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Bar *bar = [bars objectAtIndex:indexPath.row];
NSArray *friendsAtBar = (NSArray*)bar.friends;
static NSString *cellIdentifier = #"SKSTableViewCell";
SKSTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell){//If no cell, create a new one
cell = [[SKSTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
UIColor *cellBackgroundColor = [UIColor colorWithWhite:( 30/255.0) alpha:1.0];
UIColor *cellTextColor = [UIColor colorWithWhite:0.80 alpha:1.0];
UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 73, 320, 2)];
bottomLine.backgroundColor = [UIColor colorWithWhite:( 50/255.0) alpha:1.0];
cell.nameLabel.textColor = cellTextColor;
cell.friendsLabel.textColor = cellTextColor;
cell.backgroundColor = cellBackgroundColor;
cell.selectionBanner.backgroundColor = cellBackgroundColor;
[cell addSubview:bottomLine];
[cell.goingButton addTarget:self
action:#selector(goingButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.nameLabel.frame = nameStartFrame;
}
if (friendsAtBar != nil && friendsAtBar.count != 0)
cell.isExpandable = YES;
else
cell.isExpandable = NO;
cell.nameLabel.text = bar.name;
//cell.userInteractionEnabled = YES;
if (friendsAtBar.count == 1) // If only 1 friend is going, say friend, if more than 1 friend is going say friends
cell.friendsLabel.text = [NSString stringWithFormat:#"%lu friend going",(unsigned long)friendsAtBar.count];
else if (friendsAtBar.count > 1)
cell.friendsLabel.text = [NSString stringWithFormat:#"%lu friends going",(unsigned long)friendsAtBar.count];
else {
cell.friendsLabel.text = #"";
//cell.nameLabel.frame = CGRectMake(20, 26, 200, 23);
}
//cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.tag = indexPath.row;
[self deselectGoingButton:cell.goingButton];
if ([bar.objectID isEqualToString:[currentUser objectForKey:#"currentBarID"]] && [self under15Hours:[currentUser objectForKey:#"barTimeStamp"]])
{
goingToBarID = bar.objectID; // HERE
//NSLog(#"goingToBarID from cell: %#",goingToBarID);
selectedGoingToButton = cell.goingButton;
[self selectGoingButton:cell.goingButton];
}
cell.goingButton.tag = indexPath.row;
cell.selectionBanner.tag = indexPath.row;
return cell;
}
#pragma mark - TableView - Subrow
- (NSInteger)tableView:(SKSTableView *)tableView numberOfSubRowsAtIndexPath:(NSIndexPath *)indexPath {
if (bars != nil && bars.count != 0) {
Bar *bar = [bars objectAtIndex:indexPath.row];
return bar.friends.count;
}
else
return 0;
} // PARSE IMPACTED
- (UITableViewCell *)tableView:(UITableView *)tableView cellForSubRowAtIndexPath:(NSIndexPath *)indexPath {
//NSMutableDictionary *bar = [bars objectAtIndex:indexPath.row];
Bar *bar = [bars objectAtIndex:indexPath.row];
NSArray *friendsAtBar = (NSArray*)bar.friends;
//UIColor *cellBackgroundColor = [UIColor colorWithWhite:( 20/255.0) alpha:1.0];
//UIColor *cellTextColor = [UIColor colorWithWhite:0.85 alpha:1.0];
UIImageView *bottomLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, 73, 320, 2)];
bottomLine.backgroundColor = [UIColor colorWithWhite:( 50/255.0) alpha:1.0];
static NSString *cellIdentifier = #"FriendsGoingCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UIView *cellView;
UILabel *nameLabel;
UILabel *usernameLabel;
UIButton *callButton;
UIButton *textButton;
if (!cell){//If no cell, make a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cellView = [self createSubRowView];
nameLabel = [cellView.subviews objectAtIndex:1];
usernameLabel = [cellView.subviews objectAtIndex:2];
usernameLabel.textColor = [UIColor colorWithWhite:0.7 alpha:1.0];
callButton = [cellView.subviews objectAtIndex:3];
textButton = [cellView.subviews objectAtIndex:4];
[cell addSubview:cellView];
[cell addSubview:bottomLine];
}
//cell.backgroundColor = cellBackgroundColor;
cell.tag = 2;
//PFUser *user = [friendsAtBar objectAtIndex:indexPath.subRow-1];
Friend *user = [friendsAtBar objectAtIndex:indexPath.subRow-1];
//UILabel *nameLabel = [cellView.subviews objectAtIndex:1];
//nameLabel.text = [[friendsAtBar objectAtIndex:indexPath.subRow-1] objectForKey:#"username"];
nameLabel.text = [NSString stringWithFormat:#"%#",user.compositeName];
//nameLabel.textColor = cellTextColor;
// UILabel *usernameLabel = [cellView.subviews objectAtIndex:2];
usernameLabel.text = user.userName;
//UIButton *callButton = [cellView.subviews objectAtIndex:3];
callButton.tag = indexPath.subRow-1;
//UIButton *textButton = [cellView.subviews objectAtIndex:4];
textButton.tag = indexPath.subRow-1;
return cell;
}
[self createSubView]
- (UIView *)createSubRowView {
UIView *cellView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, [rowHeight floatValue])];
UIColor *fontColor = [UIColor colorWithWhite:0.85 alpha:1.0];
UIView* bgview = [[UIView alloc] initWithFrame:cellView.frame];
bgview.backgroundColor = [UIColor colorWithWhite:0.15 alpha:1.0];
[cellView addSubview:bgview];
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 16, 180, 23)];
nameLabel.textColor = fontColor;
nameLabel.font = [UIFont boldSystemFontOfSize:17];
[cellView addSubview:nameLabel];
UILabel *goingTimeStampLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 41, 180, 16)];
goingTimeStampLabel.textColor = fontColor;
goingTimeStampLabel.font = [UIFont systemFontOfSize:13];
[cellView addSubview:goingTimeStampLabel];
CGFloat x = 200;
CGFloat width = 55;
CGFloat height = [rowHeight floatValue];
CGFloat y = ([rowHeight floatValue] - height)/2;
UIButton *callButton = [[UIButton alloc] initWithFrame:CGRectMake(x, y, width, height)];
UIImage *callIcon = [UIImage imageNamed:#"call.png"];
[callButton setImage:callIcon forState:UIControlStateNormal];
[callButton addTarget:self
action:#selector(clickedCallButton:)
forControlEvents:UIControlEventTouchUpInside];
[cellView addSubview:callButton];
UIButton *textButton = [[UIButton alloc] initWithFrame:CGRectMake(x+width, y, width, height)];
UIImage *textIcon = [UIImage imageNamed:#"text.png"];
[textButton setImage:textIcon forState:UIControlStateNormal];
[textButton addTarget:self
action:#selector(clickedTextButton:)
forControlEvents:UIControlEventTouchUpInside];
[cellView addSubview:textButton];
return cellView;
}
SKSTableView.m
#import "SKSTableView.h"
#import "SKSTableViewCell.h"
#import "SKSTableViewCellIndicator.h"
#import <objc/runtime.h>
#pragma mark - NSArray (SKSTableView)
#interface NSMutableArray (SKSTableView)
- (void)initiateObjectsForCapacity:(NSInteger)numItems;
#end
#implementation NSMutableArray (SKSTableView)
- (void)initiateObjectsForCapacity:(NSInteger)numItems
{
for (NSInteger index = [self count]; index < numItems; index++) {
NSMutableArray *array = [NSMutableArray array];
[self addObject:array];
}
}
#end
#pragma mark - SKSTableView
#interface SKSTableView () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) NSMutableArray *expandedIndexPaths;
#property (nonatomic, strong) NSMutableDictionary *expandableCells;
#end
#implementation SKSTableView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_shouldExpandOnlyOneCell = NO;
}
return self;
}
- (void)setSKSTableViewDelegate:(id<SKSTableViewDelegate>)SKSTableViewDelegate
{
self.dataSource = self;
self.delegate = self;
[self setSeparatorColor:[UIColor colorWithRed:236.0/255.0 green:236.0/255.0 blue:236.0/255.0 alpha:1.0]];
if (SKSTableViewDelegate)
_SKSTableViewDelegate = SKSTableViewDelegate;
}
- (void)setSeparatorColor:(UIColor *)separatorColor
{
[super setSeparatorColor:separatorColor];
[SKSTableViewCellIndicator setIndicatorColor:separatorColor];
}
- (NSMutableArray *)expandedIndexPaths
{
if (!_expandedIndexPaths)
_expandedIndexPaths = [NSMutableArray array];
return _expandedIndexPaths;
}
- (NSMutableDictionary *)expandableCells
{
if (!_expandableCells)
_expandableCells = [NSMutableDictionary dictionary];
return _expandableCells;
}
#pragma mark - UITableViewDataSource
#pragma mark - Required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_SKSTableViewDelegate tableView:tableView numberOfRowsInSection:section] + [[[self expandedIndexPaths] objectAtIndex:section] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (![self.expandedIndexPaths[indexPath.section] containsObject:indexPath]) {
NSIndexPath *tempIndexPath = [self correspondingIndexPathForRowAtIndexPath:indexPath];
SKSTableViewCell *cell = (SKSTableViewCell *)[_SKSTableViewDelegate tableView:tableView cellForRowAtIndexPath:tempIndexPath];
if ([[self.expandableCells allKeys] containsObject:tempIndexPath])
[cell setIsExpanded:[[self.expandableCells objectForKey:tempIndexPath] boolValue]];
[cell setSeparatorInset:UIEdgeInsetsZero];
if (cell.isExpandable) {
[self.expandableCells setObject:[NSNumber numberWithBool:[cell isExpanded]]
forKey:indexPath];
UIButton *expandableButton = (UIButton *)cell.accessoryView;
[expandableButton addTarget:tableView
action:#selector(expandableButtonTouched:event:)
forControlEvents:UIControlEventTouchUpInside];
if (cell.isExpanded) {
cell.accessoryView.transform = CGAffineTransformMakeRotation(M_PI);
} else {
if ([cell containsIndicatorView])
[cell removeIndicatorView];
}
} else {
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell removeIndicatorView];
cell.accessoryView = nil;
}
return cell;
} else {
NSIndexPath *indexPathForSubrow = [self correspondingIndexPathForSubRowAtIndexPath:indexPath];
UITableViewCell *cell = [_SKSTableViewDelegate tableView:(SKSTableView *)tableView cellForSubRowAtIndexPath:indexPathForSubrow];
cell.backgroundView = nil;
cell.backgroundColor = [self separatorColor];
cell.indentationLevel = 2;
return cell;
}
}
#pragma mark - Optional
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(numberOfSectionsInTableView:)]) {
NSInteger numberOfSections = [_SKSTableViewDelegate numberOfSectionsInTableView:tableView];
if ([self.expandedIndexPaths count] != numberOfSections)
[self.expandedIndexPaths initiateObjectsForCapacity:numberOfSections];
return numberOfSections;
}
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:titleForHeaderInSection:)])
return [_SKSTableViewDelegate tableView:tableView titleForHeaderInSection:section];
return nil;
}
#pragma mark - UITableViewDelegate
#pragma mark - Optional
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:didSelectRowAtIndexPath:)])
[_SKSTableViewDelegate tableView:tableView didSelectRowAtIndexPath:indexPath];
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:didDeselectRowAtIndexPath:)])
[_SKSTableViewDelegate tableView:tableView didDeselectRowAtIndexPath:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
SKSTableViewCell *cell = (SKSTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[SKSTableViewCell class]] && cell.isExpandable) {
cell.isExpanded = !cell.isExpanded;
NSIndexPath *_indexPath = indexPath;
if (cell.isExpanded && self.shouldExpandOnlyOneCell) {
_indexPath = [self correspondingIndexPathForRowAtIndexPath:indexPath];
[self collapseCurrentlyExpandedIndexPaths];
}
NSInteger numberOfSubRows = [self numberOfSubRowsAtIndexPath:_indexPath];
NSMutableArray *indexPaths = [NSMutableArray array];
NSInteger row = _indexPath.row;
NSInteger section = _indexPath.section;
for (NSInteger index = 1; index <= numberOfSubRows; index++) {
NSIndexPath *expIndexPath = [NSIndexPath indexPathForRow:row+index inSection:section];
[indexPaths addObject:expIndexPath];
}
if (cell.isExpanded) {
[self setIsExpanded:YES forCellAtIndexPath:_indexPath];
[self insertExpandedIndexPaths:indexPaths forSection:_indexPath.section];
} else {
[self setIsExpanded:NO forCellAtIndexPath:_indexPath];
[self removeExpandedIndexPaths:indexPaths forSection:_indexPath.section];
}
[self accessoryViewAnimationForCell:cell];
}
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:accessoryButtonTappedForRowWithIndexPath:)])
[_SKSTableViewDelegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath];
[self.delegate tableView:tableView didSelectRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = 0;
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:heightForHeaderInSection:)])
height = [_SKSTableViewDelegate tableView:tableView heightForHeaderInSection:section];
return height;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view = [[UIView alloc] init];
if ([_SKSTableViewDelegate respondsToSelector:#selector(tableView:viewForHeaderInSection:)])
view = [_SKSTableViewDelegate tableView:tableView viewForHeaderInSection:section];
return view;
}
#pragma mark - SKSTableViewUtils
- (IBAction)expandableButtonTouched:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self];
NSIndexPath *indexPath = [self indexPathForRowAtPoint:currentTouchPosition];
if (indexPath)
[self tableView:self accessoryButtonTappedForRowWithIndexPath:indexPath];
}
- (NSInteger)numberOfSubRowsAtIndexPath:(NSIndexPath *)indexPath
{
return [_SKSTableViewDelegate tableView:self numberOfSubRowsAtIndexPath:[self correspondingIndexPathForRowAtIndexPath:indexPath]];
}
- (NSIndexPath *)correspondingIndexPathForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger index = 0;
NSInteger row = 0;
while (index < indexPath.row) {
NSIndexPath *tempIndexPath = [self correspondingIndexPathForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:indexPath.section]];
BOOL isExpanded = [[self.expandableCells allKeys] containsObject:tempIndexPath] ? [[self.expandableCells objectForKey:tempIndexPath] boolValue] : NO;
if (isExpanded) {
NSInteger numberOfExpandedRows = [_SKSTableViewDelegate tableView:self numberOfSubRowsAtIndexPath:tempIndexPath];
index += (numberOfExpandedRows + 1);
} else
index++;
row++;
}
return [NSIndexPath indexPathForRow:row inSection:indexPath.section];
}
- (NSIndexPath *)correspondingIndexPathForSubRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger index = 0;
NSInteger row = 0;
NSInteger subrow = 0;
while (1) {
NSIndexPath *tempIndexPath = [self correspondingIndexPathForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:indexPath.section]];
BOOL isExpanded = [[self.expandableCells allKeys] containsObject:tempIndexPath] ? [[self.expandableCells objectForKey:tempIndexPath] boolValue] : NO;
if (isExpanded) {
NSInteger numberOfExpandedRows = [_SKSTableViewDelegate tableView:self numberOfSubRowsAtIndexPath:tempIndexPath];
if ((indexPath.row - index) <= numberOfExpandedRows) {
subrow = indexPath.row - index;
break;
}
index += (numberOfExpandedRows + 1);
} else
index++;
row++;
}
return [NSIndexPath indexPathForSubRow:subrow inRow:row inSection:indexPath.section];
}
- (void)setIsExpanded:(BOOL)isExpanded forCellAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *correspondingIndexPath = [self correspondingIndexPathForRowAtIndexPath:indexPath];
[self.expandableCells setObject:[NSNumber numberWithBool:isExpanded] forKey:correspondingIndexPath];
}
- (void)insertExpandedIndexPaths:(NSArray *)indexPaths forSection:(NSInteger)section
{
NSIndexPath *firstIndexPathToExpand = indexPaths[0];
NSIndexPath *firstIndexPathExpanded = nil;
if ([self.expandedIndexPaths[section] count] > 0) firstIndexPathExpanded = self.expandedIndexPaths[section][0];
__block NSMutableArray *array = [NSMutableArray array];
if (firstIndexPathExpanded && firstIndexPathToExpand.section == firstIndexPathExpanded.section && firstIndexPathToExpand.row < firstIndexPathExpanded.row) {
[self.expandedIndexPaths[section] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSIndexPath *updated = [NSIndexPath indexPathForRow:([obj row] + [indexPaths count])
inSection:[obj section]];
[array addObject:updated];
}];
[array addObjectsFromArray:indexPaths];
self.expandedIndexPaths[section] = array;
} else {
[self.expandedIndexPaths[section] addObjectsFromArray:indexPaths];
}
[self sortExpandedIndexPathsForSection:section];
// Reload TableView
[self insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
}
- (void)removeExpandedIndexPaths:(NSArray *)indexPaths forSection:(NSInteger)section
{
NSUInteger index = [self.expandedIndexPaths[section] indexOfObject:indexPaths[0]];
[self.expandedIndexPaths[section] removeObjectsInArray:indexPaths];
if (index == 0) {
__block NSMutableArray *array = [NSMutableArray array];
[self.expandedIndexPaths[section] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSIndexPath *updated = [NSIndexPath indexPathForRow:([obj row] - [indexPaths count])
inSection:[obj section]];
[array addObject:updated];
}];
self.expandedIndexPaths[section] = array;
}
[self sortExpandedIndexPathsForSection:section];
// Reload Tableview
[self deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
}
- (void)collapseCurrentlyExpandedIndexPaths
{
NSArray *expandedCells = [self.expandableCells allKeysForObject:[NSNumber numberWithBool:YES]];
if (expandedCells.count > 0) {
NSIndexPath *indexPath = [expandedCells firstObject];
[self.expandableCells setObject:[NSNumber numberWithBool:NO] forKey:indexPath];
[self removeExpandedIndexPaths:[self.expandedIndexPaths[indexPath.section] copy] forSection:indexPath.section];
SKSTableViewCell *cell = (SKSTableViewCell *)[self cellForRowAtIndexPath:indexPath];
cell.isExpanded = NO;
[self accessoryViewAnimationForCell:cell];
}
}
- (void)sortExpandedIndexPathsForSection:(NSInteger)section
{
[self.expandedIndexPaths[section] sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if ([obj1 section] < [obj2 section])
return (NSComparisonResult)NSOrderedAscending;
else if ([obj1 section] > [obj2 section])
return (NSComparisonResult)NSOrderedDescending;
else {
if ([obj1 row] < [obj2 row])
return (NSComparisonResult)NSOrderedAscending;
else
return (NSComparisonResult)NSOrderedDescending;
}
}];
}
- (void)accessoryViewAnimationForCell:(SKSTableViewCell *)cell
{
__block SKSTableViewCell *_cell = cell;
[UIView animateWithDuration:0.2 animations:^{
if (_cell.isExpanded) {
_cell.accessoryView.transform = CGAffineTransformMakeRotation(M_PI);
} else {
_cell.accessoryView.transform = CGAffineTransformMakeRotation(0);
}
} completion:^(BOOL finished) {
if (!_cell.isExpanded)
[_cell removeIndicatorView];
}];
}
#end
#pragma mark - NSIndexPath (SKSTableView)
static void *SubRowObjectKey;
#implementation NSIndexPath (SKSTableView)
#dynamic subRow;
- (NSInteger)subRow
{
id subRowObj = objc_getAssociatedObject(self, SubRowObjectKey);
return [subRowObj integerValue];
}
- (void)setSubRow:(NSInteger)subRow
{
id subRowObj = [NSNumber numberWithInteger:subRow];
objc_setAssociatedObject(self, SubRowObjectKey, subRowObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (NSIndexPath *)indexPathForSubRow:(NSInteger)subrow inRow:(NSInteger)row inSection:(NSInteger)section
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
indexPath.subRow = subrow;
return indexPath;
}
#end

How can I update/reload/refresh a section header view in a UITableView?

I'm willing to change a specific header view of my UITableView when I click a row.
I've read all posts about it yet. I tried "reloadData", "setNeedDisplay", "reloadSections:withRowAnimation:", and several others ideas... there is nothing to do. My header view either doesn't update or it does weird things like updating only when I move the table view (which is not what I'm willing to achieve).
My code looks like this for now (regarding the UITableView delegates methods):
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
if(tableView==_storeTableView){
return [_storeDataArray count];
} else {
return 1;
}
}
-(UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {
if(tableView==_storeTableView){
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:section];
if (!headerModel.headerView) {
NSString *shelfName = headerModel.shelf;
headerModel.headerView = [[[HouraStoreHeaderView alloc] initWithFrame:CGRectMake(0.0, 0.0, _storeTableView.bounds.size.width, 80) title:shelfName section:section subheaderNumber:([headerModel.openedSubHeaders count]-1) delegate:self] autorelease];
}
return headerModel.headerView;
} else {
return nil;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(tableView==_storeTableView){
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:section];
NSDictionary *myDict = _storeDataDict;
for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
}
NSInteger numberOfRowsInSection = [[myDict allKeys] count];
return headerModel.open ? numberOfRowsInSection : 0;
} else if(tableView==_searchTableView){
return [_resultArray count];
} else {
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if(tableView==_storeTableView){
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
NSDictionary *myDict = _storeDataDict;
for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
}
cell.accessoryView=[[[HouraStoreCellView alloc] initWithFrame:CGRectMake(0.0, 0.0, _storeTableView.bounds.size.width, 50) title:[[myDict allKeys] objectAtIndex:indexPath.row]] autorelease];
return cell;
} else if (tableView==_searchTableView) {
cell.textLabel.text = [_resultArray objectAtIndex:indexPath.row];
return cell;
} else {
return cell;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:section];
NSInteger height = 59.0 + ([headerModel.openedSubHeaders count]-1)*41.0;
return height;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(tableView==_storeTableView){
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
NSDictionary *myDict = _storeDataDict;
for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
}
if ([[myDict objectForKey:[[myDict allKeys] objectAtIndex:indexPath.row]] isKindOfClass:[NSDictionary class]]) {
[self cellOpened:indexPath];
} else {
[_activityIndicatorView startAnimating];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(_listProductsFoundedFinished:)
name:HouraSearchProductsDone
object:nil];
NSString *searchString = [[myDict allKeys] objectAtIndex:indexPath.row];
searchString = [searchString stringByReplacingOccurrencesOfString:#"\"" withString:#"\\u0022"];
[_singleton.util beginSearchProducts:searchString context:#"2"];
}
} else if(tableView==_searchTableView){
_searchBar.text = [_resultArray objectAtIndex:indexPath.row];
[_searchBar resignFirstResponder];
[_activityIndicatorView startAnimating];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(_listProductsFoundedFinished:)
name:HouraSearchProductsDone
object:nil];
[_singleton.util beginSearchProducts:_searchBar.text context:#"2"];
}
}
-(void)headerView:(HouraStoreHeaderView*)headerView headerOpened:(NSInteger)headerOpened {
if (self.openSectionIndex!=NSNotFound) {
[self closeAllHeaders];
}
//[self closeAllHeaders];
HouraStoreHeaderModel *headerModel =nil;
headerModel = [self.headerInfoArray objectAtIndex:headerOpened];
headerModel.open = YES;
headerModel.headerView.disclosureButton.selected = YES;
NSDictionary *myDict = _storeDataDict;
for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
}
NSInteger countOfRowsToInsert = [[myDict allKeys] count];
NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < countOfRowsToInsert; i++) {
[indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:headerOpened]];
}
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
NSInteger previousOpenSectionIndex = self.openSectionIndex;
if (previousOpenSectionIndex != NSNotFound) {
HouraStoreHeaderModel *previousHeaderModel = [self.headerInfoArray objectAtIndex:previousOpenSectionIndex];
previousHeaderModel.open = NO;
previousHeaderModel.headerView.disclosureButton.selected = NO;
[previousHeaderModel.headerView toggleOpenWithUserAction:NO];
NSInteger countOfRowsToDelete = [[[_storeDataDict objectForKey:previousHeaderModel.shelf ] allKeys] count];
for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:previousOpenSectionIndex]];
}
}
UITableViewRowAnimation insertAnimation;
UITableViewRowAnimation deleteAnimation;
if (previousOpenSectionIndex == NSNotFound || headerOpened < previousOpenSectionIndex) {
insertAnimation = UITableViewRowAnimationTop;
deleteAnimation = UITableViewRowAnimationBottom;
} else {
insertAnimation = UITableViewRowAnimationBottom;
deleteAnimation = UITableViewRowAnimationTop;
}
[_storeTableView beginUpdates];
[_storeTableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:deleteAnimation];
[_storeTableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:insertAnimation];
[_storeTableView endUpdates];
self.openSectionIndex = headerOpened;
}
-(void)headerView:(HouraStoreHeaderView*)headerView headerClosed:(NSInteger)headerClosed {
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:headerClosed];
headerModel.open = NO;
headerModel.headerView.disclosureButton.selected = NO;
[headerModel cleanOpenedSubHeaders];
[self.headerInfoArray replaceObjectAtIndex:headerClosed withObject:headerModel];
NSInteger countOfRowsToDelete = [_storeTableView numberOfRowsInSection:headerClosed];
if (countOfRowsToDelete > 0) {
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:headerClosed]];
}
[_storeTableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationTop];
}
self.openSectionIndex = NSNotFound;
}
-(void)cellOpened:(NSIndexPath*)indexPath {
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
[self headerView:headerModel.headerView headerClosed:indexPath.section];
[headerModel addOpenedSubHeaders:[[[_storeDataDict objectForKey:headerModel.shelf] allKeys] objectAtIndex:indexPath.row]];
[self.headerInfoArray replaceObjectAtIndex:indexPath.section withObject:headerModel];
headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
[self headerView:headerModel.headerView headerOpened:indexPath.section];
}
-(void)closeAllHeaders {
for (NSInteger i = 0; i < [self.headerInfoArray count]; i++) {
HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:i];
[self headerView:headerModel.headerView headerClosed:i];
}
}
What I'd like to do is, when I click a row, the section header update so it contains a new button with the row text. Then I dismiss the row and reload new datas in the section rows. I managed to handle the rows perfectly. But I can't find a way to get this header view updated.
Thx for any idea.
You just change it directly. I created an instance variable in the header file for a label that I will put in the header's view I'll create:
#interface MainViewController : UITableViewController {
// creating my datasource array instance variable
NSArray *_items;
// this is the label I will add to the header view when I create it
UILabel *_headerLabel;
}
#end
And in my tableView when they select a row I call a function that simply changes the text on the label:
#implementation MainViewController
- (id)init {
self = [super initWithStyle:UITableViewStyleGrouped];
/ filling my datasource with test strings
_items = #[#"one", #"two"];
return self;
}
- (void)changeHeaderLabel:(NSString *)newLabel {
// when this function gets called and is passed a string, I will simply
// set the text on the label to the new string and viola!
_headerLabel.text = newLabel;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// this table will only have a single section for demo purposes
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// return the count of my datasource array
return _items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// attempt to create a cell by reusing one with a given identifier
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
// if I wasn't able to reuse one
if (cell == nil) {
// create one from scratch with that identifier
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
// now simply set the text on the cell from my data source array of strings
cell.textLabel.text = _items[indexPath.row];
// and return the cell
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// deselect the row so the cell automatically fades out after selection
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// here you could do one of two things, either get a reference to the cell itself,
// and then get the value stored in it's textLabel
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *newHeaderTitleString = selectedCell.textLabel.text;
// OR you can get it right from your datasource
NSString *newHeaderTitleString = _items[indexPath.row];
// then just call the above function with the string as the single param
[self changeHeaderLabel:newHeaderTitleString];
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
// here I just create a view that will span the whole frame and is an arbitrary height
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 80)];
// set the background color to clear
headerView.backgroundColor = [UIColor clearColor];
// then I initialize my instance variable with a frame that's centered in the view
// for aesthetic purposes
_headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, self.view.frame.size.width - 10, 80)];
// then I set the text color, add an autoresizing mask so if the view rotates
// it still remains centered properly, set the text to some starting value,
// and add it to the headerView I previously created
_headerLabel.textColor = [UIColor darkGrayColor];
_headerLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_headerLabel.text = #"Before";
[headerView addSubview:_headerLabel];
// then I return the headerView
return headerView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
// return an arbitrary height here for testing
return 80;
}
That results in the following:
If you have any questions let me know! This is just a quick example to demonstrate it, but you may want to customize the view in a different way altogether. This should at least solve your problem and give you a starting point to work from.
Have you tried reloadRowsAtIndexPaths:withRowAnimation: where you set the row property of the NSIndexPath passed in as NSNotFound? So reloading just the header of section 3, for instance would look like
NSIndexPath * headerIndexPath = [NSIndexPath indexPathForRow: NSNotFound section:3];
[self.tableView reloadRowsAtIndexPaths:#[headerIndexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
I guarantee nothing, but I'm pretty sure it used to work before, because I used it a couple of times.
But even if it works, it's still a hack that might get broken by Apple any time.
edit
Ok, never mind. I tried this with iOS 7 in Xcode 5 and for some reason, even with NSNotFound as the row number, it still reloads the whole sections (with all its cells). So this does not work any more, damn.

Resources