I have a UISearchDisplayController that is properly hooked up in Interface Builder.
delegate = Files Owner
searchBar = Search Bar
searchContentsController = Files Owner
searchResultsDataSource = Files Owner
searchResultsDelegate = Files Owner
When my UITableView calls numberoOfRowsInSection: the correct number is returned.
However, my cells in cellForRowAtIndexPath: don't even reach:
- (UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tblView == searchController.searchResultsTableView){
NSLog(#"search will go here");
UITableViewCell* cell = [self provideSearchQueryCells:tblView identifer:#"searchQueryCell"];
STSymbol *aSymbol = [self.searchQueryResults objectAtIndex:indexPath.row];
cell.textLabel.text = aSymbol.symbol;
cell.detailTextLabel.text = aSymbol.symbol_title;
return cell;
}
else { ... }
It always goes to the else condition.
I am not exactly sure why.
I needed to create an instance of a UISearchDisplayController instead of using self.searchDisplayController.
use the following. It should work.
if ([tblView isEqual:[searchController searchResultsTableView]]) {
...
}
you should also make sure the search result row count is correct as in :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([tblView isEqual:[searchController searchResultsTableView]]) {
return [self.searchResults count];
}
...
}
This is a guess from this close in on the code, but are we looking at the search display controller itself? Maybe your self.searchDisplayController.searchResultsTableView should just be self.searchResultsTableView.
I can't be sure without knowing your delegates.
Related
I have 3 table views in one view and I was wondering why the tableView:cellForRowAtIndexPath: was not getting called.
#pragma mark -
#pragma mark <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainVoucherTableViewController)
[self setSelectedIndex:indexPath.row];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.mainVoucherTableViewController){
return 10;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainVoucherTableViewController){
static NSString *MyIdentifier = #"MyReuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
cell.textLabel.text = #"THISTEXT";
return cell;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView == self.mainVoucherTableViewController)
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// The header for the section is the region name -- get this from the region at the section index.
if (tableView == self.mainVoucherTableViewController){
NSString * myString = [NSString stringWithFormat:#"HELLLO WORLD"];
return myString;
}
}
WOULD anyone know why this is? Basically this doesn't create any cell or display cells. It just displays the table views. :(
Just to consolidate a few things from above:
From your naming, your tableView is called mainVoucherTableViewController - just want to confirm that this is indeed a UITableView and not a UITableViewController? If it's a UITableViewController then the rest of this won't work for obvious reasons (or not so obvious - let me know and can explain further)
Make sure you have set the current viewController as the tableView's delegate and dataSource, either with the code below or in Interface Builder if you're using a XIB
self.mainVoucherTableViewController.delegate = self;
self.mainVoucherTableViewController.dataSource = self;
Make sure your numberOfRowsInSection function is being called and that you're returning non-zero (put in NSLogs, etc) and do the same for numberOfSections as well (actually numberOfSections isn't required if you're only using 1 section) - see UITableViewDataSource Protocol Reference: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html
As per previous post, log your cellForRow (if points #1-3 are checked and working) at the beginning to make sure it's triggered, and just before the return. Also do an NSLog of the cell you're returning just to make sure it isn't nil.
Start off by logging inside your tableView:cellForRowAtIndexPath: method to see if it gets called at all outside your if statement as well as inside to help narrow down the issue.
Also try instead of comparing your:
tableView == self.mainVoucherTableViewController
Set the tableViews to have tag values instead. Then you can do:
if(tableView.tag == 100){ // tag number we assigned self.mainVoucherTableViewController via IB
//do your stuff here
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.mainVoucherTableViewController)
{
return 10;
}
else
{retun 5;
}
}
It display row in first table 10, second table show 5 rows.
The order of instance declaration does matter. For example, if you have a ivar called tableView:
WRONG
self.tableView.delegate = self;
self.tableView = [UITableView alloc] init];
CORRECT
self.tableView = [UITableView alloc] init];
self.tableView.delegate = self;
check UITableView Object Frame Size. maybe Frame size is not enough to draw Cell.
I'm stuck with a seemingly very simple app that I'm trying to develop
Basically, I have a UITable, and two buttons: red/blue
When a button is pressed, a row with corresponding title of that button is append to the table
I'm overwhelmed by how complicated UITableView has to be implemented (datasource, delegate, resuable identifier, etc)
Can anyone help me out with this, preferably show me detailed codes
For my Buttons, I have something like this
- (IBAction)buttonPressed:(UIButton *)sender{
NSString *item = sender.currentTitle;
[self.cellArray addObject:item];
[self.myTable reloadData];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.cellArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"The Table Cell";
self.myTableCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (self.myTableCell == nil) {
self.myTableCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
self.myTableCell.textLabel.text = [self.cellArray objectAtIndex:indexPath.row];
return self.myTableCell;
}
Since you are learning this..i will post a simple solution.
Make add a member variable NSMutableArray *cellArrays;
initialize it in your viewDidLoad
in buttonPressed check;
if([#"red" isEqualToString:[YourButton titleForState:UIControlStateNormal]])
{
[self.cellArrays addObject:#"red"];
}
else
{
[self.cellArrays addObject:#"blue"];
}
[self.YOURTABLEVIEW reloadData];
Now in your table view datasource method
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.cellArrays.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//in between your code;
YOURCELL.textlabel.text = [self.cellArrays objectAtIndex : indexpath.row];
}
Try this ..
I'd recommend subclassing UITableViewController, then override the dataSource and delegate methods and you should be good to go. Going straight to UITableView is more complicated without any obvious benefits.
You may not be using Core Data, but I still recommend this lecture because it hooks up a TableViewController and works great - all code included. Check it out:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/node/289
The lectures in iTunes U explain everything further.
Enjoy,
Damien
I wanted to add that "One more thing, the compiler shows a warning says no reusable identifier. what exactly is that?" above...
His answer is correct, but to get rid of that compiler warning...
The tableviewcell of your tableview has to have an identifier. In IOS 5, in your storyboard, highlight the TableViewCell in your TableView, and enter a value in the Identifier. This must match the value in your code of the cell that you are creating.
Can I have the number of rows dynamically?
I'm trying to remove a tableView section header and I don'k know how... and I've taught that a solution would be to change the number of sections.
Right now my numberOfSectionsInTableView looks like:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
and
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
beTribesAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
switch (section) {
case 0:
return [appDelegate.firstArray count];
case 1:
return [appDelegate.secondArray count];
default:
return 0;
}
}
setting the title section like this:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
sectionTitles = [[NSMutableArray alloc] init];
[sectionTitles addObject:#"firstSection"];
[sectionTitles addObject:#"secondSection"];
NSString *sectionText = [sectionTitles objectAtIndex:section];
return sectionText;
}
I am not sure to understand the question as the answer seems trivial: just change the implementation to return some dynamic value and you are done, right?
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.nbSections;
}
Where nbSections is a property to which you will assign the value you want so you can change it at any time you want. So what's the matter then?
PS: Of course, call [tableView reloadData] to recompute the content of your tableView and make the new value being taken into account obviously... maybe that's what you were missing?
To remove the section header you must set the header height to 0 like so
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
switch (section) {
case 0:
return 0;
default:
return 44;
}
}
this example will remove the first section header and all the others will be set to 44.
First thing to do would be to move the sectionTitles array into a property on your view controller, and initialise it in your init method.
Then when you want to change the title of a section change the value in the array and call [tableView reloadData]
Do you want to remove the whole section from the tableView or just the header? if you want to just remove the header set the item in the array to #""
If you want to remove the section altogether remove the item from sectionTitles and change your numberOfSectionsInTableView method to read:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sectionTitles count];
}
I'm creating a uitableview with custom cells which I created in Interface Builder. There are currently three cells (UITableViewCell).
I have a UITableView which is on the view.
The code I have is fairly standard, but I cannot work out how to actually SHOW the three custom cells. I am using the cellForRowAtIndexPath method.
My aim is to get a grouped uitableview which shows like the following
Item
- Name
Settings
- alert
- time
So the above indented view should be my grouped uitableview. The problem is, I cannot get it to show using code. The uitableview will ALWAYS be this. I am trying to replicate the settings style screen... so I do not have any arrays to display the uitableview cells.
How do I actually display my three cells? I have the following code
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0)
return 1;
else
return 2;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if(section == 0)
return #"Item";
else
return #"Settings";
}
So all I need to know is how to actually display my custom cells inside the tableview!
Thanks for any information. I've searched for AGES in google .. all the tutorials use arrays to display data!
You'll kick yourself.
In cellForRow, use some cascading if statements, like:
if (indexPath.section == 0) {
cell.textLabel.text = #"Name";
} else {
if (indexPath.row == 0) {
cell.textLabel.text = #"alert";
} else {
cell.textLabel.text = #"time";
}
}
For the iPhone, is it possible to configure a UITableView such that it will allow multiple-selection?
I've tried overriding -setSelected:animated: for each UITableViewCell, but trying to fudge the required behavior is tricky as it's difficult to separate the real unselections from the ones where the UITableView thinks I've unselected due to selection of another cell!
Hope someone can help!
Thanks,
Nick.
Following property should work fine if you are developing app for iOS5.0+
self.tableView.allowsMultipleSelection = YES;
The best way to do this would be to a checkmark per selected row.
You can do that by setting the accessoryType on the selected UITableViewCell instances to UITableViewCelAccessoryCheckmark.
To deselect the row, set it back to UITableViewCellAccessoryNone.
To enumerate which cells/rows were selected (say, upon clicking a button), simply iterate over the cells of the table looking for UITableViewCellAccessoryCheckmark. Or, manage some NSSet or the like in your table view delegate in the "did select" delegate methods.
Use the following code to set up the cell accesory types:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone) {
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
}
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
//add your own code to set the cell accesory type.
return UITableViewCellAccessoryNone;
}
Jeff Lamarche has a tutorial on how to do this here:
http://iphonedevelopment.blogspot.com/2008/10/table-view-multi-row-edit-mode.html
I've not tried the code but it's been on the back of my mind for a while, knowing the day will come when I need it.
I backported allowsMultipleSelectionDuringEditing and allowsMultipleSelection from iOS5 to older iOS. You can fork it at https://github.com/ud7/UDTableView-allowsMultipleSelection
It's drop in replacement and only thing you need to do is change UITableView to UDTableView (in code or interface builder)
From the HIG:
Table views provide feedback when users select list items. Specifically, when an item can be selected, the
row containing the item highlights briefly when a user selects it to show that the selection has been received.
Then, an immediate action occurs: Either a new view is revealed or the row displays a checkmark to indicate
that the item has been selected. The row never remains highlighted, because table views do not display a
persistent selected state.
You'll need to roll your own multiple selection style, either with something like Mail, or using the checkmark accessory on your cells.
Guys for multiple selection you just need
self.tableView.allowsMultipleSelection = YES;
on viewDidLoad and
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = NO;
// if you don't use custom image tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = YES;
// if you don't use custom image tableViewCell.accessoryType = UITableViewCellAccessoryNone;
}
I was searching for the same issue and the answer of Bhavin Chitroda sovled it for me but with some addition to keep the check mark as it was while scrolling.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ( [array indexOfObject:indexPath] == NSNotFound ) {
[array addObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
[array removeObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
The addition:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
// Your code here
.
.
.
if ( [array indexOfObject:indexPath] == NSNotFound ) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
return cell;
}
If you're trying to do something like Mail's multiple-select (to delete mail, for example), then you're probably going to have to manage all the selection yourself. Multiple row selection isn't something that's standard on the iPhone. Mail solves this by using checkmarks to indicate which rows have been selected.
blue highlighted row as an indicator of whether a row is selected is actually discouraged according to the HIG page 121. Checkmarks will do the trick.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
int selectedRow = indexPath.row;
cout << "selected Row: " << selectedRow << endl;
UITableViewCell *indexPathForCell = [tableView cellForRowAtIndexPath:indexPath];
if (indexPathForCell.accessoryType == UITableViewCellAccessoryNone) {
indexPathForCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
indexPathForCell.accessoryType = UITableViewCellAccessoryNone;
}
}
then add your arraying or how ever you wish to store the data of which were selected.
Note: This does not work in iOS 4+. This is a private, undocumented constant. Do not use it.
If you are not planning to submit your app to the App Store, you can invoke multi-row edit mode by implementing the following method in your UITableViewController delegate:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return 3; // Undocumented constant
}
Tested with iOS4.3 - 6.0
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
if ([controller.searchResultsTableView respondsToSelector:#selector(allowsMultipleSelectionDuringEditing)]) {
controller.searchResultsTableView.allowsMultipleSelectionDuringEditing = YES;
}
else {
controller.searchResultsTableView.allowsSelectionDuringEditing = YES;
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellAccessoryCheckmark;
}