UITableView adjust content inset not unitl 1st scroll - ios

while trying to create a tableview with a searchBar I encountered the problem that my tableView automatically adjust the contentInset, but not until the 1st scroll. On another tableView, where is no searchBar the problem does not exists. The setup of the searchController is pretty much ripped out of Apples TableSearchWithUISearchController sample.
So my Codes get called by the TableViewController in viewDidLoad:
resultsController = [[ResultConstantTVController alloc] init];
searchController = [[BaseSearchController alloc] initWithSearchResultsController:resultsController];
searchController.searchResultsUpdater = self;
searchController.delegate = self;
self.navigationItem.searchController = searchController;
self.navigationItem.hidesSearchBarWhenScrolling = NO;
[self.searchBar setBarStyle:UIBarStyleBlackTranslucent];
[self.searchBar setKeyboardAppearance:UIKeyboardAppearanceDark];
[self.searchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
self.definesPresentationContext = YES;
self.dimsBackgroundDuringPresentation = NO;
I tried already to set the tableViews contentInsetAdjustmentBehavior to automatic manually but it still won't take effect until the 1st scroll.
Before firstScroll
After first scroll
P.S. I am using the beta Version of Xcode, macOS and iOS.
UPDATE:
I managed to bypass the problem by calling
[self.navigationController.view layoutSubviews];
in viewDidAppear in the TableViewController.

I tried already to set the tableViews contentInsetAdjustmentBehavior to automatic
That was right, but not quite enough. Problems of this sort are usually solved by also setting the table view's alwaysBounceVertical to YES. You need to do this very early in the life of the view controller.

Related

iOS - segmentedControl disappears after using searchBar

Through Storyboard, I have created a ViewController with a UITableView and a SegmentedControl on top. Programatially, I have added a SearchController as the TableView's header.
This is what happens when I launch the app:
It works perfectly.
But when I click on the search bar, it already messes up a bit. It's easy to fix by hiding the SegmentedControl though.
Now the problem appears when I finish my search:
The SegmentedControl disappears. Whenever I click on the searchbar again, it comes back, just like in the picture number 2, but if I cancel again, it disappears.
I have tried removing it from the view and adding it again once the user stops searching, but it changes nothing. Here is my code:
searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
searchController.searchResultsUpdater = self;
searchController.dimsBackgroundDuringPresentation = NO;
searchController.searchBar.delegate = self;
self.tableView.tableHeaderView = searchController.searchBar;
searchController.searchBar.scopeButtonTitles = #[];
self.definesPresentationContext = YES;
[searchController.searchBar sizeToFit];
What can I change?
searchController.searchBar.showsScopeBar = YES;

UITableView with UISearchController go under navbar when enter in a result view and come back

I have a UITableView with a UISearchController search bar in the UINavigationBar, all works perfectly, but when I push a result of the searched results of the UISearchController, and I come back the UITableView is under the NavBar, this is how I initialize the UISearchController:
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.delegate = self;
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.searchBar.placeholder = NSLocalizedString(#"Local Search", #"");
self.searchController.searchBar.frame = CGRectMake(0, -5, [UIScreen mainScreen].bounds.size.width, 44);
ctrl = [[UIView alloc] initWithFrame:CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width, 44)];
ctrl.backgroundColor = [UIColor clearColor];
ctrl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[ctrl addSubview:self.searchController.searchBar];
self.navigationItem.titleView = ctrl;
self.definesPresentationContext = YES;
The search bar is displayed perfectly in the UINavigationBar, then when I search something and I push the view controller of one results like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
DetailListController *detailList = [[DetailListController alloc] init];
[self.navigationController pushViewController:detailList animated:YES];
}
when I come back to the UITableView doing this:
[self.navigationController popViewControllerAnimated:YES];
the UITableView is under the UINavigationBar, how I can fix this?
thanks
I had exactly the same problem, setting extendedLayoutIncludesOpaqueBars to YES/true in view controller, that presents search controller, seems to fix it.
self.extendedLayoutIncludesOpaqueBars = YES
As a word of caution: setting this property changes value of scroll view's vertical content offset.
This is an extremely frustrating bug in UIKit. What appears to be happening is that the presenting view controller's top layout guide get reset to 0, meaning it is now underneath the nav bar. The layout guide is a read only property, so you can't fix it by editing directly. However, I did come up with a hack to get it to reset to the correct value. Add this to your UISearchControllerDelegate:
- (void)didDismissSearchController:(UISearchController *)searchController
{
UINavigationController *nav = self.navController; // you muse save this earlier
// force to layout guide to reset by pushing a dummy controller and popping it right back
[nav pushViewController:[UIViewController new] animated:NO];
[nav popViewControllerAnimated:NO];
}
I have used UISearchController for years but today is the first time I am facing this issue
I used to set edgesForExtendedLayout = [] and extendedLayoutIncludesOpaqueBars = true and everything is fine
but today It is not, I needed to reverse it to edgesForExtendedLayout = .all
it may be useful to you too!
Ran into this issue today and resolved using a reference to the result view controller's safeAreaLayoutGuide
After refreshing your result table's contents, you can then call this method:
// NOTE: this method is used to fix a known UIKit bug where search results that do not have a content
// size that fills the view will be placed underneath the navigation bar when displayed. this hack
// fixes this issue by resetting the contentInset based on the content size.
private func adjustContentInsetForContentSize() {
if collectionView.contentSize.height > view.frame.height {
collectionView.contentInset = UIEdgeInsets.zero
} else {
collectionView.contentInset = UIEdgeInsets(top: view.safeAreaLayoutGuide.layoutFrame.origin.y, left: 0, bottom: 0, right: 0)
}
}
Essentially the issue is caused by having a result view that has a contentSize height that is smaller than the viewable region for the view. The results render find when the contentSize.height > view.frame.height, so this hack will force the content insets to properly respect the safe area layout guide.

How can I make a UISearchController start hidden?

I have added a UISearchController to my code using the following method:
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.scopeButtonTitles = #[];
self.searchController.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
[self.searchController.searchBar sizeToFit];
self.definesPresentationContext = YES;
This creates my search controller and adds it to the top of my tableView. Annoyingly it starts visible though:
I can hide it by sliding it up under the navigation bar which suggests the underlying functionality of the code is working but I can't get it to start hidden so I can slide it down.
I have tried adjusting the edge insets, I have tried setting the navigation bar to translucent, I have tried to go through the search bar tutorials online but nothing seems to be dealing with this issue.
Any help very welcome
Did you try setting the content offset of your table view?
[self.tableView setContentOffset:CGPointMake(0, self.searchController.searchBar.frame.size.height) animated:NO];
Here is for swift 4
tableView.setContentOffset(CGPoint(x: 0, y: searchController.searchBar.frame.size.height), animated: true)
From iOS 11.0 onwards you can use,
self.navigationItem.searchController = self.searchController;
The search bar will be hidden, unless you swipe down to reveal it.

UISearchBar changes its superview when it is added to UITableViewCell on iOS 7.1

In my project i need an UISearchBar to scroll on an UITableView. So i just put it on an UITableViewCell like this:
searchBar = [[SearchBar alloc] initWithFrame:cell.bounds];
searchBar.delegate = self;
searchBar.placeholder = NSLocalizedString(#"Search friends", "");
searchBar.layer.borderWidth = 1.f;
searchBar.layer.borderColor = [UIColor whiteColor].CGColor;
sdc = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:nil];
sdc.delegate = self;
[cell addSubview:searchBar];
and it works fine on iOS 6. But on iOS 7 it switches to another superview (and literally disappears from the screen) when just getting in focus. At first i thought it's something wrong with my project which causes such a behaviour but then i created a simple test project and i verified this - indeed, it's a rule, on iOS 7.1 UISearchBar added to UITableViewCell moves to another superview and gets lost from the screen right after becoming first responder.
I have overridden willMoveToSuperview: method on the search bar and i see that it moves from UITableViewCellScrollView to a view which class is UIView and whose superview's class is UISearchDisplayControllerContainerView.
After few hours of search and experiments i'm not able to figure out what causes this behaviour and how to escape it. All i know for sure is that it happens right between calls to these two UISearchDisplayDelegate methods: searchDisplayControllerWillBeginSearch: and searchDisplayControllerDidBeginSearch:.
Did anyone ever encountered this? Any ideas how to resolve it?
Are you sure you need this bizarre way to add UISearchBar to UITableViewCell to just scroll it? I simply use smthng like this:
UISearchBar *mainSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
mainSearchBar.delegate = self;
UISearchDisplayController *searchCon = [[UISearchDisplayController alloc] initWithSearchBar:mainSearchBar contentsController:self ];
searchCon.delegate = self;
searchCon.searchResultsDataSource = self;
searchCon.searchResultsDelegate = self;
mainTableView.tableHeaderView = mainSearchBar;

UISearchBar is covered up in a tableViewHeader

I have placed a UISearchBar in my UITableView.tableHeaderView. However it covers the searchBar by placing the viewable top to the first section header. I can only see the searchBar when I drag the tableView down. It is half covered and then can not be selected because releasing the tableView scrolling will rubber band it back out of view. Please help.
The following is placed in my UITableViewController viewDidLoad method:
UISearchBar *theSearchBar = [[UISearchBar alloc] init];
theSearchBar.delegate = self;
self.searchBar = theSearchBar;
[theSearchBar release];
self.tableView.tableHeaderView = self.searchBar;
The result is the following screenshots: http://imagebin.ca/view/6qNiwHR.html
It turns out that it was a sizing issue. I found a tutorial that places the following code in the set up:
[theSearchBar sizeToFit];
which make everything look perfect.
Since UISearchDisplayController uses an already established UISearchBar it doesn't eliminate the problem.
I think the tableHeaderView is not the best place to put your search bar.
I usually use a UISearchDisplayController:
searchController = [[UISearchDisplayController alloc]
initWithSearchBar:theSearchBar contentsController:self];
searchController.delegate = self;
searchController.searchResultsDataSource = self;
searchController.searchResultsDelegate = self;
It's pretty straight-forward and give some functions for searching (you have to implement them in the delegate/datasource, in this case your controller).
I usually do it from a nib but i think you just have to assign it to your viewcontroller :
self.searchDisplayController=searchController;
And if it doesn't show the view, you should add the view to the tableView directly.
You can look at the reference, or ask if you have some problems.

Resources