我有一个SearchViewController
,作为此ViewController
的一部分,我有一个UISearchController
(SearchResultsController
名为SearchResultsTableViewController
。我注意到我的SearchResultsTableViewController
UITableView
contentInset.top
比应该多20分,尽管它在iOS8 / 9上很好并且automaticallyAdjustScrollViewInsets
=真。如果我从这个ViewController
执行一个segue到另一个,然后返回,我看到contentInset.top
增加了另外20个点。同样,这不会发生在iOS8 / 9上。以下是显示此行为的couple of images。
以下是两个相关ViewControllers
的代码。
class SearchViewController: UIViewController, UISearchBarDelegate, UISearchControllerDelegate {
@IBOutlet var tableView: UITableView!
@IBOutlet var backgroundImageView: UIImageView!
var searchController: UISearchController!
var backBarButtonItem: UIBarButtonItem!
var searchButtonTapped = false
@IBOutlet var titleLabel: SpringLabel!
@IBOutlet var loadingIndicatorView: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
let searchResultsVC = self.storyboard!.instantiateViewController(withIdentifier: "SearchResultsTableViewController") as! SearchResultsTableViewController
searchResultsVC.searchController = self
searchController = UISearchController(searchResultsController: searchResultsVC)
searchController.searchResultsUpdater = searchResultsVC
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = true
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.searchBar.placeholder = "Search Courses"
searchController.view.backgroundColor = UIColor.clear
searchController.searchBar.keyboardAppearance = .dark
self.setSearchBarCaretColor(UIColor(red: 0.24, green: 0.34, blue: 0.19, alpha: 1.0))
self.setSearchBarFontSize(17.0)
self.navigationItem.titleView = searchController.searchBar
self.definesPresentationContext = true
self.backBarButtonItem = self.navigationItem.leftBarButtonItem
self.backgroundImageView.clipsToBounds = true
self.titleLabel.alpha = 0
self.titleLabel.layer.shadowColor = UIColor.black.cgColor
self.titleLabel.layer.shadowOpacity = 0.8
self.titleLabel.layer.shadowOffset = CGSize(width: 2.0, height: 2.0)
self.titleLabel.layer.shouldRasterize = true
self.titleLabel.layer.rasterizationScale = UIScreen.main.scale
self.loadingIndicatorView.layer.zPosition = CGFloat.greatestFiniteMagnitude
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.perform(#selector(SearchViewController.showKeyboard), with: nil, afterDelay: 0.01)
searchBarTextDidBeginEditing(searchController.searchBar)
}
func showKeyboard() {
self.searchController.searchBar.becomeFirstResponder()
}
func hideKeyboard() {
self.searchController.searchBar.resignFirstResponder()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.titleLabel.delay = 0.1
self.titleLabel.animation = "zoomIn"
self.titleLabel.duration = 0.6
self.titleLabel.animate()
let selectedRowIndexPath = self.tableView.indexPathForSelectedRow
if ((selectedRowIndexPath) != nil) {
self.tableView.deselectRow(at: selectedRowIndexPath!, animated: true)
self.transitionCoordinator?.notifyWhenInteractionEnds({ context in
if (context.isCancelled) {
self.tableView.selectRow(at: selectedRowIndexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)
}
})
}
}
func setSearchBarCaretColor(_ color : UIColor) {
let view = searchController.searchBar.subviews[0]
let subViewsArray = view.subviews
for subView in subViewsArray {
if subView.isKind(of: UITextField.self) {
subView.tintColor = color
}
}
}
func setSearchBarFontSize(_ pointSize : CGFloat) {
let view = searchController.searchBar.subviews[0]
let subViewsArray = view.subviews
for subView in subViewsArray {
if subView.isKind(of: UITextField.self) {
let textField = subView as! UITextField
textField.font = UIFont.systemFont(ofSize: pointSize)
}
}
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
//This doesn't animate for some reason, so don't use it.
if (UI_USER_INTERFACE_IDIOM() != .pad) { //Because the iPad (for some reason) doesn't ever show the Cancel button, so keep the back button.
UIView.animate(withDuration: 0.3, animations: { self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView()) }, completion: { Void in
self.navigationItem.setHidesBackButton(true, animated: false)
})
}
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
if (self.searchButtonTapped == false) {
self.navigationItem.leftBarButtonItem = self.backBarButtonItem
self.navigationItem.setHidesBackButton(false, animated: true)
} else {
self.searchButtonTapped = false
}
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
self.navigationItem.leftBarButtonItem = self.backBarButtonItem
self.navigationItem.setHidesBackButton(false, animated: true)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.searchButtonTapped = true
searchBar.resignFirstResponder()
}
}
现在这里是SearchResultsTableViewController:
class SearchResultsTableViewController: UITableViewController, UISearchResultsUpdating {
var resultsArray = [CourseResult]()
var emptySearchResultsView : EmptySearchResultsView!
var keyboardActive = false
var keyboardHeight : CGFloat = 0.0
var searchController : SearchViewController!
var query = PFQuery(className: "Course")
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.backgroundColor = UIColor.clear
self.tableView.estimatedRowHeight = 140
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.keyboardDismissMode = .onDrag
self.emptySearchResultsView = EmptySearchResultsView.construct(self) as EmptySearchResultsView
emptySearchResultsView.translatesAutoresizingMaskIntoConstraints = true
self.emptySearchResultsView.isHidden = true
self.tableView.addSubview(emptySearchResultsView)
query.whereKey("institution", equalTo: "College")
query.limit = 20
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.registerKeyboardNotifications()
let selectedRowIndexPath = self.tableView.indexPathForSelectedRow
if ((selectedRowIndexPath) != nil) {
self.tableView.deselectRow(at: selectedRowIndexPath!, animated: true)
self.transitionCoordinator?.notifyWhenInteractionEnds({ context in
if (context.isCancelled) {
self.tableView.selectRow(at: selectedRowIndexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)
}
})
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.unregisterKeyboardNotifications()
}
var lastSearch = ""
func updateSearchResults(for searchController: UISearchController) {
guard searchController.isActive else { return }
if (lastSearch == searchController.searchBar.text!) {
return
}
self.lastSearch = searchController.searchBar.text!
query.cancel()
self.emptySearchResultsView.isHidden = true
if (searchController.searchBar.text?.characters.count == 0) {
resultsArray.removeAll()
self.tableView.reloadData()
}
if ((searchController.searchBar.text?.characters.count)! > 0) {
self.searchController.loadingIndicatorView.startAnimating()
var searchString = searchController.searchBar.text!
searchString = searchString.lowercased()
var searchStringArray = searchString.components(separatedBy: " ")
searchStringArray = searchStringArray.filter { $0 != "" }
//print(searchStringArray.description)
query.whereKey("searchTerms", containsAllObjectsIn: searchStringArray)
query.findObjectsInBackground(block: { (results, error) -> Void in
if (error == nil) {
self.resultsArray = []
let courseResultsArray = results! as [PFObject]
for result in courseResultsArray {
//removed all of this jargon.
}
self.searchController.loadingIndicatorView.stopAnimating()
self.tableView.reloadData()
if (self.resultsArray.count == 0) {
self.emptySearchResultsView.isHidden = false
} else {
self.emptySearchResultsView.isHidden = true
}
} else {
print(error?.localizedDescription)
self.searchController.loadingIndicatorView.stopAnimating()
}
})
}
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if (self.keyboardActive == true) {
self.emptySearchResultsView.frame = CGRect(x: 0, y: 0, width: self.tableView.bounds.width, height: self.tableView.bounds.height - self.keyboardHeight - self.tableView.contentInset.top)
self.emptySearchResultsView.setNeedsLayout()
} else {
self.emptySearchResultsView.frame = CGRect(x: 0, y: 0, width: self.tableView.bounds.width, height: self.tableView.bounds.height - self.tableView.contentInset.top)
self.emptySearchResultsView.setNeedsLayout()
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return resultsArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellContent: CourseResult = self.resultsArray[(indexPath as NSIndexPath).row]
let cell = tableView.dequeueReusableCell(withIdentifier: "CourseResultTableViewCell", for: indexPath) as! CourseResultTableViewCell
cell.backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
cell.backgroundColor = UIColor.clear
cell.courseLabel.text = cellContent.courseCode + " - " + cellContent.courseName
cell.universityLabel.text = cellContent.university
cell.facultyLabel.text = cellContent.faculty
cell.leftHandSideImageView.image = UIImage(named: cellContent.faculty)
cell.leftHandSideImageView.layer.shadowColor = UIColor.black.cgColor
cell.leftHandSideImageView.layer.shadowOpacity = 0.6
cell.leftHandSideImageView.layer.shouldRasterize = true
cell.leftHandSideImageView.layer.rasterizationScale = UIScreen.main.scale
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let schedulesVC = self.storyboard!.instantiateViewController(withIdentifier: "SchedulesViewController") as! SchedulesViewController
schedulesVC.selectedCourse = self.resultsArray[(indexPath as NSIndexPath).row]
self.searchController.show(schedulesVC, sender: tableView)
}
func registerKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(SearchResultsTableViewController.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(SearchResultsTableViewController.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func unregisterKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(_ notification: Notification) {
if (UI_USER_INTERFACE_IDIOM() != .phone) { //Because devices like iPads don't have they keyboards affect the error screen visibility much.
return
}
if let keyboardFrame = ((notification as NSNotification).userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue {
UIView.animate(withDuration: 0.6, animations: { self.emptySearchResultsView.frame = CGRect(x: 0, y: 0, width: self.tableView.bounds.width, height: self.tableView.bounds.height - keyboardFrame.height - self.tableView.contentInset.top)
self.emptySearchResultsView.layoutIfNeeded()
})
self.keyboardActive = true
self.keyboardHeight = keyboardFrame.height
}
}
func keyboardWillHide(_ notification: Notification) {
if (UI_USER_INTERFACE_IDIOM() != .phone) {
return
}
UIView.animate(withDuration: 0.6, animations: { self.emptySearchResultsView.frame = CGRect(x: 0, y: 0, width: self.tableView.bounds.width, height: self.tableView.bounds.height - self.tableView.contentInset.top)
self.emptySearchResultsView.layoutIfNeeded()
})
self.keyboardActive = false
}
}
这些ViewControllers
中的每一个都在故事板中都有自己的表示。
有没有人知道为什么我会看到这种行为,这只在iOS10中出现过?这个问题出现在我测试的各种设备上。
注意:只需忽略与结果或任何其他相关代码相关的任何字符串解析代码。我删除了一些这样的东西,试图让代码更加连贯,以及json解析代码等等。
唯一对我有用的解决方案(不理想)是检查设备是否在运行iOS10,并根据状态栏的高度动态调整contentInset.top
并navigationBar
。显然我必须关闭automaticallyAdjustScrollViewInsets
才能做到这一点。