UISearchDisplayController changing row height - iphone

I've set my UITableView row height to in Interface Builder to 54.0. I have a UISearchDisplayController on that view. When the user taps the search bar in it, the table resizes properly. However, when they start typing (and actually doing the search) the row height decreases. It stays wrong until the search taps Cancel.
I could find no documentation on this behavior on Apple's site.
I've tried setting the row height in UISearchDisplayDelegate delegate calls. This might be the right approach, but I don't know the details and couldn't get it to work.
I've also tried implementing - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;. This worked, but I have thousands of entries in this list and can't take the performance hit.
What's the right way to fix this?

The correct way to do this is to use the following delegate.
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
tableView.rowHeight = 54.0f; // or some other height
}
It's called when the UITableView is created or shown.
If you happen to call searchDisplayController.searchResultsTableView in other code when a search is not being performed, it will create the UITableView in advance. If you use the willShow delegate method to set the rowHeight, it will miss the timing (for some reason) to change the rowHeight if the tableView has been created beforehand.

I found it!
Assuming the table is stored in tableView:
- (void)viewDidLoad;
{
[super viewDidLoad];
self.searchDisplayController.searchResultsTableView.rowHeight = tableView.rowHeight;
}
Nothing else is necessary.
Edit: See netmikey's answer for a better solution.

Steve, your solution didn't work for me: The first time the search result would display fine, but when a user was hitting "Cancel" (closing away the search bar) and then reopening it and entering a search term into it, the height would be wrong again.
DigDog's solution of using searchDisplayController:didShowSearchResultsTableView was kinda working, but users saw the cell height "jumping" when the search started.
The solution I found, that fixed both these issues is using:
- (void)searchDisplayController: (UISearchDisplayController *)controller
willShowSearchResultsTableView: (UITableView *)searchTableView {
searchTableView.rowHeight = myTableView.rowHeight;
}
... in the UISearchDisplayDelegate.
Regards,
netmikey

In viewDidLoad:
you can set the search display controller's delegate to self:
- (void)viewDidLoad
{
self.searchDisplayController.delegate = self;
}
Then, implement the table view delegate in your view controller:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableview == self.searchDisplayController.tableView) {
return 55;
} else if (tableView == self.tableView) {
return 44;
}
}

Overriding the method didLoadSearchResultsTableView should do the trick.
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
tableView.rowHeight = 82.0; // Change height of search result row
}
More explanation from this blog

You need to set both
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 54.;
}
and
self.tableView.rowHeight = 54.;
also in your UISearchDisplayDelegate
- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
tableView.rowHeight = 54.;
}
Otherwise, when "No Result" happened in searching, cell height will fall back to default.

I've been using ios 7.0 and Xcode 5.0. I think you should change you row height in this method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (tableView == self.searchDisplayController.searchResultsTableView)
{
tableView.rowHeight = ...;// change your row height here!
return [self.searchResults count];
}
else
{
...
return ...;
}
}
Because every time a tableview try to display its layout, this method is called, so everytime you type a letter into search bar, this method is called,and the row height won't have a chance to change.

None of the solutions worked for me...
Did my own hit and trial... and got it working...
If you want different row heights for normal & search table views...
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
// for normal results
if (tableView==self.tableView) return 54;
// for search results
else return 54; }
And if you want common height...
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 54; }
PS: Do keep in mind, if you have same row height for each row, this method is not very efficient resource usage wise, as the row height is re-calculated for each cell... Although, this is unnoticeable in most cases, I am still searching for a better solution!

Related

How do you retain the current IndexPath.row in a Table View when going from one View Controller to another such as Instagram or Facebook in Swift?

I am trying to retain the current IndexPath.row of a cell in a Table View when passing from one View Controller to another such as Instagram or Facebook. Every time I move from one View Controller to another, I have to call reloadData() for the Table View to load it back. But when I do this, I lose the current position before going to a new View Controller.
I can get it to work on didSelect by passing the current IndexPath.row between Controllers, but if the user is just scrolling, it becomes buggy trying to do that.
Any suggestions would be greatly appreciated! Thanks so much!
By default, reloadData keeps the contentOffset. However, it could be updated if you do have inaccurate estimatedRowHeight values.
Calling reloadData on the tableView does not change the content offset. However, if you are using UITableViewAutomaticDimension which was introduced in iOS 13, you could have an issue.
While using UITableViewAutomaticDimension, one needs to write the delegate method tableView: estimatedHeightForRowAtIndexPath: and return UITableViewAutomaticDimension along with tableView: heightForRowAtIndexPath: which also returns the same.
For me, I had issues in iOS 13 while using this. It was because the method estimatedHeightForRowAtIndexPath: method was returning inaccurate values even though I was using UITableViewAutomaticDimension. It was problem with iOS 13 as there was no issue with iOS 13 devices.
I solved this problem by using a dictionary to store the value of the cell's height and returning it. This is what I did.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *key = #(indexPath.row);
NSNumber *height = #(cell.frame.size.height);
[self.cellHeightsDictionary setObject:height forKey:key];
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *key = #(indexPath.row);
NSNumber *height = [self.cellHeightsDictionary objectForKey:key];
if (height)
{
return height.doubleValue;
}
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
as u said u can save the position and in viewDidLoad of the new viewController scroll to that index:
tableView.scrollToRow(at: <IndexPath>, at: <UITableView.ScrollPosition>, animated: <Bool>)
set animated to false and scrollPosition to whatever fits u, example .top, and the indexPath u just pass between view controllers. try to alternate where to use this function in viewDidLoad or viewWillApear.

Change heightOfPrevious UITableViewCell

Is there anyway I can change the height of previous UITableViewCell when setting height for current cell in - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath?
Have two rows in a UITableView. When in first row, it will set the default height.. When in row two I want to change the height of first row. Is this possible? If so how?
Thanks,
Bharathi.
Try to work with a boolean check if the requirement is fulfilled.
You could do it like this:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0 && !secondRowIsSynced) {
return otherHeight ;
}
else {
return defaultHeight;
}
}
I think you misunderstand tableView:heightForRowAtIndexPath: is called multiple times (once for each row in your table).
If your rows have different heights then you need to determine which row you are on and what height it should have.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
CGFloat height;
if (0 == indexPath.row) {
// This is the first row
height = // what ever you want
} else if (1 == indexPath.row) {
// This is the second row
height = // what ever you want
}
return height;
}
If you later decide that a row needs to be a different height then it is still this method that needs to calculate the correct height to be used for each row. You can force this to be called without reloading the tableView like this
[tableView beginUpdates];
[tableView endUpdates];
bharathi:
You have to reload your table in the didSelectRowAtIndexPath method of UITableView.
You should check that the second row is selected, then reload all the table rows, so all tableview delegate and datasource methods get called again.

How to remove blank spaces on Hiding rows in Table View Cell?

i was able to hide row on Table View Cell by using this code
cell.hidden = YES;
the problem is it gives blank spaces (show on the picture).
Is there any way on eliminating this blank spaces?
Thank you.
You need to set the correct height for the cell in the UITableViewDelegate.
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == someIndex) {
return 0.0f;
}
return 65.0f;
}
Better would be to not have the cell in tabelview at all.

Padding on TableViewCell

I want to add padding to my table view cells. Thought I could do something like this but that didnt work.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
return cell.frame.size.height + 20;
}
See the below link. Explains the basics of getting a variable height (for cells) UITableView along with proper padding that your require. Example just includes text. Change it to suit your requirements within the cell.
http://www.cimgf.com/2009/09/23/uitableviewcell-dynamic-height/
Are you sure you placed this method in your delegate? it also depends on which cells. There are other methods...
// UITableViewDelegate Method
- (CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
}
// UITableViewDelegate Method
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
}
also, if you are using the contentView of the cell then you will need to change the frame of your custom view
When adding your cells you will need to set the y value of the cell's frame to half your padding to make it start at the right place. Also ensure that the cell does not have flexible height or it will expand to fill the height of the row.

How to prevent UITableView from reserving space at the left of cell when editing is turned on?

I'm set editing mode for UITableView to have a possibility of cell reordering. UITableViewCellEditingStyleNone is returned by editingStyleForRowAtIndexPath: method for every cell, but it reserve some area on the left of cell. Is it possible to prevent such an area reserving, because I'm not need an insert or delete icon on left? In short, i want have a cell that occupate all available area and still can be reordered.
// UITableViewDelegate
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
See the docs: You can set a boolean on the cell to make it not indent. Just add
cell.shouldIndentWhileEditing = NO;
to wherever you create your cell.
Set this to like 2 or 3
tableView:indentationLevelForRowAtIndexPath:
The shouldIndentWhileEditing property only works with grouped tables. I found that setting an indentation level of -3 does the job for plain tables. Is there a better way? Here's what I'm using now:
if (self.tableView.style == UITableViewStylePlain) {
cell.indentationLevel = -3;
} else if (self.tableView.style == UITableViewStyleGrouped) {
cell.shouldIndentWhileEditing = FALSE;
}
Do both
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
and
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
in your UITableViewDelegate. Otherwise the cell content is indented.