简体   繁体   中英

Tab Bar and UISearchController giving black screen

I have two scenes which can be accessed through a tab bar, on scene 1 there is a search bar. the problem that I am facing is that while searching if I switch to the downloads tab -

  1. The navigation bar disappears.
  2. When I come back to the search tab, it gives me a black screen.

This is screen 1 while searching - 搜索时屏幕1

Now when I click on the downloads tab, the navigation bar disappears.

Here is the view controller for the first screen -

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"
                }

        }
    }


}

我在iOS12中遇到了这个问题,并通过将hostingPresentationContext设置为true来修复它,以便托管搜索控制器的viewcontroller。

self.definesPresentationContext = true

This is because there is probably no separate navigation controller for the tab that gives you a black screen on back. For maintaining the navigation hierarchy seperately, you should embed a uinavigationcontroller to the uiviewcontroller and from IB check Top Bar as opaque navigation bar instead of Inferred . Hope this helps. Cheerio

Behind the scenes the search controller is being presented. This is what is causing the black screen when returning.

Solution 1

The simplest way is to override UISearchController and set isActive=false in it's viewDidDisappear ( https://stackoverflow.com/a/39212080/215748 ). It works, but I found some usability issues with this solution. I didn't pursue it, so they may be easy enough to overcome.

Solution 2

Call the following before moving away from the view controller:

searchController.dismiss(animated: false, completion: nil)

Add this to viewDidDisappear .

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    dismissSearch()
}

func dismissSearch() {
    searchController.dismiss(animated: false, completion: nil)
}

Unfortunately, viewDidDisappear doesn't get called when you switch tabs, because the search controller is being presented. It received the viewDidDisappear . To get around this, you can subclass UITabBarController and implement 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
    }

Looks like the view that your UISearchController is attached to gets removed from the view hierarchy. You can think of the UISearchController as being presented modally when you start searching, and the definesPresentationContext property indicates which UIViewController would be the one to present it ( more on this ).

You can get more detail in the answer to a possibly duplicate question: https://stackoverflow.com/a/37357242/300131

只需将UiNavigationcontroller添加到下载选项卡的uiviewcontroller,它将解决问题停电和隐藏的导航栏

What if you move this bit of code

self.activityIndicator.stopAnimating()
self.activityIndicator.hidden = true

to after your result? Like this:

          // If the network works fine
          if response.result.isFailure != true {

               self.activityIndicator.stopAnimating()
               self.activityIndicator.hidden = true

(if that works, you would also need to include it on the other side of your else too... )

 // If the network fails
                else {
                    self.activityIndicator.stopAnimating()
                    self.activityIndicator.hidden = true

                    self.retryButton.hidden = false
                    self.loadingMessageLabel.text = "Check your internet connectivity"
                }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM