I currently have two UITableViewControllers, one with the prototype of the custom cell, and the other one not. Since both of them are connected through a push segue from the first to the second. I pass the selected custom cell to the second tableView.
Everything works fine, except that when I come back to the first view, the selected (and passed) cell is hidden, but when I scroll it enough to hide the blank space and scrolling back it shows.
How can I fix this?
The Big Nerd Ranch Guide says basically to stay away from Storyboard for just this kind of reason.
Amongst other things about Storyboards, it says:
"Overall storyboards make easy code easier and difficult code more difficult".
Not sure you should be passing a cell through the push segue.
When not using storyboard, you would typically create a new file of type UITableViewCell called e..g MyCustomerTableviewCell.
Then in your UITableView viewDidLoad method, create a new Nib and add it to the tableView,
UINib *nib = [UINib nibWithNibName:#"MyCustomTableViewCell" bundle:nil];
// register this nib that contains the cell
[[self tableView] registerNib:nib forCellReuseIdentifier:#"MyCustomTableViewTableViewCell"];
Then create a new empty XIB file (file->new->User Interface->empty) and call it MyCustomTableViewCell.xib.
Drop a UITableViewCell into the interface builder space, change it from UITableViewCell type to MyCustomTableViewCell, make sure it's File's Owner is MyCustomTableViewCell.
Then in your UITableView file, do this...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomTableViewTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"MyCustomTableViewCell"];
...
return cell;
}
You can probably do this as part of a storyboard project anyway (though I haven't tried missing XIB and Storyboard in one project).
If I understand correctly what you are doing, you are passing a reference of the tapped cell to the second view controller, and then you are showing it inside the table view of the second controller passing the same reference in the cellForRowAtIndexPath method.
It doesn't seems a good choice :-)
First: because that cell was allocated and queued for use in the first view controller. At any time, the cell could receive a prepareForReuse message by the first view controller.
Second: when you show the cell in the second table view, the cell is removed from the first table view.
If you don't want to create another prototype cell in the second view controller, you can, for example, allocate a new cell in the first one, copy all properties from the tapped one to the new, and then pass the new to the second viewcontroller.
This is the first solution I've thought about, but sure there are other better solutions :-)
Related
I am working on an app that has several prototype cells in one view. This worked well for easily altering the appearance of the app while in development using the storyboard. However, now I'm adding search (filtering) capability. I would like the appearance of the tableview to remain unchanged, just filter out some of the results.
My understanding is that I have to create new cells to do this. Is this correct? If it is, is there a way to create a cell with all the properties of my prototype cells. As it is now, the newly created (search result) cells have default settings.
Thanks.
You can certainly use copy and paste. Create a xib file (an empty one), and copy the cell you want from your table view in the storyboard, and then paste it into the xib file. In the viewDidLoad method for your table data source, register that nib file:
[self.searchDisplayController.searchResultsTableView registerNib:[UINib nibWithNibName:#"SearchCell" bundle:nil] forCellReuseIdentifier:#"SearchCell"];
Then in the cellForRowAtIndexPath method, you just dequeue a cell with that identifier for your search results table view.
The thing to understand clearly is that the table view that appears when you are doing a search with the UISearchDisplayController conglomerate is not your table view. It is a different table view, and you do not have a UITableViewController managing it - the UISearchDisplayController does that. Thus you must take other measures if you want that different table view to look like your table view.
EDIT: On the whole (and after the little exchange with rdelmar in the comments on his answer), I tend to think the easiest solution is to abandon the use of cell prototypes altogether. If you design the cell in a nib (xib), you can then use that cell both for the real table and for the search results table. In both cases you register the nib with the respective table view - and then dequeue just does the right thing all by itself, in both cases, with no change in the code.
You can see me doing something similar here:
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch21p632searchableTable/p536p550searchableTable/RootViewController.m
... except that in that case I'm registering the same cell class for both tables, not the same nib. But it all comes down to the same thing. However, note that I do not start with a storyboard, so I never fell into the trap of using a prototype cell in the first place.
Using a dynamic, custom cell prototype that I design in, say, UITableViewController A (in Interface Builder/Storyboard), works really well with dequeuing the cell (through its identifier, cellA) and such in cellForRow... I use a custom class (UITableViewCell subclass, let's name it MyCustomCell) to link up the labels and image thumb and it works all pretty well and straight forward in my UITableViewController A.
Now I create a UITableViewController B (in Storyboard), which happens to have the exact same design/functionality for its custom cells (dynamic cells). So I switch the class of these cells to the MyCustomCell and give it a new identifier, cellB.
In UITableViewController B, I dequeue the cell in cellForRow... and use the new identifier cellB. Note: Using cellA here leads to a crash, more or less obviously.
But when the table view shows up, while running the app, the UITableViewController A works just fine, and the almost identical UITableViewController B does not work (empty cells).
In Storyboard, it looks sort of off a bit, because the custom cell is designable within the UITableViewController A but in UITableViewController B, it's just a simple, plain cell. Despite the class associated to MyCustomCell.
How would one avoid copy&pasting these cells to the other controller (and therefore heavily going back and forth between copies when making design changes) – and rather just properly re-use it?
What you are doing is correct. I don't know why its not working, it may be some problem with reloading the tableview; check with your datasource and the datasource method.
- (NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger) section
rather what you can do is: drag a
Viewcontroller
and then drag a
tableview
and make it dynamic and do the thing that you did earlier; it worked fine for me when I did so myself.
Saying the Cell is from a your custom class doesn't mean it's "designed" the same. What you really try to achieve here (and what I'm looking for) is some king of "Contained" Cell, but this is only doable with a ContainerViewController in iOS 6 I think. The other option is to use a XIB for that one Cell — that should work just as good, but then you lose the benefits of having an overview in the Storyboard.
I had a similar problem, I had created a custom cell with a uitextfield inside it. It was working well in the first tableview but not in the second. I figured out that the textfield's delegate was not connected to the custom cell. I connected the two in storyboard by making a connection from textfields delegate outlet back to the textfield.
I am trying to learn iPhone development as I've read many others on here are also saying. And Ive searched through about 20 pages of previous threads but couldn't quite find one that is what I need. I have a TableViewController as my root view that is inside a NavigationController. I have a grouped table with 2 cells inside the TableViewController and was wanting the text of which ever cell was selected to become the title of the next view's NavigationBar. I am using Xcode 4.3 and storyboards. Any help would be appreciated!!
In the tableview:didSelectRowAtIndexPath: method, I assume that you are creating and pushing your next view controller. You also must be having an Array (or some data source) which populates the text in the Tableview. So get the current cell's text by using indexpath.row. Set this text to:
nextViewController.title = cellText;
So when you push this view controller, it'll have the title of the cell selected.
try below it in didSelectRowAtIndexPath method will help you
detailViewController.title = [[[self tableView:tableView cellForRowAtIndexPath:indexPath] textLabel] text];
I have a UITableView of customers where a row/customer is selected. The user can then push another view on the UINavigationController stack to add a new customer. When I pop the child screen and return to the UITableView the previously selected row is no longer selected.
I can re-select the row in viewDidAppear() but it looks bad as you can see the deselect and the select. Is there a way to maintain the selected row when returning from the child screen?
I assume you are using a table view controller, as otherwise it is your responsibility to write this behaviour anyway. In a table view controller, though, it's easy. Just add in viewDidLoad:
self.clearsSelectionOnViewWillAppear = NO;
That will keep the row selected, unless you manually deselect the row or the user selects another row on the table.
If you select it in viewWillAppear:, it should get selected without the user seeing it. Would that solve your problem?
You need to call:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
This is found in the didSelectRowAtIndexPath delegate method for a UITableView.
By default, a selected row gets deselected (with animation) when you return to that VC.
So, if you push a DetailViewController, the cell stays selected until you return to the RootViewController and then gets deselected automatically.
I used to have such a problem too. Make sure to always call the superclass's implementation of methods such as viewWillAppear, viewWillDisappear etc.
Also, do not call deselectRowAtIndexPath: manually.
This is possible :
Only in once case: If you have the static content in TAbleView,
just reload the TableView in ViewDidLoad only, not in View will Appear.
whereas make sure, you don't allow table to reload anywhere in same class in any method. Then you can achieve what you want.
The cell get deselect because of reload the TAbleView.
But for Dynamic content, you need to use the delegate method:
- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;
In this you need to pass the indexPath which you want to show selected with the scrollPostion same as tableviewposition.
You cannot have a tableViewCell selected all the time. It gets back to normal once it serves its purpose. I think you meant highlighted or appear to be selected, and I am answering the question based on that.
Get the row that was selected at the cellForRowAtIndexPath. When you pop your navigation controller and come back to the tableView, go the the cellForRowAtIndexPath and have that cell highlighted (You can use any UIColor as you wish) - there is no specific way to highlight stuff - use your imagination - Default highlight style is Blue, while the text is White.
How is this done ?
Find selected row in cellForRowAtIndexPath
Store is in an external variable / or NSUserDefaults and you can also use NSUserDefaultsto communicate between screen to find out if item was popped from that screen.
[tableView reloadData] in viewWillAppear
Check for NSUserDefaults value in cellForRowAtIndexPath and modify that cell with cell.backgroundColor or something.
Without some code, I can just give an advice : stop using [tableView reloadData], use [tableView beginUpdates], [tableView endUpdates] and – insertRowsAtIndexPaths:withRowAnimation: and – reloadRowsAtIndexPaths:withRowAnimation:. Things should work as expected.
i used the ib to create a uiimageview footer in the tableview, i want that the image will appear all the time while rolling and not just when rolling to the end of the table,
is there a way to d that?
Yes, but your view hierarchy will need to change.
You will need to make the view controller a subclass of UIViewController, and a delegate for UITableViewDelegate and UITableViewDataSource.
In this arrangement, you have a normal view controller, with a base view that remains static. You add a UITableView to that view, and depending on the size & placement you can have that base view showing at either top or bottom (or both).
Connect up your table-view to an outlet in the controller, set it's data source and delegate to the files-owner, and use the same delegate methods that a normal UITableViewController does.
One thing I've noticed is that a UITableViewController will automagically deselect any selected cell (either as the table disappears or reappears, I forget which). You will just have to manage that in:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
or in
- (void)viewWillAppear:(BOOL)animated.
No, the footer is part of the table itself. In fact, it is part of a section of the table. The footer only has meaning the in the context of the data above it so having a footer always visible would not make sense in the interface grammar.