SearchController changes the size of tableView - ios

The size of my tableView mysteriously changes heights when the search controller is active like the images I attached below.
The image in the far left is the initial state. Middle image is when the search controller is active and the last image is when the search controller is dismissed.
I tried setting the content size of the tableview when the search controller is active, in the viewDidLoad, viewWillAppear and viewDidAppear without any luck.
Any idea on how to resolve this problem?
P.S. The items you see are just dummy posts.

Try set edgesForExtendedLayout property to be under Top Bar using code
or storyboard

I solved it by setting the extendedLayOut to 0
self.edgesForExtendedLayout = UIRectEdge.init(rawValue: 0)
However, the status bar was covering the search bar so I hide the status bar when the searchController is active
override var prefersStatusBarHidden: Bool {
return searchController.isActive
}

Related

Animation Delayed for navigationBar "hidesBarOnSwipe"

Hi everyone I have a UITableViewController that hides the navigation bar when the user writes the tableView
navigationController? .hidesBarsOnSwipe = true
When the user shows the navigationBar by scrolling down the tableview, the navigationbar's slide animation appears to be delayed showing a black space between the tableView and the navigation bar
How can you solve this problem?
Here you can see what happens when the navigation bar is shown after the user scrolls down
Maybe you can try in viewDidLoad in your UITableViewController
self.edgesForExtendedLayout = []
Hope it will help you

How to hide UISearchController inside of navigation bar

I want to dismiss/hide UISearchController from navigation bar when I switch tabs, I tried many things, if I set it to nil a black layer is shown in the search space. The settings view controller should not present the UISearch any thoughts?
Without seeing your code, this is what I would do if I wanted to hide my search bar. Use the following code to hide searchBar:
searchBar.isHidden = true
view.backgroundColor = .orange
//.clear? Or whatever colour you want to be there in the background.
//In viewDidLoad put
searchBar.isHidden = false
I was adding only one Navigation Controller to all tabs, I changed it, now for each tab I have an independent navigation controller, so it is solved.

iOS 11 - Weird UINavigationBar and UICollectionView behavior

I have a UINavigationController the root view controller of which is a UIViewController with a UICollectionView. The collection has constraint to the left, right, bottom and top. I've checked the prefersLargeTitles attribute in the UINavigationController, so I have big titles. I expected that, during the scroll, the UINavigationBar would automatically collapse, but I had to disable the large titles in my root view controller and add this line of code in my viewWillAppear :
navigationItem.largeTitleDisplayMode = .automatic
Then, I added also the search bar to the UINavigationBar, in this way :
let searchController = UISearchController.init(searchResultsController: nil)
searchController.searchResultsUpdater = self
navigationItem.searchController = searchController
Everything is perfect, visually.
Now, when I scroll down, the UICollectionView suddenly stick to the UINavigationBar which collapses. When I tap on the status bar to go to the top of the collection, a white space appears between the large title and the status bar. Is there a specific procedure that, for some reason, I'm not following? Do you have any solution?
EDIT:
Here you can find the video of the problem
When you see the collection that sticks to the UINavigationBar I confirm you that it's happening in a unnatural way. The last "bug" happens when I tap on the status bar.

UISearchBar of UISearchController moves off screen when active

I need to have a UISearchBar above a UITableView (ie. the search bar is not part of the table view), and what I found is that when the search bar is activated, it moves off screen.
I did a fair bit of search and could not find a solution, there are ‘search bar off screen’ issues but they are adding search bar to table's header view and tweaking properties like definesPresentationContext fixed it.
My view hierarchy:
VC’s view
|— top view
|— segmented control
|— search bar
|— table view
Looks like UISearchController expects the search bar to be inside the table view, and always shifts the table view so that the search bar moves to the very top of screen.
Anyone having the same issue and found a solution?
Thanks a lot!
// Swift 5
// if you are using UISearch Controller then simply add line below to your
viewDidLoad() and it will fix the issue.
override func viewDidLoad() {
super.viewDidLoad()
// fixes the search moving to next screen when its active
self.definesPresentationContext = true
}
Updates
After further testing I decided to just implement the UISearchBar delegate and stop using the UISearchController since I was just reusing my UICollectionView for the results. Found a great guide on how three different methods to implement the SearchBar.
Edge Case #1
TLDR
Enable clips to bounds on the containing view. Or if you have a collection view cell that has a user-generated content view, enable clips to bounds on that content view.
Details:
An additional very important fact is that you may have the search bar embedded in a container view. This can cause issues if the container view does not have clips to bounds enabled. Other examples of this being a problem is the user-generated content views in UICollectionViewCells. Compare the setting on a UITableViewCell auto-generated content view to observe the difference.
Summary
A Boolean value that determines whether subviews are confined to the
bounds of the view. Declaration
var clipsToBounds: Bool { get set } Discussion
Setting this value to true causes subviews to be clipped to the bounds
of the receiver. If set to false, subviews whose frames extend beyond
the visible bounds of the receiver are not clipped. The default value
is false.
Swift 4.x Solution
In my case, this was happening both inside a UICollectionView and inside of a UIStackView. I was able to keep my searchBar in place after noticing the following info in the searchBar quick help.
Summary
The search bar to install in your interface. Declaration
var searchBar: UISearchBar { get } Discussion
Before presenting your searchable content, install the search bar in
this property somewhere into your view controller’s interface. The
search bar becomes the starting point for searching your contents.
Interactions with the search bar are handled automatically by the
UISearchController object, which notifies the object in the
searchResultsUpdater property whenever the search information changes.
To use a custom subclass of UISearchBar, subclass UISearchController
and implement this property to return your custom search bar.
After that I was able to resolve the issue successfully by doing the following:
let searchController = UISearchController(searchResultsController: nil)
var searchBar:UISearchBar!
Sometime later I assign the searchBar from the searchController to the searchBar in my UIViewController...
BTW - I embed my searchBar in a container UIView that has all the contraints I need to keep it in place.
func setupSearchController<T:UIViewController>(delegate vc:T) where T: UISearchResultsUpdating, T:UISearchBarDelegate {
searchBar = searchController.searchBar //this is the key
searchController.searchResultsUpdater = vc
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search".localized()
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = vc
searchController.searchBar.showsCancelButton = true
definesPresentationContext = true
self.searchMenu.addSubview(searchBar)
//searchMenu is a constrained UIView in my hierarchy
}
I believe putting searchBar inside tableView is not mandatory. I had same issue some time back. All you need to do is setting proper auto layout constraint. Adjust leading and trailing of searchView as align to leading and trailing of the tableView. Also release the margin property from constraints. Hope this may help you.
After a few tries, I've found the reason being that when the UISearchBar is activated, UISearchController removes it from your view and puts it on its own view with a table view for showing the results, since I use auto-layout for the search bar, by removing it, some of the constraints are screwed up. So my solution was to not use auto layout for the UISearchBar from UISearchController.
If you choose to use UISearchBar without an UISearchController, which I have found much easier for keeping UISearchBar within its initial bounds, here is the code template:
final class MyUIViewController: UIViewController {
// MARK: Properties
private let tableView = UITableView()
private let searchBar = UISearchBar()
...
// MARK: View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
...
searchBar.delegate = self
searchBar.sizeToFit()
tableView.tableHeaderView = searchBar
}
}
extension MyUIVewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
... // Your code filtering tableView dataSource goes here
tableView.reloadData()
}
}

UISearchController with UIBarPositionTopAttached throws UISearchBar offscreen; impossible to have standard UISearchController with UITableView?

I'm trying to create a similar experience to the Contacts apps in iOS 8. The primary components of this are:
Keep the search bar fixed below the navigation bar
Have the search bar attach to the top of the view (standard functionality) when presenting.
This, however, is easier said than done. After a while of struggling with tableHeaderView (which didn't allow for interaction in front of the table view, and was complex with the viewDidLayoutSubviews positioning), I decided to embed a UITableView within a UIViewController, so I could add the UISearchBar as a subview. This worked pretty well, and allowed interaction with the search bar at all scroll positions, and the insets weren't hard to calculate.
But, the search bar gets cut off below the status bar, when activated. Seems like a straightforward issue—even if I didn't experience it with the exact same implementation in a UITableViewController. So, I tried making sure all my properties were set up for alignment, in every possible view controller.
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = YES;
self.automaticallyAdjustsScrollViewInsets = NO;
I've tried every possible combination of these, in viewWillAppear as well as viewDidLoad, as well as translucent navigation bars and different starting frames for the table view and search bar. No luck. So, I tried to adjust the frames or constraints, perhaps using the topLayoutGuide or just 0. Unfortunately, adjusting the frame in any of the UISearchControllerDelegate methods didn't actually adjust its presented position, and adding constraints crashed immediately when the active animation begins (due to super.top not existing in the view hierarchy at the time; removing the constraints in willPresent did absolutely nothing).
After struggling for a bit longer, I tried implementing positionForBar as the UISearchBar's delegate:
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar {
return UIBarPositionTopAttached;
}
This seemed to adjust the height, but the search bar flies off the top of the view. When activated, the search bar seems to appear directly above the visible area. This is even worse than it getting clipped behind or below the UIStatusBar. I also tried to just hide the status bar when the search controller becomes active, but conditionally implementing prefersStatusBarHidden didn't work at all (returning YES works great without UISearchController active, but when active it shows the status bar again or it gets shown beneath it). I assume this is because UISearchController refuses to obey any standards or rules, as is now painfully clear.
I've been trying to figure this out for a few days now, and I can't think of a solution besides reimplementing the UISearchController class/animation entirely. Please help!
For the behavior you described, this works great for me 😊
var resultSearchController = UISearchController()
And the following in your viewDidLoad function:
//Search Bar
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.searchBar.sizeToFit()
controller.dimsBackgroundDuringPresentation = false
self.tableView.tableHeaderView = controller.searchBar
self.definesPresentationContext = true
return controller
})()
What worked for me was to subclass UISearchController and override the prefersStatusBarHidden in the subclass.
Also make sure View Controller Based Status Bar Appearance is set to YES
And in your viewcontroller containing the tableview / search bar:
self.definesPresentationContext = YES;
I have the same problem. I add a UISearchController to UIViewController,not using tableView.header. And the UISearchBar.superview.frame.origin.y is -44. So you cannot see the searchBar.
Method 1: You can change the frame of UISearchBarWrapperView in the didPresentSearchController,the delegate of UISearchControllerDelegate。But you will see the animation of this process.
Method 2: like JBlake say. Set self.definesPresentationContext = YES; after the UISearchController is init. It works!
What i understood is if u need searchbar under navigationbar as u mentioned in #1 its very easy just set a boolean (Solution for #1) searchController.hidesNavigationBarDuringPresentation = true
Unfortunately i couldnt fix the searchbar-offscreen-issue while navigationbar is hidden.

Resources