I try to do so as in the picture shown in red square.
I need by clicking a user opens a plate and DatePicker. For this I use Expandable UITableView (http://www.wannabegeek.com/?p=338). But I can not understand how to do so in the section could is one element (eg DatePicker) and by clicking on the section shows exactly DatePicker. Now, if at least two elements, then the string is not displayed as a section, but as just a string containing no more elements. And as if I did not change the size of the prototype cell size does not change and I can not see completely DatePicker. Now my DatePicker is behind the text of the cell (which is logical)
Two main questions: how to change the size of the cell, that is normal to see DatePicker and how to make that you can have only one item in the list
In StoryBoard I see:
In simulator:
May have the decision easier?
I use the code:
// Exampl2eController.m
#import "Example2Controller.h"
#implementation Example2Controller
#synthesize dataModel = _dataModel;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_dataModel = [NSMutableArray arrayWithObjects:
[NSMutableArray arrayWithObjects:#"Row 1a", #"Row 2a", #"Row 3a", nil],
[NSMutableArray arrayWithObjects:#"Row 1b", #"Row 2b", nil],
[NSMutableArray arrayWithObjects:#"Row 1c", #"Row 2c", #"Row 3c", #"Row 4c", nil],
[NSMutableArray arrayWithObjects:#"Row 1d", nil],
nil];
}
- (NSInteger)numberOfSectionsInTableView:(ExpandableTableView *)tableView
{
// Return the number of sections.
return [_dataModel count];
}
- (NSInteger)tableView:(ExpandableTableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([_dataModel count] == 0) {
return 0;
}
// Return the number of rows in the section.
return [[_dataModel objectAtIndex:section] count];
}
- (UITableViewCell *)tableView:(ExpandableTableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"RowCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.text = [[_dataModel objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
// just change the cells background color to indicate group separation
cell.backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
cell.backgroundView.backgroundColor = [UIColor colorWithRed:232.0/255.0 green:243.0/255.0 blue:1.0 alpha:1.0];
return cell;
}
- (UITableViewCell *)tableView:(ExpandableTableView *)tableView cellForGroupInSection:(NSUInteger)section
{
static NSString *CellIdentifier = #"GroupCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.text = [NSString stringWithFormat: #"Group %d (%d)", section, [self tableView:tableView numberOfRowsInSection:section]];
// We add a custom accessory view to indicate expanded and colapsed sections
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ExpandableAccessoryView"] highlightedImage:[UIImage imageNamed:#"ExpandableAccessoryView"]];
UIView *accessoryView = cell.accessoryView;
if ([[tableView indexesForExpandedSections] containsIndex:section]) {
accessoryView.transform = CGAffineTransformMakeRotation(M_PI);
} else {
accessoryView.transform = CGAffineTransformMakeRotation(0);
}
return cell;
}
// The next two methods are used to rotate the accessory view indicating whjether the
// group is expanded or now
- (void)tableView:(ExpandableTableView *)tableView willExpandSection:(NSUInteger)section {
UITableViewCell *headerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
[UIView animateWithDuration:0.3f animations:^{
headerCell.accessoryView.transform = CGAffineTransformMakeRotation(M_PI - 0.00001); // we need this little hack to subtract a small amount to make sure we rotate in the correct direction
}];
}
- (void)tableView:(ExpandableTableView *)tableView willContractSection:(NSUInteger)section {
UITableViewCell *headerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
[UIView animateWithDuration:0.3f animations:^{
headerCell.accessoryView.transform = CGAffineTransformMakeRotation(0);
}];
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(ExpandableTableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (BOOL)tableView:(ExpandableTableView *)tableView canEditSection:(NSInteger)section {
return YES;
}
// Override to support editing the table view.
- (void)tableView:(ExpandableTableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView beginUpdates];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[[_dataModel objectAtIndex:indexPath.section] removeObjectAtIndex:indexPath.row];
// cellVisibleForIndexPath: isn't strictly required sicne the table view will determine if the
// the row at that indexPath is actually visible, and do the appropriate manipulation
if ([(ExpandableTableView *)tableView cellVisibleForIndexPath:indexPath]) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
if ([[_dataModel objectAtIndex:indexPath.section] count] == 0) {
[_dataModel removeObjectAtIndex:indexPath.section];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
} else {
[tableView reloadSectionCellsAtIndexes:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
}
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
[tableView endUpdates];
}
// Override to support rearranging the table view.
- (void)tableView:(ExpandableTableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(ExpandableTableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
- (BOOL)tableView:(ExpandableTableView *)tableView canRemoveSection:(NSUInteger)section {
return YES;
}
#end
There is an ivar called: _ungroupSingleElement set it to false and then you disable this feature
Related
In a UITableView Controller, I have just added 'swipe to delete' by implementing tableView: commitEditingStyle: forRowAtIndexPath. Additionally, the rows can be selected to expand showing more content.
The undesired result after swiping:
The two lower rows remain in view after swiping until about about 0.5 seconds after the undelete animation completes.
A screenshot of IB:
The cell's contents have grown into the lower cell without it showing that it has been selected. (Selection causes the cell to increase height and give it a grayish background color.) This is occurring on every row in 2 similarly operating view controllers.
I have tried (without success) to intercept the 'selection' in several UITableViewDelegate methods, and cannot find out how to stop this from occurring. I have also tried setting the IB dynamic prototype cells to height: 85.
Looking for ideas on how to prevent this expansion from occurring.
EDIT
- (void)viewDidLoad {
....
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = kCellHeight;
....
}
#pragma mark - TableView delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
NSInteger *rows = (NSInteger *)[sectionInfo numberOfObjects];
if (!self.rowsInSection)
self.rowsInSection = rows;
if (rows > 0)
return [sectionInfo numberOfObjects];
else {
[tableView setSeparatorColor:[UIColor clearColor]];
[tableView setBounces:NO];
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = self.rowsInSection > 0 ? #"numberIdentifier" : #"noNumbersIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
if (self.rowsInSection > 0)
[self configureCell:cell atIndexPath:indexPath];
else
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// [self.arrayOfIndexPaths addObject:indexPath];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
if (selectedIndexPath) {
if (tableView.editing)
return 85.0;
else if (selectedIndexPath.row == indexPath.row)
return 185.0;
}
return 85.0;
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)path {
if (tableView.editing)
return nil;
// If real rows exist, return the path, making row selectable
if (self.rowsInSection > 0)
return path;
// Otherwise do not allow the row to be selected
return nil;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][0];
if ([sectionInfo numberOfObjects] > 0)
// Return the contentView to stop the header from sliding with delete
return [tableView dequeueReusableCellWithIdentifier:#"numberHeaderIdentifier"].contentView;
else
return [tableView dequeueReusableCellWithIdentifier:#"emptyHeaderIdentifier"];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 75;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Number *aNumber = [self.fetchedResultsController objectAtIndexPath:indexPath];
[cell configureSubviewsInCell:cell withNumber:aNumber];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView beginUpdates];
[tableView endUpdates];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
}
}
You should set the hidden property of the labels that you don't want to show when the table view cell is not selected. For example:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Number *aNumber = [self.fetchedResultsController objectAtIndexPath:indexPath];
UILabel *label1 = (UILabel *)[cell.contentView viewWithTag:501];
label1.text = [aNumber valueForKey:#"number"];
if (!cell.selected)
{
label1.hidden = YES;
}
else
{
label1.hidden = NO;
}
.....
}
Then in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView beginUpdates];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *label1 = (UILabel *)[cell.contentView viewWithTag:501];
label1.text = [aNumber valueForKey:#"number"];
label1.hidden = NO;
[tableView endUpdates];
}
You should look into subclassing UITableViewCell so you don't have to use tags to access subviews.
The 'hiding' solution posted by beowulf is a valid option. In addition and because the swipe (to begin editing) was causing subviews in the cell to become 'unclipped', a method needed to be overrided, like so:
// this method is called as the swipe to delete is started
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
// only hide for unexpanded (unselected) cells
if ([self.selectedRowIndex compare:indexPath] != NSOrderedSame)
{
NumberTableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
// a cell subclass method to hide/unhide subviews that fall into
// the next cell below
[cell subViewsInCellShouldBeHidden:YES];
}
}
I have a tableview in which i have provided checkmarks as a accessory to multiple cells.
Now I want to get values of all those cells having checkmarks.
#import "HealthIssues.h"
#interface HealthIssues ()<UITableViewDataSource,UITableViewDelegate>
{
NSIndexPath* checkedIndexPath;
}
#property (nonatomic, retain) NSIndexPath* checkedIndexPath;
#end
#implementation HealthIssues
#synthesize HealthIssuesTV;
#synthesize checkedIndexPath;
- (void)viewDidLoad {
[super viewDidLoad];
PickerList=[[NSArray alloc]initWithObjects:#"None" ,#"Diabetes", #"Heart Problem" , #"Thyroid" , #"Over Weight" , #"Kidney Issues" , #"Lever Issues" , #"Vitamins Deficiency" , #"Blood Pressure" , nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [PickerList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==Nil) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
if (indexPath.row == 0){
if ([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
cell.textLabel.text = [PickerList objectAtIndex:indexPath.row];
cell.tintColor=[UIColor blueColor];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
{
int z=0;
if (indexPath.row==0)
{
NSArray *visibleCells = [tableView visibleCells];
for (UITableViewCell *cell in visibleCells)
{
if (z==0)
{
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
z++;
}
else
{
[cell setAccessoryType:UITableViewCellAccessoryNone];
z++;
}
}
}
else
{
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone)
{
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else
{
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
}
[tableView reloadData];
}
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
#end
This Works perfect for me as per my requirements. now i want to store selected rows in dictionary.
#interface selectUsers ()
{
NSMutableArray *selected_ids;
}
- (void)viewDidLoad {
[super viewDidLoad];
selected_ids = [[NSMutableArray alloc]init];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *_id = [[yourarray objectAtIndex:indexPath.row]valueForKey:#"_id"];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
[selected_ids removeObject:_id];
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
[selected_ids addObject:_id];
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}
}
Use selected_ids array where you want.
Try to get values from your data source of array and get all selected rows of UITableView:
Following code will give you all indexpaths of selected rows:
NSArray *arrIndexpaths = [YourTableView indexPathsForSelectedRows]; // Returns indexpaths for multiple selection in Table view.
Then Get value from the array by indexpath.row and indexpath.section whatever you used during in data source method.
First of all, you should do:
tableView.allowsMultipleSelection = YES;
Then you can get list of selected rows by:
NSArray *selectedIndexPaths = [self.tableView indexPathsForSelectedRows];
As you have now list of selected rows, you can get row or data of row.
You can use array for this.
- (void)viewDidLoad
{
arrData=[[NSMutableArray alloc]init];
}
On didSelectRowAtIndexPath add your value into array.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[arrData addObject:[YourDataArray objectAtIndex:indexPath.row]];
}
May be it will help you.
try this..
NSMutableArray *selectedIndexes ; // instance variable, do initialization in viewDidLoad
i am assuming that you are using didSelectRowAtIndexPath for selecting cell (i mean not a custom button action)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
if ([selectedIndexes containsObject:indexPath])
{
[selectedIndexes removeObject:indexPath];
}
else
{
[selectedIndexes addObject:indexPath];
}
}
Now you can get all selected cells using index values in selectedIndexes array
for ex UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:1];
edit :
remove all objects from selectedIndexes after selection process is over
#interface RestTableViewController ()<UISearchBarDelegate>{
NSMutableSet *setTemp;
// NSMutableArray *setTemp;
}
In ViewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
setTemp = [[NSMutableSet alloc] initWithCapacity:1];
. . .
}
In cellForRowAtIndexPath
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self markCell:cell atIndex:indexPath.row];
Create a Method
- (void)markCell:(UITableViewCell *)cell atIndex:(NSInteger)index{
if ([setTemp containsObject:[NSNumber numberWithInteger:index]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
In didSelectRowAtIndexPath
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
{
// Restaurent is my Object File
Restaurent *obj = [restMutableArray objectAtIndex:indexPath.row];
if ([setTemp containsObject:[NSNumber numberWithInteger:indexPath.row]]) {
[setTemp removeObject:[NSNumber numberWithInteger:indexPath.row]];
// tempMainArray is an array which manages the title of selected or deselected Rows . . .
[tempMainArray removeObject:obj.strTitle];
NSLog(#"Selected Row Data %#",tempMainArray);
}
else {
[setTemp addObject:[NSNumber numberWithInteger:indexPath.row]];
[tempMainArray addObject:obj.strTitle];
NSLog(#"Selected Row Data %#",tempMainArray);
}
[self markCell:cell atIndex:indexPath.row];
}
To Select All The Cell
#pragma mark : Select All Data Method. . .
- (IBAction)actionBtnClicked:(id)sender {
{
[setTemp removeAllObjects];
for (int i = 0 ; i < [restMutableArray count]; i++) {
Restaurent *obj = [restMutableArray objectAtIndex:i];
[tempMainArray addObject:obj.strTitle];
[setTemp addObject:#(i)];
}
NSLog(#"%#",tempMainArray);
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.effectsTableView beginUpdates];
Effect *effectToBeDeleted =self.effectsArray[indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
[self.effectsArray removeObjectAtIndex:indexPath.row];
[self.effectsTableView endUpdates];
}
}
The above function should in theory delete the rows as they are slided and the delete button is pressed. However the row does not delete instead is visible even after the
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
is called. And after the user scrolls to the bottom of the UITableView, while loading the last row, the app obviously crashes with "*** -[__NSArrayM objectAtIndex:]: index 9 beyond bounds [0 .. 8]" error since one of the objects has been deleted from the array.
the cellForRowAtIndexPath is as follows:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.effectsArray)
{
[self loadEffectsInArray];
}
static NSString *cellIdentifier = #"EffectsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
Effect *effectCellEffect = [self.effectsArray objectAtIndex:indexPath.row];
NSString *effectCellText = effectCellEffect.name;
[cell.textLabel setText:effectCellText];
cell.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
return cell;
}
Below is the entire .m file for better context:
#import "EffectsManagementTableViewController.h"
#import "Effect+Manage.h"
#import "VLOGAppDelegate.h"
#import "AddEffectViewController.h"
#import "EffectFilterProperty+Manage.h"
#import "Effect.h"
#interface EffectsManagementTableViewController ()
#property (strong, nonatomic) IBOutlet UITableView *effectsTableView;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong) NSMutableArray *effectsArray;
#property (nonatomic, strong) NSString *currSelectedRowTitle;
#end
#implementation EffectsManagementTableViewController
-(NSString *)currSelectedRowTitle
{
if(!_currSelectedRowTitle)
{
_currSelectedRowTitle = #"";
}
return _currSelectedRowTitle;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
VLOGAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;
self.effectsTableView.dataSource = self;
self.effectsTableView.delegate = self;
}
-(void)viewWillAppear:(BOOL)animated
{
[self loadEffectsInArray];
[self.effectsTableView reloadData];
[self.effectsTableView setNeedsDisplay];
[self.effectsTableView setNeedsLayout];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (!self.effectsArray)
{
[self loadEffectsInArray];
}
return [self.effectsArray count];
}
//4
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.effectsArray)
{
[self loadEffectsInArray];
}
static NSString *cellIdentifier = #"EffectsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
//6
Effect *effectCellEffect = [self.effectsArray objectAtIndex:indexPath.row];
NSString *effectCellText = effectCellEffect.name;
//7
[cell.textLabel setText:effectCellText];
//[cell.detailTextLabel setText:#"5 stars!"];
cell.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
//cell.backgroundColor = [UIColor blackColor];
//cell.textLabel.textColor = [UIColor whiteColor];
//cell.detailTextLabel.textColor = [UIColor grayColor];
//cell.textLabel.highlightedTextColor = self.effectsTableView.tintColor;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.effectsTableView beginUpdates];
Effect *effectToBeDeleted =self.effectsArray[indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
[self.effectsArray removeObjectAtIndex:indexPath.row];
//[self loadEffectsInArray];
[self.effectsTableView endUpdates];
//[self.effectsTableView reloadData];
//[self.effectsTableView setNeedsLayout];
//[self.effectsTableView setNeedsDisplay];
}
}
-(void)deleteEffectWithName:(NSString *)effectName
{
NSArray *efpForEffectToBeDeleted = [EffectFilterProperty getEffectFilterPropertiesForEffectName:effectName forImmediateEngagement:NO forManagedObjectContext:self.managedObjectContext];
Effect *effectToBeDeleted = [Effect getEffectWithName:effectName forManagedObjectContext:self.managedObjectContext];
for (int i = 0; i < efpForEffectToBeDeleted.count; i++)
{
EffectFilterProperty *currEFP = efpForEffectToBeDeleted[i];
currEFP.relatedEffect = nil;
currEFP.relatedFilterProperty = nil;
[self.managedObjectContext deleteObject:currEFP];
}
[self.managedObjectContext deleteObject:effectToBeDeleted];
NSError *err = nil;
[self.managedObjectContext save:&err];
if (err != nil) {
//Problem while saving
}
}
-(void)loadEffectsInArray
{
self.effectsArray = [[Effect getAllEffectsForManagedObjectContext:_managedObjectContext] mutableCopy];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Effect *effectCellEffect = [self.effectsArray objectAtIndex:indexPath.row];
self.currSelectedRowTitle = effectCellEffect.name;
[self performSegueWithIdentifier:#"PushedByTableView" sender:self];
}
/*
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<##"reuseIdentifier"#> forIndexPath:indexPath];
// Configure the cell...
return cell;
}
*/
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"PushedByTableView"])
{
AddEffectViewController *destinationViewController = segue.destinationViewController;
NSString *selectedRowText = self.currSelectedRowTitle;
destinationViewController.effectToManage = [Effect getEffectWithName:selectedRowText forManagedObjectContext:self.managedObjectContext];
}
}
#end
What am I doing wrong here?
where are you beginning your updates, please add
[self.effectsTableView beginUpdates];
before deleting your row and no need of reloading the table when you are writing the begin updates and end updates.
Please don't remove the object from array before deleting the row.
IT'S WORKING
At end of your commitEditingStyle method add this line this will help you
[TableViewForFirstView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
try this code to add beginUpdatesmethod before delete called
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.effectsTableView beginUpdates];
Effect *effectToBeDeleted =self.effectsArray[indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
[self.effectsArray removeObjectAtIndex:indexPath.row];
[self loadEffectsInArray];
[self.effectsTableView endUpdates];
}
Try this code:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
Effect *effectToBeDeleted =[self.effectsArray objectAtIndex:indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsArray removeObjectAtIndex:indexPath.row];
[self loadEffectsInArray];
[self.effectsTableView reloadData];
}
As this message, it's crash for reason out of bound, so try check the array index before assign:
Effect *effectToBeDeleted = self.effectsArray > indexPath.row ? self.effectsArray[indexPath.row] : nil;
And
if(self.effectsArray.count > indexpath.row)
[self.effectsArray removeObjectAtIndex:indexPath.row];
else
NSlog("out of bound");
So I have been creating a tableviewcontroller that handles my tableview and its tableviewcells..
Here's the code––
ItemsViewController.h
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface ItemsViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
-(IBAction)addNewItem:(id)sender;
#end
ItemsViewController.m
#implementation ItemsViewController
-(id) init{
self= [super initWithStyle:UITableViewStyleGrouped];
if (self) {
UINavigationItem *n= [self navigationItem];
[n setTitle:#"Homepwner"];
for (int i=0; i<5; i++) {
[[BNRItemStore sharedStore] createItem];
}
}
return self;
}
- (id)initWithStyle:(UITableViewStyle)style
{
return [self init];
}
- (void)viewDidLoad
{
NSLog(#"ItemsView loaded");
[super viewDidLoad];
UIBarButtonItem *bbi= [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addNewItem:)];//Target-Action pair..
self.navigationItem.rightBarButtonItem= bbi;
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
}
-(void)viewWillAppear:(BOOL)animated{
NSLog(#"ItemsView appearing");
[super viewWillAppear:animated];
[[self tableView] reloadData];
}
-(IBAction)addNewItem:(id)sender{
BNRItem *newItem= [[BNRItemStore sharedStore] createItem];
NSLog(#"%d",[[[BNRItemStore sharedStore] allItems] count]);
int newRow = [[[BNRItemStore sharedStore] allItems] indexOfObject:newItem];
NSIndexPath *ip= [NSIndexPath indexPathForRow:newRow inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationTop];
}
//Row Selection
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.row<[[BNRItemStore sharedStore] allItems].count){
NSLog(#"Row# %d selected",indexPath.row);
DetailViewController *detailViewController= [[DetailViewController alloc] init];
NSArray *items= [[BNRItemStore sharedStore] allItems];
BNRItem *item= [items objectAtIndex:indexPath.row];
detailViewController.item=item;//BNRItem at the selected indexPath.
//Push it onto the top of the navigation controller's stack
[[self navigationController] pushViewController:detailViewController animated:YES];
}
else{
return;
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"Test1");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
NSLog(#"Current section- %d",section);
return [[[BNRItemStore sharedStore] allItems] count]+1 ;//no. of rows (5)+'No more items' row
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"hello");
// NSLog(#"%#",headerView);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (!cell) {
cell= [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (indexPath.row<[[BNRItemStore sharedStore] allItems].count) {
[[cell textLabel] setText:[[[[BNRItemStore sharedStore] allItems] objectAt Index:indexPath.row] description]];
}
else if (indexPath.row== [[BNRItemStore sharedStore] allItems].count)
{
[[cell textLabel] setText:#"No more items"];
}
return cell;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
if (self.editing) {
NSLog(#"Editing is on");
self.navigationItem.rightBarButtonItem.enabled=NO;
if (indexPath.row==[[BNRItemStore sharedStore] allItems].count) {
[tableView cellForRowAtIndexPath:indexPath].hidden=YES;
return NO;// Do not make 'No more items' editable.
}
}
else{//When the user is out of editing mode
NSLog(#"editing done");
[self.tableView cellForRowAtIndexPath:indexPath].hidden=NO;
self.navigationItem.rightBarButtonItem.enabled=YES;
}
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",NSStringFromSelector(_cmd));
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSLog(#"Deletion is on");
// Delete the row from the data source
NSArray *items= [[BNRItemStore sharedStore] allItems];
BNRItem *p= [items objectAtIndex:[indexPath row]];
[[BNRItemStore sharedStore] removeItem:p];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
[[BNRItemStore sharedStore] moveItemAtIndex:fromIndexPath.row toIndex:toIndexPath.row];
}
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedIndexPath{
if (proposedIndexPath.row==[[BNRItemStore sharedStore] allItems].count) {// 'No more items' row
return [NSIndexPath indexPathForRow:proposedIndexPath.row-1 inSection:0];
}
return proposedIndexPath;
}
#end
When the editing mode is on i.e when i tap Edit button on the NavBar the Add button grays out and the 'No more items' rows becomes hidden. After exiting Edit mode (by tapping 'Done' button) the Add button becomes selectable and the 'No more items' row unhides.. This is all fine when i perform editing by first entering the Edit mode and then exiting the Edit mode. But when instead of using the above way, i use swipe to delete feature, the view doesn't realize the above functionality (i.e. Ungraying/Re-enabling the Add button once i'm done doing a deletion using the swipe to delete thing. When i swipe across a cell (so as to bring up the delete button on the right side of the cell and graying out the Add button in the process) and choose not to press the 'Delete' button by just retapping on the cell (so that the Delete button goes away) the Add button does not update itself so as to get enabled.. What to do about. Pls carefully examine my code first and give recommendations accordingly..
use this tableView Delegate mathod
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
Please Utilize the Apple Library- UItableView
I am working with the tableview and working well with that. But i stuck at one place where i want to tap the cell and on the tap the cell should expand its height and and the cell below it should move down according to the expanded height.
The code which i am using is as follows.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[cell.textLabel setNumberOfLines:0]; // unlimited number of lines
gratitude *grat = [gratitude_list objectAtIndex:indexPath.row];
cell.textLabel.text=grat.gratitude;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[cell.textLabel setFont:[UIFont fontWithName:#"Lucida Sans" size:20]];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
gratindex > -1;
if (gratindex == indexPath.row) {
[self collapseSubItemsAtIndex:indexPath];
gratindex = -1;
}
else {
BOOL shouldCollapse = gratindex > -1;
if (shouldCollapse) {
[self collapseSubItemsAtIndex:gratindex];
}
gratindex = (shouldCollapse && indexPath.row > gratindex) ? indexPath.row - [[gratitude_list objectAtIndex:gratitude_list] count] : indexPath.row;
[self expandItemAtIndex:gratitude_list];
}
[self.gratitude_tableview endUpdates];
}
- (void)expandItemAtIndex:(int)index
{
NSMutableArray *indexPaths = [NSMutableArray new];
int insertPos = index + 1;
for (int i = 0; i < [gratitude_list count]; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:insertPos++ inSection:0]];
}
[self.gratitude_tableview insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.gratitude_tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (void)collapseSubItemsAtIndex:(int)index {
NSMutableArray *indexPaths = [NSMutableArray new];
for (int i = index + 1; i <= index + [[gratitude_list objectAtIndex:index] count]; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[self.gratitude_tableview deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
}
Please help me out if i am using wrong approch please help me out.
Please check my answer. If you need any more detailing then you can ask me in comment.
UPDATED:
ANd in .h file
#interface tableViewDemoViewController : UITableViewController
{
NSIndexPath *selectedCellIndexPath;
BOOL clickedAgain;
int heights;
}
And in .m file
#import "tableViewDemoViewController.h"
#interface tableViewDemoViewController ()
#end
#implementation tableViewDemoViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
clickedAgain = YES;
heights =0;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 15;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.textLabel.text = [NSString stringWithFormat:#"This is cell %d",indexPath.row ];
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
if ([selectedCellIndexPath compare:indexPath] == NSOrderedSame && !clickedAgain)
{
heights =40;
clickedAgain =YES;
}
else
{
heights =80;
clickedAgain = NO;
}
[tableView beginUpdates];
selectedCellIndexPath = indexPath;
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(selectedCellIndexPath != nil
&& [selectedCellIndexPath compare:indexPath] == NSOrderedSame )
{
return heights;
}
return 40;
} #end