使用 SearchController 搜索时使用标签栏出现黑屏
Posted
技术标签:
【中文标题】使用 SearchController 搜索时使用标签栏出现黑屏【英文标题】:Getting black screen on using tab bar while searching using SearchController 【发布时间】:2016-05-20 16:58:19 【问题描述】:我有一个在导航控制器中嵌入标签栏控制器的应用。该应用程序有 2 个选项卡,第一个(搜索)有一个使用 UISearchController 实现的搜索栏。如果我在搜索时从这个选项卡切换到另一个选项卡(下载),那么会发生两件事 -
第二个标签(下载)中的导航栏消失了 当我回到第一个选项卡(搜索)时,它显示黑屏我已经使用情节提要完成了所有这些工作。
这是我的 SearchViewController
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"
这是我的 DownloadViewController
import UIKit
import QuickLook
class DownloadViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, QLPreviewControllerDataSource
var items = [(name:String, url:String)]()
@IBOutlet weak var downloadsTable: UITableView!
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return items.count
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
print(items[indexPath.row].url)
// performSegueWithIdentifier("DocumentViewSegue", sender: items[indexPath.row].url)
let previewQL = QLPreviewController() // 4
previewQL.dataSource = self // 5
previewQL.currentPreviewItemIndex = indexPath.row // 6
showViewController(previewQL, sender: nil) // 7
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
if let cell = self.downloadsTable.dequeueReusableCellWithIdentifier("Download Cell") as? DownloadsTableCell
cell.initCell(items[indexPath.row].name, detail: "", fileURL: items[indexPath.row].url)
return cell
return DownloadsTableCell()
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
if editingStyle == UITableViewCellEditingStyle.Delete
// let fileManager = NSFileManager.defaultManager()
//
// // Delete 'hello.swift' file
//
// do
// try fileManager.removeItemAtPath(String(items[indexPath.row].url))
//
// catch let error as NSError
// print("Ooops! Something went wrong: \(error)")
//
items.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
override func viewDidAppear(animated: Bool)
items.removeAll()
let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
// now lets get the directory contents (including folders)
do
let directoryContents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(documentsUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions())
// print(directoryContents)
for var file in directoryContents
print(file.lastPathComponent)
print(file.absoluteURL)
// Save the data in the list as a tuple
self.items.append((file.lastPathComponent!, file.absoluteString))
catch let error as NSError
print(error.localizedDescription)
downloadsTable.reloadData()
// MARK: Preview
func numberOfPreviewItemsInPreviewController(controller: QLPreviewController) -> Int
return items.count
func previewController(controller: QLPreviewController, previewItemAtIndex index: Int) -> QLPreviewItem
return NSURL(string: items[index].url)!
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
override func viewWillAppear(animated: Bool)
//do something
super.viewWillAppear(true)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
*/
【问题讨论】:
【参考方案1】:看起来您的UISearchController
附加到的视图已从视图层次结构中删除。当您开始搜索时,您可以将UISearchController
视为模态呈现,definesPresentationContext
属性指示哪个UIViewController
将呈现它(more on this)。
解决此问题的方法之一是重新配置您的故事板,以便每个选项卡都有自己的UINavigationController
(以防两者都需要):
而不是(我怀疑你现在拥有的):
如果您想在选项卡切换时关闭UISearchController
,请将此覆盖添加到ViewController
:
override func viewWillDisappear(animated: Bool)
super.viewWillDisappear(animated)
searchController.active = false
【讨论】:
导航控制器嵌入标签栏控制器时遇到了同样的问题。带有导航的视图还包含一个搜索栏。我不需要更改情节提要中的任何内容,只需设置self.definesPresentationContext = true
,谢谢!
在 viewDidLoad 中设置 self.definesPresentationContext = true
为我解决了这个问题。并且每个标签都有一个单独的UINavigationController
。
@Hendrix 我的配置和你的一样,但这对我没有帮助。我在视图确实加载时以编程方式实现了搜索控制。以上是关于使用 SearchController 搜索时使用标签栏出现黑屏的主要内容,如果未能解决你的问题,请参考以下文章
除非我在搜索栏中点击,否则 SearchController 不会显示未过滤的结果
UINavigationBar变成白色,在iOS 13中使用navigationItem.searchController时不会关闭
当 searchController 处于活动状态时,UIButton 不起作用?