I am implementing a UITableView with UISearchDisplayController in xcode 4.2.
UITableView & UISearchDisplayController are created in StoryBoard.
I set the Cell Identifier (SampleCell) for UITableView and access it like
cell = [tableView dequeueReusableCellWithIdentifier:#"SampleCell"];
UItableView is working fine.
But once i try to search, the app crash with below error.
*** Assertion failure in -[UISearchResultsTableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:6072
2011-11-09 22:22:16.058 SampleApp[14362:fb03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
I guess I need to set the cell identifier for self.searchDisplayController.searchResultsTableView cell.
But I don't know how.
Thanks in advance for any help. =)
Use [self.tableView dequeue...], not [tableView dequeue...].
The cell you're trying to dequeue is linked to your primary view controller's tableView in the storyboard, NOT the searchDisplayController's newly created tableView (which has no cell identifiers linked to it). If you just message "tableView" then your dequeue message goes to the searchDisplayController's tableView since that's what was passed into the cellForRowAtIndexPath:... method.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"CellId"];
// do your thing
return cell;
}
Hard bug to track indeed, it seems that every time you do a search a new tableview is created. Meaning that your cell registering has to be taken out of ViewDidLoad since this will only work for the first search. Instead use the following delegate method to do cell registering and customization:
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[self.searchDisplayController.searchResultsTableView
registerNib:[UINib nibWithNibName:#"YOURCELLNIB" bundle:nil] forCellReuseIdentifier:#"YOURCELLID"];
self.searchDisplayController.searchResultsTableView.separatorColor = [UIColor clearColor];
}
(The answer that recommends using self.tableview is dependent on another table view. This is the cleanest solution and can be used even if the search controller is used by itself.)
You need to register the cells on the UISearchDisplayController's UITableView. The best way to do that is to register the cells when that table view is loaded.
UISearchDisplayDelegate has a method that notifies you when the table view is loaded - just like viewDidLoad but for the search table view.
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
[tableView registerNib:[UINib nibWithNibName:#"MyCellNib" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"MyCellIdentifier"];
}
You can in
- (void)searchDisplayController:(UISearchDisplayController *)searchDisplayController didLoadSearchResultsTableView:(UITableView *)searchResultsTableView
do
[searchResultsTableView registerNib:[UINib nibWithNibName:#"someNibName" bundle:nil] forCellReuseIdentifier:#"yourReuseId"];
Then you're able to use in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
the normal
[tableView dequeueReusableCellWithIdentifier:
Related
When we select UITableViewCell than - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath called.
But which method will be called if we hold the UITebleViewCell. Guys my problem is that I have created a tableview which contain large cell and in that cell I am setting various view an view's background color.
When I select the cell, the background color of my cell will be gone. I have solved this problem by setting view background color again in didSelectRowAtIndexPath method like this.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
UIView *vLineview=[selectedCell viewWithTag:1];
vLineview.backgroundColor = [UIColor colorWithRed:(89/255.0) green:(89/255.0) blue:(89/255.0) alpha:1];
}
This done the trick and my view background color will displayed but when I hold the UITableViewCell than it will gone again.
How can I solve this? Do I have to and gesture recognizer to detect long touch and implement my view background method in it? Or there is any other method available for that.
Try with set cell selection style none like this in cellForRowAtIndexPath
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
You can subclass UITableViewCell and override this method:
- (void) setSelected: (BOOL) selected
animated: (BOOL) animated
{
[super setSelected: selected
animated: animated];
// Configure the view for the selected state
}
Is this an issue with the UITableViewCell remaining selected after you tap on the row?
If row selection is not required, make sure you call deselectRowAtIndexPath:animated at the end of your tableView:didSelectRowAtIndexPath method.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Pleasese see method named -(void)beginUpdates
Call this method if you want subsequent insertions, deletion, and selection operations (for example, cellForRowAtIndexPath: and indexPathsForVisibleRows) to be animated simultaneously.
for more detail visit apple documentation in below link
UITableView Class Refrence
Also try [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
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.
This is either an XCode bug, or me missing a crucial rule here.
Update:
- What's the chance of this being a weird bug in XCode/Storyboard?
Situation:
iOS 5, Storyboard
This is the storyboard setup: http://i.imgur.com/T5WyD.png
Another screenshot of the full setup: http://i.imgur.com/1tVuz.png
TableViewController with Custom Cell, cell has reusable identifier "NewCell"
in "cellForRowAtIndexPath" I basically have:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"NewCell"];
return cell;
This throws an exception:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
Things I have already tried:
I setup a new project from scratch, TabBarController, with a TableViewController and a Custom Cell, all wired up in Storyboard, set a reusable cell identifier. Used the same code as above, worked perfectly. I don't know why it didn't work with the storyboard above...
I have a feeling it has something to do with the tree I built there, which is a TabBarController, loading a NavigationController, loading a TableViewController, providing a few items, one is clicked, which loads another TableViewController, which is unable to work with the custom cell, somehow.
Important:
- The issue is that the Storyboard should make sure that:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"NewCell"]; will never return NIL (unlike without the Storyboard/iOS4). But, mine is nil. And I can't, for the hell of it, figure out what's happening.
Heyo, I just had this problem today and figured out a few possible causes. To link a UITableView as a subview of a ViewController in Story board check that you have done these steps.
In your "ViewController.h", add <UITableViewDataSource> to your list
of protocols
#interface ViewController : UIViewController
<UITableViewDataSource>
you might want to add <UITableViewDelegate> as well but I didn't.
In your "ViewController.m" set up your Table view data source
functions
#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 [yourCells count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NewCell *cell = (NewCell *)[tableView
dequeueReusableCellWithIdentifier:#"NewCell"];
if (cell == nil) {
NSLog(#"Cell is NIL");
cell = [[CustomCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
return cell;
}
In Storyboard, connect the UITableView's "Data Source" and
"Delegate" references to the ViewController.
In Storyboard, give the Prototype Cell the Identifier "NewCell"
If these are done, I believe it should work.
Hope this helps =)
I always use custom cells in the storyboard like this:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
Make sure the number of rows/sections is at least one. And another thing to check is that you set the UITableViewController to your custom class name in the storyboard.
Did you double check the cell prototype identifier is "NewCell"?
Your setup as Tabbar->navigationcontroller->tableview is perfectly fine. I
am using this layout all the time.
verify also there's no useless runtime attributes anywhere in this
viewcontroller/tableview/cell.
your prototype looks a bit weird there - you added a UIButton to the cell as subview? why?
To solve this problem add the following just above your dequeueReusableCellWithIdentifier statement:
static NSString *CellIdentifier = #"NewCell";
making sure the identifier matches the prototype cell in Storyboard
It maybe late to answer this but i bet this will fix all your problems
I have a UITableView and have it so when you press the first cell, it takes you to a new view (new xib). When you press the second cell, you go to another view and so on. When you go to any of those new views, and come back to the tableview view, the cell you just pressed is still selected (its highlighted blue). What is the code to fix this?
In your tableView datasource delegate method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Inside viewWillAppear of your tableView whose cell you wish to remove selection from:
UITableViewCell *cell = (UITableViewCell *)[myTableView cellForRowAtIndexPath:lastSelected];
[cell setSelected:NO];
Where lastSelected can be a global var of type NSIndexPath storing indexPath from the didSelectRowAtIndexPath of the above UITableView
It's quite easy..
In the same method that you push the new view you should add the line:
[tableView deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated];
I have a UITableView in my nib file and would like to dynamically add some content to each of the cells in that TableView. Is there a way to do this? I have an array of text that I would like to display in the TableView as well as an array of Pictures.
You need to implement the UITableViewDataSource protocol and override the
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
and
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
methods. You will want to return the length of your array for the tableView:numberOfRowsInSection: method. In the tableView:cellForRowAtIndexPath: method you will get create the UITableViewCell (dequeue one if available) and add the UIViews you want to hold your data (i.e. a UIImage, etc.). Access the data to populate your view using the indexPath.row as the index to your array(s). Does that all make sense? It sounds a bit more complicated than it is in practice.
Here is the documentation for the UITableViewDataSource protocol
My ideal is to register as an observer for each cell, then the interested content has changed, then it sends event or necessary data to those cells. By comparing some information, like current indexPath, or some unique identifier of cell, the cell can decide to accept those sent data and change himself, or just pass this sent event and data.
I has implemented above for loading thumbnail image in the background, when the image has been loaded, it notify those cells to update images. And if any source data has been modified, it will notify the those registered cells, then those cells will reload necessary data to update their content.
If you want add cell and data on that cell dynamically from one view controller to other Tableview controler----
Step--1:[[NSNotificationCenter defaultCenter] postNotificationName:#"ReturnTableView" object:(send array object or any object)];
Step--2:go to your Table View controller
Step--3:In YourTableView.h file add this method : - (void)change_view:(NSNotification *)notif;
Step--4:Now Came in YourTableView.m file add the line in viewDidLoad ---[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(change_view:) name:#"ReturnTableView" object:nil];
Step--5:Now Add the method in YourTableView.m ----
- (void)change_view:(NSNotification *)notif {
if([[notif name] isEqualToString:#"ReturnTableView"]){
Your Object Ref(Obj-1)=[notif object];
[Obj-1 addObjectsFromArray:self.AnotherMutableArray(obj-2)];
self.obj-2=Obj-1;
[self.tableView reloadData];
}
}
Step--6:Now Add Finally in
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifierName"];
UILabel *label;
label = (UILabel *)[cell viewWithTag:TagNo(e.g:0)];
label.text = [self.messageposts objectAtIndex:indexPath.row];
label = (UILabel *)[cell viewWithTag:TagNo(e.g:1)];
label.text = [self.messageposts objectAtIndex:indexPath.row];
return cell;
}
Now Your Data Is Added
Thanks-----