标签栏和 UISearchController 出现黑屏
Posted
技术标签:
【中文标题】标签栏和 UISearchController 出现黑屏【英文标题】:Tab Bar and UISearchController giving black screen 【发布时间】:2016-04-29 12:20:24 【问题描述】:我有两个可以通过标签栏访问的场景,在场景 1 中有一个搜索栏。 我面临的问题是,在搜索时,如果我切换到下载选项卡 -
-
导航栏消失。
当我返回搜索选项卡时,它给了我一个黑屏。
这是搜索时的屏幕 1 -
现在当我点击下载标签时,导航栏消失了。
这是第一个屏幕的视图控制器 -
import UIKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating, UISearchBarDelegate
//MARK: Variables
var papers = [Paper]()
var filteredPapers = [Paper]()
let searchController = UISearchController(searchResultsController: nil)
// MARK: Outlets
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet var table: UITableView!
@IBOutlet weak var loadingMessageLabel: UILabel!
@IBOutlet weak var retryButton: UIButton!
//MARK: Actions
@IBAction func retryButton(sender: UIButton)
self.loadingMessageLabel.hidden = false
self.loadingMessageLabel.text = "While the satellite moves into position..."
self.activityIndicator.hidden = false
self.activityIndicator.startAnimating()
self.retryButton.hidden = true
self.getPapersData()
// MARK: Table View
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// If in searching mode, then return the number of results else return the total number
// if searchController.active && searchController.searchBar.text != ""
if searchController.active
return filteredPapers.count
return papers.count
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let paper: Paper
// if searchController.active && searchController.searchBar.text != ""
if searchController.active
paper = filteredPapers[indexPath.row]
else
paper = papers[indexPath.row]
if let cell = self.table.dequeueReusableCellWithIdentifier("Cell") as? PapersTableCell
cell.initCell(paper.name, detail: paper.detail)
print(cell)
return cell
return PapersTableCell()
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?
let downloadButton = UITableViewRowAction(style: .Normal, title: "Download") action, index in
var url = String(self.papers[indexPath.row].url)
url = url.stringByReplacingOccurrencesOfString(" ", withString: "%20")
print(url)
let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
// Spinner in cell
// var selectCell = self.table.cellForRowAtIndexPath(indexPath) as? PapersTableCell
// selectCell!.downloadSpinner.hidden = false
// Dismiss the download button
self.table.editing = false
Alamofire.download(.GET, url, destination: destination).response _, _, _, error in
if let error = error
print("Failed with error: \(error)")
else
print("Downloaded file successfully")
// selectCell?.downloadSpinner.hidden = true
downloadButton.backgroundColor = UIColor(red:0.30, green:0.85, blue:0.39, alpha:1.0)
return [downloadButton]
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
// the cells you would like the actions to appear needs to be editable
return true
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
// you need to implement this method too or you can't swipe to display the actions
// MARK: Search
func filterContentForSearchText(searchText: String, scope: String = "All")
filteredPapers = papers.filter paper in
let categoryMatch = (scope == "All") || (paper.exam == scope)
return categoryMatch && paper.name.lowercaseString.containsString(searchText.lowercaseString)
table.reloadData()
func updateSearchResultsForSearchController(searchController: UISearchController)
let searchBar = searchController.searchBar
let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
filterContentForSearchText(searchController.searchBar.text!, scope: scope)
func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int)
filterContentForSearchText(searchBar.text!, scope: searchBar.scopeButtonTitles![selectedScope])
// MARK: Defaults
override func viewDidLoad()
super.viewDidLoad()
self.getPapersData()
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
table.tableHeaderView = searchController.searchBar
searchController.searchBar.scopeButtonTitles = ["All", "ST1", "ST2", "PUT", "UT"]
searchController.searchBar.delegate = self
activityIndicator.startAnimating()
override func viewWillDisappear(animated: Bool)
// if searchController.active
self.searchController.resignFirstResponder()
//
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
// MARK: API call
func getPapersData()
Alamofire.request(.GET, "http://silive.in/bytepad/rest/api/paper/getallpapers?query=")
.responseJSON response in
self.activityIndicator.stopAnimating()
self.activityIndicator.hidden = true
// If the network works fine
if response.result.isFailure != true
self.loadingMessageLabel.hidden = true
self.table.hidden = false
//print(response.result) // result of response serialization
let json = JSON(response.result.value!)
for item in json
// Split the title on the . to remove the extention
let title = item.1["Title"].string!.characters.split(".").map(String.init)[0]
let category = item.1["ExamCategory"].string
let url = item.1["URL"].string
let detail = item.1["PaperCategory"].string
let paper = Paper(name: title, exam: category!, url: url!, detail: detail!)
self.papers.append(paper)
self.table.reloadData()
// If the network fails
else
self.retryButton.hidden = false
self.loadingMessageLabel.text = "Check your internet connectivity"
【问题讨论】:
放一些代码来解决这个问题。 @Mr.Bond 添加了代码。 如何在搜索模拟器时切换到其他选项卡?因为键盘会向下显示,所以搜索时无法切换选项卡 @Sherin 是的,我正在使用模拟器,但是当我单击键盘上的搜索按钮时,它被关闭了。此时搜索控制器仍处于活动状态。现在我可以访问标签栏了。 模拟器中有一些相关的错误。请在真实设备上查看实际性能。甚至 Apple 也建议在真实设备上进行测试,而不是在模拟器上进行测试。请经常测试并尽早在真实设备上测试。可能模拟器不存在问题。 【参考方案1】:我在 ios12 中遇到了这个问题,并通过将托管搜索控制器的视图控制器的定义PresentationContext 设置为 true 来修复它。
self.definesPresentationContext = true
【讨论】:
完美修复了两种情况下的黑屏问题 - 当 UISearchController 附加到 NavigationItem(通常是 iOS 11+)时,以及当它附加到表视图标题时(通常是 iOS 9 和 10)。但是在表格视图标题的情况下,表格可能存在小的布局问题(可以解决或忽略它们,仍然比黑屏好得多)。 还修复了搜索栏在活动状态下被遮挡和变暗,因此无法交互的问题。【参考方案2】:这是因为标签页可能没有单独的导航控制器,让您在背面出现黑屏。为了单独维护导航层次结构,您应该将 uinavigationcontroller 嵌入到 uiviewcontroller 并从 IB 检查 Top Bar 作为不透明导航栏而不是 推断。希望这可以帮助。干杯
【讨论】:
【参考方案3】:在幕后呈现搜索控制器。这就是返回时黑屏的原因。
解决方案 1
最简单的方法是覆盖 UISearchController 并将 isActive=false
设置为 viewDidDisappear
(https://***.com/a/39212080/215748)。它有效,但我发现此解决方案存在一些可用性问题。我没有追求它,所以它们可能很容易克服。
解决方案 2
在离开视图控制器之前调用以下代码:
searchController.dismiss(animated: false, completion: nil)
将此添加到viewDidDisappear
。
override func viewDidDisappear(_ animated: Bool)
super.viewDidDisappear(animated)
dismissSearch()
func dismissSearch()
searchController.dismiss(animated: false, completion: nil)
不幸的是,viewDidDisappear
在您切换选项卡时不会被调用,因为正在显示搜索控制器。它收到了viewDidDisappear
。为了解决这个问题,您可以继承 UITabBarController
并实现 UITabBarControllerDelegate
。
// don't forget to set the delegate
extension TabBarController: UITabBarControllerDelegate
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool
if let navigationController = viewControllers?[selectedIndex] as? UINavigationController
for myController in navigationController.viewControllers.flatMap( $0 as? MyTableViewController )
myController.dismissSearch()
return true
【讨论】:
【参考方案4】:看起来您的UISearchController
附加到的视图已从视图层次结构中删除。当您开始搜索时,您可以将 UISearchController
视为模态呈现,definesPresentationContext
属性指示哪个 UIViewController
将呈现它 (more on this)。
您可以在可能重复的问题的答案中获得更多详细信息:https://***.com/a/37357242/300131
【讨论】:
【参考方案5】:只需将 UiNavigationcontroller 添加到下载选项卡的 uiviewcontroller 即可解决问题停电和隐藏导航栏
【讨论】:
【参考方案6】:如果你移动这段代码会怎样
self.activityIndicator.stopAnimating()
self.activityIndicator.hidden = true
要追求你的结果吗?像这样:
// If the network works fine
if response.result.isFailure != true
self.activityIndicator.stopAnimating()
self.activityIndicator.hidden = true
(如果可行,您还需要将其包含在 else 的另一侧...)
// If the network fails
else
self.activityIndicator.stopAnimating()
self.activityIndicator.hidden = true
self.retryButton.hidden = false
self.loadingMessageLabel.text = "Check your internet connectivity"
【讨论】:
以上是关于标签栏和 UISearchController 出现黑屏的主要内容,如果未能解决你的问题,请参考以下文章
显示和隐藏 uisearchcontroller 时调用的函数
材料迅速:带有搜索栏和标签栏的 UIView 迅速移出视图 3
Swift - 使用导航栏和标签栏获取 viewController 的大小