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];
}
Related
I am relatively new in iOS, I have found an example of accordion table view that I need. But the thing is that example is TableViewController and I need to implement TableView inside viewController. Can you please help me. What I have tried to do is create tableView, declare it in the h file as
#property (strong, nonatomic) IBOutlet UITableView *MyTb;
and then change all appearances of self.tableView to self.MyTb but it did not work, oh also changed
AccordionTableViewController : UITableViewController
to
AccordionTableViewController : UIViewController
So here is the original code, please help me and provide some guiadance to it, thanks.
h file:
#import <UIKit/UIKit.h>
#interface AccordionTableViewController : UITableViewController {
NSArray *topItems;
NSMutableArray *subItems; // array of arrays
int currentExpandedIndex;
}
#end
m file:
#import "AccordionTableViewController.h"
#define NUM_TOP_ITEMS 20
#define NUM_SUBITEMS 6
#implementation AccordionTableViewController
- (id)init {
self = [super init];
if (self) {
topItems = [[NSArray alloc] initWithArray:[self topLevelItems]];
subItems = [NSMutableArray new];
currentExpandedIndex = -1;
for (int i = 0; i < [topItems count]; i++) {
[subItems addObject:[self subItems]];
}
}
return self;
}
#pragma mark - Data generators
- (NSArray *)topLevelItems {
NSMutableArray *items = [NSMutableArray array];
for (int i = 0; i < NUM_TOP_ITEMS; i++) {
[items addObject:[NSString stringWithFormat:#"Item %d", i + 1]];
}
return items;
}
- (NSArray *)subItems {
NSMutableArray *items = [NSMutableArray array];
int numItems = arc4random() % NUM_SUBITEMS + 2;
for (int i = 0; i < numItems; i++) {
[items addObject:[NSString stringWithFormat:#"SubItem %d", i + 1]];
}
return items;
}
#pragma mark - View management
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [topItems count] + ((currentExpandedIndex > -1) ? [[subItems objectAtIndex:currentExpandedIndex] count] : 0);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ParentCellIdentifier = #"ParentCell";
static NSString *ChildCellIdentifier = #"ChildCell";
BOOL isChild =
currentExpandedIndex > -1
&& indexPath.row > currentExpandedIndex
&& indexPath.row <= currentExpandedIndex + [[subItems objectAtIndex:currentExpandedIndex] count];
UITableViewCell *cell;
if (isChild) {
cell = [tableView dequeueReusableCellWithIdentifier:ChildCellIdentifier];
}
else {
cell = [tableView dequeueReusableCellWithIdentifier:ParentCellIdentifier];
}
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ParentCellIdentifier] autorelease];
}
if (isChild) {
cell.detailTextLabel.text = [[subItems objectAtIndex:currentExpandedIndex] objectAtIndex:indexPath.row - currentExpandedIndex - 1];
}
else {
int topIndex = (currentExpandedIndex > -1 && indexPath.row > currentExpandedIndex)
? indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count]
: indexPath.row;
cell.textLabel.text = [topItems objectAtIndex:topIndex];
cell.detailTextLabel.text = #"";
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL isChild =
currentExpandedIndex > -1
&& indexPath.row > currentExpandedIndex
&& indexPath.row <= currentExpandedIndex + [[subItems objectAtIndex:currentExpandedIndex] count];
if (isChild) {
NSLog(#"A child was tapped, do what you will with it");
return;
}
[self.tableView beginUpdates];
if (currentExpandedIndex == indexPath.row) {
[self collapseSubItemsAtIndex:currentExpandedIndex];
currentExpandedIndex = -1;
}
else {
BOOL shouldCollapse = currentExpandedIndex > -1;
if (shouldCollapse) {
[self collapseSubItemsAtIndex:currentExpandedIndex];
}
currentExpandedIndex = (shouldCollapse && indexPath.row > currentExpandedIndex) ? indexPath.row - [[subItems objectAtIndex:currentExpandedIndex] count] : indexPath.row;
[self expandItemAtIndex:currentExpandedIndex];
}
[self.tableView endUpdates];
}
- (void)expandItemAtIndex:(int)index
{
NSMutableArray *indexPaths = [NSMutableArray new];
NSArray *currentSubItems = [subItems objectAtIndex:index];
int insertPos = index + 1;
for (int i = 0; i < [currentSubItems count]; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:insertPos++ inSection:0]];
}
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
//[indexPaths release];
}
- (void)collapseSubItemsAtIndex:(int)index
{
NSMutableArray *indexPaths = [NSMutableArray new];
for (int i = index + 1; i <= index + [[subItems objectAtIndex:index] count]; i++)
{
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
//[indexPaths release];
}
- (void)dealloc
{
[topItems release];
[subItems release];
[super dealloc];
}
#end
You must set your view controller as delegate and datasource of your tableview:
#interface AccordionTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
in your header file and in viewDidLoad:
-(void)viewDidLoad {
[super viewDidLoad];
self.MyTb.delegate = self;
self.MyTb.dataSource = self;
}
Or you can set the datasource and delegate in Storyboard. You must also make sure you have connected the table view to MyTb IBOutlet in storyboard.
Im trying to figure out why my program runs well on simulator but not on Phone.
when i scroll my Tables it gets laggy.
ive tried everything , even removed my Images loading but still scroll lag happen.
Im using apple lazy loading source code :
this is my code :
#define kCustomRowCount 7
#interface SubCategoryViewController () <UIScrollViewDelegate>
#property (nonatomic, strong) NSMutableDictionary *imageDownloadsInProgress;
#property (nonatomic, strong) NSMutableDictionary *imageRestitleDownloadsInProgress;
#property (nonatomic, assign) int intindex;
#end
#implementation SubCategoryViewController
#pragma mark
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = self.catname;
self.imageDownloadsInProgress = [NSMutableDictionary dictionary];
self.imageRestitleDownloadsInProgress = [NSMutableDictionary dictionary];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
NSArray *allDownloads = [self.imageDownloadsInProgress allValues];
[allDownloads makeObjectsPerformSelector:#selector(cancelDownload)];
NSArray *allDownloads2 = [self.imageRestitleDownloadsInProgress allValues];
[allDownloads2 makeObjectsPerformSelector:#selector(cancelDownload)];
[self.imageDownloadsInProgress removeAllObjects];
[self.imageRestitleDownloadsInProgress removeAllObjects];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSUInteger count = [self.entries count];
// if there's no data yet, return enough rows to fill the screen
if (count == 0)
{
return kCustomRowCount;
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell2";
NSUInteger nodeCount = [self.entries count];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
cell.contentView.translatesAutoresizingMaskIntoConstraints = NO;
UILabel *newsbody = (UILabel *)[cell.contentView viewWithTag:6];
UIImageView *uimg = (UIImageView *)[cell.contentView viewWithTag:20];
UIImageView *uimgresttile = (UIImageView *)[cell.contentView viewWithTag:23];
if (nodeCount == 0 && indexPath.row == 0)
{
if (cell == nil) {
uimg.hidden = true;
uimgresttile.hidden = true;
newsbody.hidden = true;
}
else
{
uimg.hidden = true;
uimgresttile.hidden = true;
newsbody.hidden = true;
}
return cell;
}
if (nodeCount == 0 && indexPath.row > 0)
{
cell.hidden = true;
return cell;
}
if (nodeCount > 0)
{
uimg.hidden = false;
uimgresttile.hidden = false;
newsbody.hidden = true;
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
[newsbody setText:appRecord.Body];
if (!appRecord.appIcon)
{
if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
uimg.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
uimg.image = appRecord.appIcon;
}
if (!appRecord.appIconrestitle)
{
if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
{
[self startRestitleIconDownload:appRecord forIndexPath:indexPath];
}
uimgresttile.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
uimgresttile.image = appRecord.appIconrestitle;
}
}
if ((unsigned long)indexPath.row == [self.entries count] - 1){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^{
NewsFetchParseOperation *p = [[NewsFetchParseOperation alloc]init];
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
p.cat = appRecord.Category;
self.intindex = self.intindex + 1;
p.index = [NSString stringWithFormat:#"%d", (int)self.intindex];
p.lastid = appRecord.ids;
[p main];
dispatch_async(dispatch_get_main_queue(), ^(void)
{
SubCategoryViewController *svc =[self.storyboard instantiateViewControllerWithIdentifier:#"SubCategory"];
NSArray *temp =[self.entries arrayByAddingObjectsFromArray:p.appRecordList];
self.entries = temp;
[self.tableView reloadData];
});
});
}
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell2";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
height += 1;
return height;
}
- (void)startIconDownload:(NewsFetchAppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
NewsFetchIconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[NewsFetchIconDownloader alloc] init];
iconDownloader.newsfetchappRecord = appRecord;
[iconDownloader setCompletionHandler:^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIImageView *uimg = (UIImageView *)[cell.contentView viewWithTag:20];
uimg.image = appRecord.appIcon;
[self.imageDownloadsInProgress removeObjectForKey:indexPath];
}];
[self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
}
}
- (void)startRestitleIconDownload:(NewsFetchAppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
NewsFetchRestitleIconDownloader *ResttitleiconDownloader = [self.imageRestitleDownloadsInProgress objectForKey:indexPath];
if (ResttitleiconDownloader == nil)
{
ResttitleiconDownloader = [[NewsFetchRestitleIconDownloader alloc] init];
ResttitleiconDownloader.newsfetchappRecord = appRecord;
[ResttitleiconDownloader setCompletionHandler:^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIImageView *uimgresttile = (UIImageView *)[cell.contentView viewWithTag:23];
uimgresttile.image = appRecord.appIconrestitle;
[self.imageRestitleDownloadsInProgress removeObjectForKey:indexPath];
}];
[self.imageRestitleDownloadsInProgress setObject:ResttitleiconDownloader forKey:indexPath];
[ResttitleiconDownloader startDownload];
}
}
- (void)loadImagesForOnscreenRows
{
if ([self.entries count] > 0)
{
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in visiblePaths)
{
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
if (!appRecord.appIcon)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
}
}
}
- (void)loadRestitleImagesForOnscreenRows
{
if ([self.entries count] > 0)
{
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in visiblePaths)
{
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
if (!appRecord.appIconrestitle)
{
[self startRestitleIconDownload:appRecord forIndexPath:indexPath];
}
}
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
{
[self loadImagesForOnscreenRows];
[self loadRestitleImagesForOnscreenRows];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadImagesForOnscreenRows];
[self loadRestitleImagesForOnscreenRows];
}
#end
Edit:
In iphone if i scroll the the table it will freeze and jump most of time. even when
picture loaded properly. this problem never happen in simulator and only in real device.
i read most of article here base on "uitableview" lagging. most them suggest to use asnyc
method for downloading images. im using apple lazyloading sample method so i guess images
gets downloaded other than main thread.
think i have done till now is to comment most of code section by section and still lag
happend.
i even remove most part from Storyboard , but still lag happend.
You should delete all of your image download methods. Delete also scrollViewDidEndDragging and scrollViewDidEndDecelerating. I don't know why your heightForRowAtIndexPath is so complicated. Is every row a different size? If not use a simple case statement with the couple of cases you've got. Different height for each row can be a drag on resources.
Now for cellForRowAtIndexPath:
If the hidden not hidden stuff you are doing is for performance you should delete all of that.
Add AFNetworking to your project. If you are using cocaopods (you should) can add it with on line in your Podfile. It's good practice when developing with iOS to use libraries and AFNetworking is the best when it comes to getting stuff like images from a network.
#import "UIImageView+AFNetworking.h"
Now all your image work is done with one line of code (AFNetworking will handle all the caching and the performance related issues and the asynchronous stuff for you):
[uimg setImageWithURL:"http://blahbahblah.com" placeholderImage:someUIIMage]
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
}
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
I am having an app in which I am showing some data in my tableview as shown in the ScreenShot1 below.
Screenshot1.
Now I am having an imageview On my each tableview cell.
If I select any of the cell from tableview, I want an image on that selected cell as shown in screenshot2 below.
Screenshot2.
Now If I select any other cell form tableview. I want to set my imageview's image only on those selected cells as shown in Screenshot3 below.
Below is the code I am doing.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
lblRecipe = [[UILabel alloc] initWithFrame:CGRectMake(50, 5, 600, 32)];
lblRecipe.backgroundColor = [UIColor clearColor];
lblRecipe.font = [UIFont systemFontOfSize:20.0f];
[cell.contentView addSubview:lblRecipe];
checkedimg=[[UIImageView alloc]initWithFrame:CGRectMake(40, 20, 500, 5)];
[cell.contentView addSubview:checkedimg];
lblRecipe.text = [array objectAtIndex:indexPath.row];
return cell;
}
On Tableview's didselect method, what should i keep to have this kind of a functionality?
I searched a lot and there are lots of questions for this but couldn't find one for this.
So Please help me on this.
Thanks in advance.
You may be better off just subclassing UITableViewCell, as this would let you change the way the cells draw, and add a property or something of the sort to indicate this state.
To create the subclass, create a new file in Xcode, and select UITableViewCell as its superclass.
Then, within that subclass, you could implement a method called setStrikeThrough: like this that you can call on the cell you dequeue from the table:
- (void) setStrikeThrough:(BOOL) striked {
if(striked) {
// create image view here and display, if it doesn't exist
} else {
// hide image view
}
}
Then, in the view controller that holds the table, you'd call this in viewDidLoad to register your subclass with the table view:
[_tableView registerClass:[YourAmazingTableCell class] forCellReuseIdentifier:#"AmazingCellSubclass"];
You would then alter your tableView:cellForRowAtIndexPath: to be something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"AmazingCellSubclass";
YourAmazingTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[YourAmazingTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// here you would look up if this row should be selected
[cell setStrikeThrough:YES];
// Set up the remainder of the cell, again based on the row
cell.textLabel.text = #"chilli";
return cell;
}
Try this,
Add a NSMutableArray checkedCellArray, as property and alloc init.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UILabel *labelRecipe = [[UILabel alloc] initWithFrame:CGRectMake(50, 5, 600, 32)];
labelRecipe.backgroundColor = [UIColor clearColor];
labelRecipe.font = [UIFont systemFontOfSize:20.0f];
labelRecipe.tag = kRecipeTag;//a tag to label
[cell.contentView addSubview:labelRecipe];
UIImageView *checkedimg = [[UIImageView alloc]initWithFrame:CGRectMake(40, 20, 500, 5)];
[checkedimg setImage:[UIImage imageNamed:#"checked.png"];
checkedimg.tag = kCheckedImageTag;//a tag to imageView
[cell.contentView addSubview:checkedimg];
checkedimg.hidden = YES;
}
UILabel *labelRecipe = (UILabel *)[cell.contentView viewWithTag:kRecipeTag];
UIImageView *checkedimg = (UIImageView *)[cell.contentView viewWithTag:kCheckedImageTag];
if ([self.checkedCellArray containsObject:indexPath]) {
checkedimg.hidden = NO;
} else {
checkedimg.hidden = YES;
}
labelRecipe.text = [array objectAtIndex:indexPath.row];
return cell;
}
and in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (![self.checkedCellArray containsObject:indexPath]) {
[self.checkedCellArray addObject:indexPath];
}
NSArray* rowsToReload = [NSArray arrayWithObjects:indexPath, nil];
[UITableView reloadRowsAtIndexPaths:rowsToReload withRowAnimation:UITableViewRowAnimationNone];
}
Oky hear you can do like this
just subclass the tableview cell
in CustomCell.h file
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell
#property (nonatomic,retain)UIImageView *dashImageView; //add a property of image view
#end
in CustomCell.m file
#import "CustomCell.h"
#implementation CustomCell
{
BOOL isCellSelected; //add this to check
}
#synthesize dashImageView = _dashImageView; //synthesize it
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
isCellSelected = NO;//initially set it no
_dashImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.bounds.origin.x + 15, self.bounds.origin.y + 10, self.bounds.size.width, 15.0f)];
_dashImageView.backgroundColor = [UIColor redColor];
_dashImageView.tag = 12345;
_dashImageView.hidden = YES;
[self.contentView addSubview:_dashImageView];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if(selected)
{
UIImageView *dashImageVIew = (UIImageView *)[self viewWithTag:12345];
if(dashImageVIew)
{
if(!isCellSelected)
{
dashImageVIew.hidden = NO;
isCellSelected = YES;
}
else
{
dashImageVIew.hidden = YES;
isCellSelected = NO;
}
}
}
}
EDIT:2 *For selecting both section and row for the table view*
there is no change in the custom cell only change in the controller so that u hav to reflect what changes that u made to tableview cell i.e weather u select or deselect
since u want select section along with the selected row.(your requirement) there are various way to do that, but i go by using some model object which contains index section and row.
for that u need to create a subclass of NSObject and name it as MySelectedIndex then in
in MySelectedIndex.h file
#import <Foundation/Foundation.h>
#interface MySelectedIndex : NSObject<NSCoding>//to store and retrieve data like user defaults, for non-property list objects, confirms to NSCoding protocol
#property (nonatomic,retain) NSNumber *selectedRow;
#property (nonatomic,retain) NSNumber *selectedSection;
- (id)initWithSelectedRow:(NSNumber *)selRow andSelectedIndex:(NSNumber *)selSection;
#end
in MySelectedIndex.m file
#import "MySelectedIndex.h"
#implementation MySelectedIndex
#synthesize selectedSection = _selectedSection;
#synthesize selectedRow = _selectedRow;
- (id)initWithSelectedRow:(NSNumber *)selRow andSelectedIndex:(NSNumber *)selSection
{
self = [super init];
if(self)
{
_selectedRow = selRow;
_selectedSection = selSection;
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_selectedRow forKey:#"ROW"];
[aCoder encodeObject:_selectedSection forKey:#"SECTION"];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if(self)
{
_selectedRow = [aDecoder decodeObjectForKey:#"ROW"];
_selectedSection = [aDecoder decodeObjectForKey:#"SECTION"];
}
return self;
}
#end
now get back to controller where u are using the table
in .m file
import it #import "CustomCell.h"
and in the method
in viewController.m
#interface SampleViewController ()<UITableViewDataSource,UITableViewDelegate>
{
NSMutableArray *indexes;//to store in defaults
NSMutableArray *indexesRed;//to red from the defaults
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//...other stuff's
indexes = [[NSMutableArray alloc]init];//initilise your arrays
indexesRed = [[NSMutableArray alloc]init];
//after initilizing your array
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:#"SELECTED_CELLL"];
if(data != nil)
{
indexes = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[indexes retain];//you hav to retain the objects other wise u will get crash, make sure u will release it by proper memory mabagement (if u are not using ARC)
}
}
as u said u are using buttons to pop this viewcontroller so already u know where to place so put this in all the action methods(just replace where u are saving to user defaults )
and also read the comments that i put in the code
//put all these codes where u poping this viewcontroller
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:indexes];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:#"SELECTED_CELLL"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.navigationController popViewControllerAnimated:YES];
replace the cellForRowAtIndexPath by following code (i added in the below method)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
CustomTabedCell *Cell = [tableView dequeueReusableCellWithIdentifier:#"CELL"];
if(Cell == nil)
{
Cell = [[CustomTabedCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CELL"];
}
Cell.textLabel.text = #"Apple";
NSNumber *rowNum = [NSNumber numberWithInt:indexPath.row];
NSNumber *secNum = [NSNumber numberWithInt:indexPath.section];
__block BOOL isImageHidden = YES;
[indexes enumerateObjectsUsingBlock:^(MySelectedIndex *obj, NSUInteger idx, BOOL *stop)
{
if(obj.selectedRow == rowNum && obj.selectedSection == secNum)
{
isImageHidden = NO;
}
}];
Cell.dashImageView.hidden = isImageHidden;
[Cell.contentView bringSubviewToFront:Cell.dashImageView];//as i notised the red dash imageview appers below the text, but in your image it is appearing above the text so put this line to bring the imageview above the text if dont want commnent this
return Cell;
}
finally in the method didSelectRowAtIndexPath replace by following method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *selSection = [NSNumber numberWithInt:indexPath.section];
NSNumber *selRow = [NSNumber numberWithInt:indexPath.row];
if([indexes count] == 0)
{
MySelectedIndex *selectedIndx = [[MySelectedIndex alloc]initWithSelectedRow:selRow andSelectedIndex:selSection];
[indexes addObject:selectedIndx];
}
else if ([indexes count] == 1)
{
MySelectedIndex *singleIndex = [indexes objectAtIndex:0];
if(singleIndex.selectedSection == selSection & singleIndex.selectedRow == selRow)
{
[indexes removeAllObjects];
}
else
{
MySelectedIndex *selectedIndx = [[MySelectedIndex alloc]initWithSelectedRow:selRow andSelectedIndex:selSection];
[indexes addObject:selectedIndx];
}
}
else
{
__block BOOL addSelectedRow = NO;
__block int index = -1;
[indexes enumerateObjectsUsingBlock:^(MySelectedIndex *obj, NSUInteger idx, BOOL *stop) {
if(!((obj.selectedRow == selRow) & (obj.selectedSection == selSection)))
{
addSelectedRow = YES;
}
else
{
index = idx;
addSelectedRow = NO;
*stop = YES;
}
}];
if(addSelectedRow)
{
MySelectedIndex *selectedIndx = [[MySelectedIndex alloc]initWithSelectedRow:selRow andSelectedIndex:selSection];
[indexes addObject:selectedIndx];
}
else
{
if(index >= 0)
{
[indexes removeObjectAtIndex:index];
}
}
}
NSLog(#"%#",indexes.description);
[tableView reloadData];
}
edit for not able to select more than 13 row's
in viewDidLoad
do like this
indexes = [[NSMutableArray alloc]init];
indexesRed = [[NSMutableArray alloc]init];
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:#"SELECTED_CELLL"];
if(data != nil)
{
indexes = [[NSKeyedUnarchiver unarchiveObjectWithData:data] retain]; //hear only u retain it
NSLog(#"%#",indexes.description);//check the description, how many objects are there in the array
NSLog(#"indexes->%d",[indexes count]);
}
//[indexes retain];//comment this
} //end of `viewDidLoad`
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTabedCell *Cell = [tableView dequeueReusableCellWithIdentifier:#"CELL"];
if(Cell == nil)
{
Cell = [[CustomTabedCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CELL"];
}
Cell.textLabel.text = #"Apple";
__block BOOL isImageHidden = YES; //remove that __block qualifier
// __block NSInteger currentRow = indexPath.row;
// __block NSInteger currentSection = indexPath.section;
// [self.indexes enumerateObjectsUsingBlock:^(MySelectedIndex *obj, NSUInteger idx, BOOL *stop)
// {
// NSInteger rowNum = [obj.selectedRow integerValue];
// NSInteger secNum = [obj.selectedSection integerValue];
// if(rowNum == currentRow && secNum == currentSection)
// {
// isImageHidden = NO;
// }
// }];
//comment block code and use simple for loop, looping through each obj slightly faster
for(int k = 0;k < [indexes count];k++)
{
MySelectedIndex *seletedIndex = [indexes objectAtIndex:k];
NSInteger row = [seletedIndex.selectedRow integerValue];
NSInteger sec = [seletedIndex.selectedSection integerValue];
if(row == indexPath.row & sec == indexPath.section)
{
isImageHidden = NO;
}
}
Cell.dashImageView.hidden = isImageHidden;
[Cell.contentView bringSubviewToFront:Cell.dashImageView];//as i notised the red dash imageview appers below the text, but in your image it is appearing above the text so put this line to bring the imageview above the text if dont want commnent this
return Cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *selSection = [NSNumber numberWithInt:indexPath.section];
NSNumber *selRow = [NSNumber numberWithInt:indexPath.row];
if([indexes count] == 0)
{
MySelectedIndex *selectedIndx = [[MySelectedIndex alloc]initWithSelectedRow:selRow andSelectedIndex:selSection];
[indexes addObject:selectedIndx];
}
else if ([indexes count] == 1)
{
MySelectedIndex *singleIndex = [indexes objectAtIndex:0];
NSInteger rowNumInInt = [singleIndex.selectedRow integerValue];
NSInteger sectionInInt = [singleIndex.selectedSection integerValue];
if(sectionInInt == indexPath.section & rowNumInInt == indexPath.row)
{
[indexes removeAllObjects];
}
else
{
MySelectedIndex *selectedIndx = [[MySelectedIndex alloc]initWithSelectedRow:selRow andSelectedIndex:selSection];
[indexes addObject:selectedIndx];
}
}
else
{
BOOL addSelectedRow = NO;
int index = -1;
for(int j = 0; j < [indexes count];j++)
{
MySelectedIndex *selectedObj = [indexes objectAtIndex:j];
NSInteger rowInt = [selectedObj.selectedRow integerValue];
NSInteger sectionInt = [selectedObj.selectedSection integerValue];
if(!(rowInt == indexPath.row && sectionInt == indexPath.section))
{
addSelectedRow = YES;
}
else
{
index = j;
addSelectedRow = NO;
// *stop = YES;
}
}
if(addSelectedRow)
{
MySelectedIndex *selectedIndx = [[MySelectedIndex alloc]initWithSelectedRow:selRow andSelectedIndex:selSection];
[indexes addObject:selectedIndx];
}
else
{
if(index >= 0)
{
[indexes removeObjectAtIndex:index];
}
}
}
// [tableView reloadData];
NSLog(#"indexes count->%d",[indexes count]);//check each time by selecting and deselectin weateher it is working or not
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
thats it simple .. :)
hope this helps u .. :)
Try This it work good
#import "ViewController.h"
#interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
{
UITableView *menuTableView;
NSMutableArray *colorsArray,*tagvalueArray;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
menuTableView=[[UITableView alloc]initWithFrame:CGRectMake(0, 60, 320, 404) style:UITableViewStyleGrouped];
menuTableView.delegate=self;
menuTableView.dataSource=self;
menuTableView.separatorColor=[UIColor grayColor];
[self.view addSubview:menuTableView];
NSArray *serverResponseArray=[[NSArray alloc]initWithObjects:#"red",#"yellow",#"pink",#"none", nil]; // consider this array as the information you receive from DB or server
colorsArray =[[NSMutableArray alloc]init];
tagvalueArray =[[NSMutableArray alloc]init];
for (int i=0; i<serverResponseArray.count; i++) {
[colorsArray addObject:serverResponseArray[i]];
[tagvalueArray addObject:#"0"];
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return colorsArray.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 40;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
cell.textLabel.text =colorsArray[indexPath.row];
if ([[tagvalueArray objectAtIndex:indexPath.row]intValue]==1) {
UIImageView *checkedimg=[[UIImageView alloc]initWithFrame:CGRectMake(40, 20, 500, 5)];
checkedimg.backgroundColor=[UIColor redColor];
[cell.contentView addSubview:checkedimg];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",colorsArray[indexPath.row]);
[tagvalueArray replaceObjectAtIndex:indexPath.row withObject:#"1"];
[menuTableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end