【问题标题】:UIViewcontroller disappear after switch tabs UITabBarControllerUIViewcontroller 在切换标签后消失 UITabBarController
【发布时间】:2018-10-02 19:45:31
【问题描述】:

我正在开发一个使用 UITabBarController 的应用程序,并且突然停止出现一个 tabItem。然后我开始调查并最终发现与UISearchControllerUITabBarController 相关的问题。

为了隔离问题,构建一个简单的应用程序来演示情况。

这就是我在didFinishLaunchingWithOptions 上实例化 TabBar 的方式:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.backgroundColor = .white

    let first:SearchController = {
        let sc = SearchController()
        sc.tabBarItem = UITabBarItem(title: "First", image: UIImage(named:"iphone"), tag: 0)
        return sc
    }()

    let second:SecondViewController = {
        let s = SecondViewController()
        s.tabBarItem = UITabBarItem(title: "Second", image: UIImage(named:"iphone"), tag: 1)
        return s
    }()

    let tabBar = UITabBarController()
    let controllers = [first, second]
    tabBar.viewControllers = controllers.map {
        UINavigationController(rootViewController: $0)
    }


    self.window?.rootViewController = tabBar
    self.window?.makeKeyAndVisible()
    return true
}

这是带有 UISearchController 的 viewController:

class SearchController: UIViewController {
    var matchingItems:[String] = [] {
        didSet{
            self.tableView.reloadData()
        }
    }

    lazy var searchController:UISearchController = UISearchController(searchResultsController: nil)

    lazy var tableView: UITableView = { [unowned self] in
        let tv = UITableView(frame: CGRect.zero, style: .grouped)
        tv.translatesAutoresizingMaskIntoConstraints = false
        tv.delegate = self
        tv.dataSource = self
        tv.register(UITableViewCell.self, forCellReuseIdentifier: "id")
        return tv
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "First"
        view.addSubview(self.tableView)
        self.navigationItem.searchController = searchController
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.perform(#selector(showKeyboard), with: nil, afterDelay: 0.1)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        searchController.searchBar.resignFirstResponder()
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        let layout = self.view.safeAreaLayoutGuide
        tableView.topAnchor.constraint(equalTo: layout.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: layout.bottomAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: layout.rightAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: layout.leftAnchor).isActive = true
    }

    @objc func showKeyboard() {
        self.searchController.searchBar.becomeFirstResponder()
        self.searchController.searchBar.text = ""
    }
}

在运行时,当系统完成渲染此视图控制器时,调试控制台会打印:

SearchBar+TabBar[15454:895018] [MC] Reading from private effective user settings.
2018-04-22 12:07:19.595887-0300 SearchBar+TabBar[15454:895018] +[CATransaction synchronize] called within transaction
2018-04-22 12:07:19.608090-0300 SearchBar+TabBar[15454:895018] +[CATransaction synchronize] called within transaction
2018-04-22 12:07:19.608269-0300 SearchBar+TabBar[15454:895018] +[CATransaction synchronize] called within transaction
2018-04-22 12:07:19.608516-0300 SearchBar+TabBar[15454:895018] +[CATransaction synchronize] called within transaction

在stackoverflow上搜索我发现这条消息+[CATransaction synchronize] called within transaction 与在主线程中渲染多个动画有关。

我想知道这个视图控制器可视化问题是否与此有关。所以我在 SearchController 类中注释了searchController 实例化行:

self.navigationItem.searchController = searchController

现在UITabBarController 在我的第一个视图控制器中没有UISearchController 也能完美运行。

我的问题是:

  1. 是否有另一种方法来实例化 UISearchController 以避免 这个?
  2. 如果是,我应该怎么做?

带有示例代码的 GitHub 存储库:sample code

【问题讨论】:

  • 我认为这种情况永远不会上升。键盘出现后如何切换选项卡项?键盘覆盖整个标签栏。 (在实际场景中,在物理设备/模拟器中使用模拟器键盘)

标签: ios swift uiviewcontroller uitabbarcontroller uisearchcontroller


【解决方案1】:

我的一个朋友建议在didFinishLaunchingWithOptions 中添加UITabBarController 作为UINavigationController 的根,它可以完美地工作并解决问题:

let tabBar = UITabBarController()
let controllers = [first, second]
tabBar.viewControllers = controllers.map {
    UINavigationController(rootViewController: $0)
}


let nav = UINavigationController(rootViewController: tabBar)
nav.isNavigationBarHidden = true
nav.navigationBar.isUserInteractionEnabled = false

【讨论】:

    【解决方案2】:

    在你的 TabBarController 类中实现这个功能:

    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool
    

    在这个函数中,你应该检查之前是否选择了带有 searchBar 的 Controller 并使 SearchController 处于非活动状态

    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        if (tabBarController.selectedIndex == ControllerWithSearchBarIndex) {
            ((viewControllers![ControllerWithSearchBarIndex] as! UINavigationController).viewControllers.first! as! ControllerWithSearchBarIndex).searchController.isActive = false
        }
        return true
    }
    

    【讨论】:

      【解决方案3】:

      使用 tableView 在视图控制器上设置definesPresentationContext = true(在您的示例中为SearchController)。这将允许UISearchController 在您切换标签时保持活动状态。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-24
        • 2023-03-23
        • 1970-01-01
        • 2017-07-11
        • 1970-01-01
        • 1970-01-01
        • 2017-12-23
        • 1970-01-01
        相关资源
        最近更新 更多