UITableView is not populated because tableView:cellForRowAtIndexPath is never invoked - objective-c

My UITableView is not populated because:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
is never invoked.
This is how I initialize the table:
self.recentScannedItems = [[[UITableView alloc] initWithFrame:kLastScannedPortrait style:UITableViewStylePlain] autorelease];
[self.recentScannedItems setDelegate:self];
[self.recentScannedItems setDataSource:self];
[self.view addSubview:recentScannedItems];
what am I missing ?

Have you implemented correctly the datasource methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
// Return the number of sections.
return NumberOfSections;
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return NumberOfRows;
}
If you are not implementing this methods, or if you are returning 0 in them, cellForRowAtIndexPath won't be called

Does your class comply to UITableViewDataSource? Like:
#interface mySuperClass : UIViewController <UITableViewDataSource, UITableViewDelegate>

Related

UITableView removing and adding rows

I have an NSMutableArray containing sequential numbers 1,2...,n and have a UITableView that displays cells vertically ascending and in order. How would I go about deleting a row, m between 1 and n, both visually and in the data, as well as in the NSMutableArray, and then decrement by 1 the value of all cells that followed the deleted cell in the data and visually such that the firstResponder does not resign control like a reloadData method call would?
#interface TableController : UIViewController
#property (nonatomic, retain) NSMutableArray *data;
#end
#implementation TableController
#synthesize data;
- (id)init
{
if(self = [super init]) {
data = [NSArray arrayWithObjects:#"1",#"2",#"3",#"4",#"5",nil];
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [UITableViewCell new];
[cell.textLabel setText:[data objectAtRow:indexPath.row]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 20;
}
#end
How would I remove row 3 and then make rows four and five then become 3 and 4 respectively?
Just edit your view model and then reload the table.
[data removeObjectAtIndex:2];
[tableView reloadData];
Another option is the UITableView method deleteRowsAtIndexPaths:withRowAnimation:. This approach is UI only, you must also update your view model in case the cells ever get reloaded at a later time. The advantage of this approach is that only the cells you specify get changed. Existing cells are not reloaded.
If the cell you are deleting is your first responder then you could handle this case by telling the next cell to become first responder.
For user driven deletion, your [tableview dataSource] should implement the method tableView:commitEditingStyle:forRowAtIndexPath:.
Here's an implementation from my code…
-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(editingStyle == UITableViewCellEditingStyleDelete)
{
[[STLocationsModel sharedModel] deleteLocationAtIndex: [indexPath row]];
[tableView deleteRowsAtIndexPaths: #[indexPath] withRowAnimation: UITableViewRowAnimationLeft];
}
}
To allow editing, you'll also want…
-(BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
To get the table in to editing mode to allow deletions, you need to put it in to editing mode. You could place this in your viewDidLoad, or you might toggle it with a button:
[[self tableView] setEditing:YES animated:NO];
And if you also want to be able to make selections while the table is edited (again, this could go in your viewDidLoad…
[[self tableView] setAllowsSelectionDuringEditing: YES];

UITableView does not enter editing mode

I've tried many times to create a table view and delete certain rows, I even asked this question here before and implemented what they advised but yet failed to even get my table
ViewController.h
#interface XYZViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
#property (strong, nonatomic) UITableView *myTable;
#property (strong, nonatomic) NSMutableArray *names;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *editButton;
- (IBAction)editMyTable:(id)sender;
#end
ViewController.m
#implementation XYZViewController
#synthesize names, myTable, editButton;
- (void)viewDidLoad
{
[super viewDidLoad];
//input values into the mutable array
names = [[NSMutableArray alloc]initWithObjects:
#"Bob",
#"Chris",
#"Tom"
, nil];
editButton = self.editButtonItem;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return #"Friends";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.names count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//create an identifier
static NSString *identifier;
//create the cell with the identifier
UITableViewCell *cell = [myTable dequeueReusableCellWithIdentifier:identifier];
//check if cell is nil
if (cell == nil) {
//assign cell
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
//assign the names of the array to each cell
cell.textLabel.text = [names objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)editMyTable:(id)sender
{
[editButton setTitle:#"Done"];
[myTable setEditing:YES animated:YES];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[myTable setEditing:editing animated:animated];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
//remove from array
[names removeObjectAtIndex:indexPath.row];
//remove from tableView
[myTable deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Image: http://postimg.org/image/g9wqwuo6v/
Any help is much appreciated! Thank you in advance! :)
It appears that your issue is that you have not wired up your myTable property. It is not an IBOutlet and nowhere in your code do you establish the connection. When you call [myTable setEditing:YES animated:YES]; it is sending it to a nil table. You can verify this by printing out myTable's value before calling the edit method: NSLog(#"%#", myTable);.
Also you should remove your overriding of setEditing:animated: since you are a UIViewController subclass and not a UITableView subclass. Just making your initial call in your IBAction should be enough.

What would be the most elegant way to implement this without multiple inheritance in objective-c?

Basically I have classes of objects whose main function is to act as tableView Delegate.
I want to add that to some superclass. Of course there is only 1 superclass and I want flexibility. What about if latter I want to add this capability to other classes at will?
Basically these are codes used to handle tables where users can delete or rearrange rows, etc.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSAssert(false, #"Should be called at child View");
return nil;
}
-(Class) classBookmarked
{
assert(false);
return nil;
}
-(void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[self.delegate.tvDelegated setEditing:editing animated:animated];
if (!editing)
{
NSArray * newIds = _arManagedObjectArray.convertArrayOfNSManagedObjectToItsDefaultSelector;
[self varManagedObjectArrayUpdated];
[BGBookmarkStorer vReportBookmarkStatusToServer:newIds Flag:#"update" withClass:self.classBookmarked];
}
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = indexPath.row;
[self deleteARow:row];
}
-(void)deleteARow:(NSUInteger) row
{
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:0];
[_arManagedObjectArray removeObjectAtIndex:row];
[self.delegate.tvDelegated deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self varManagedObjectArrayUpdated];
}
-(void) varManagedObjectArrayUpdated
{
[self.bookmarkStorer vUpdateBookMarkIDwithArray:_arManagedObjectArray];
[self.delegate vUpdateNumberOfStuffs];
}
-(BGBookmarkStorerForPlacesandCatalog *) bookmarkStorer
{
assert(false);
return nil;
}
- (NSArray*) theBookmarkedIDs
{
return self.bookmarkStorer.bookmarkedIDs;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSMutableArray * mutableBusinessBookmarked= _arManagedObjectArray;
NSManagedObject *bizOrCatToMove = mutableBusinessBookmarked[sourceIndexPath.row];
[mutableBusinessBookmarked removeObjectAtIndex:sourceIndexPath.row];
[mutableBusinessBookmarked insertObject:bizOrCatToMove atIndex:destinationIndexPath.row];
//_arManagedObjectArray=mutableBusinessBookmarked;
[self varManagedObjectArrayUpdated];
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
Create a subclass of uitableviewcontroller. Implement all your functions there. Use it as a superclass for all your view controllers.
If I understand correctly, you want a practical place where you can put that code and reuse in your table view controllers, right?
If so, simply create a category on UITableViewController and put your code there ;-)

create section in Dynamic UITableView in objective-c

I want to create Dynamic UITableView that's contain days as a sections (sat,sun,mon,...)
would you please helping me!
Thanks in advance!
here is my code but i don't know what should I write for creating sections:
Day.h
#import <UIKit/UIKit.h>
#interface Day : UIViewController
#property (nonatomic, strong) NSMutableArray *monthTitle;
#end
Day.m
#synthesize monthTitle;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super init];
if (self) {
monthTitle = [[NSMutableArray alloc] init];
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.monthTitle count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"Cell"];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.monthTitle removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib
name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
Make sure that you set up your UIViewController as the delegate and dataSource of the UITableView. First you need to implement the protocols for these two:
#interface Day : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) NSMutableArray *monthTitle;
#end
Second you need to assign the delegate and dataSource of the UITableView to the UIViewController.
Right click on the UITableView and drag the delegate and dataSource outlets to the UIViewController at icon at the bottom of the view:
Now your UITableView is set up to use your UIViewController as the delegate and dataSource. After that, set up the functions properly to fill the UITableView with data:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.monthTitle count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.monthTitle objectAtIndex:section];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1; //Return the number of sections you want in each row
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"Whatever You Put For Cell Identifier On Interface Builder";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//Configure the cell however you wish
return cell;
}
Now, assuming you have self.monthTitle set up as an NSArray of NSString that holds the titles you want for each section, this code will give you a UITableView with as many sections as there are titles in self.monthTitle with 1 row in each section and a section header that correlates to that particular index of self.monthTitle. So if self.monthTitle holds all of the days of the week, your UITableView will look like this:
The following method returns the number of sections.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
So, if you need 3 sections, you have to return 3.
After that, you can use this method to name sections :
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if(section == 0)
return #"name section 0";
else if(section == 1){
return #"name section 1";
}else
return #"name section 2";
//etc...
}
Use Array or dictionary to create dynamic structure
_sections = [NSMutableArray array];
[_sections addObject:#"section1"];
[_sections addObject:#"section2"];
_rows = [NSMutableArray array];
NSMutableArray* section1 = [NSMutableArray array];
[section1 addObject:#"row1"];
[section1 addObject:#"row2"];
NSMutableArray* section2 = [NSMutableArray array];
[section1 addObject:#"row1"];
[section1 addObject:#"row2"];
[_rows addObject:section1];
[_rows addObject:section2];
#pragma mark - Table view data source
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [_sections count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [_sections objectAtIndex:section];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[_rows objectAtIndex:section] count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:nil];
if(!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil];
cell.textLabel.text = [[_rows objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
return cell;
}

UITableView doesn't call numberOfRowsInSection nor cellForRowAtIndexPath

I don't know what to think...
I set up my main view to contain a UITableView. (I am using a UIPickerView as well on that view.)
I defined it to conform to the protocols:
UIPickerViewDelegate,
UIPickerViewDataSource,
UITableViewDataSource,
UITableViewDelegate
Announced the two methods in my view's h:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
implemented them in m:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"] autorelease];
cell.textLabel.text = [NSString stringWithFormat:#"Test %d",indexPath];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
I did set the delegate in my viewDidLoad:
searchTableView = [[UITableView alloc] init];
[searchTableView setFrame:CGRectMake(searchBar.frame.origin.x+10, 50, searchBar.frame.size.width-20, 300)];
searchTableView.delegate=self;
And yet, not numberOfRowsInSection nor cellForRowAtIndexPath are ever called!
What am I doing wrong ?
set the datasource:
[searchTableView setDataSource:self];