标签栏和 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 的大小

你如何使用 Storyboards 引用 UISearchController

聚焦时如何调整 UISearchController.searchBar 的大小问题?