我正在处理使用UITabBarController
的应用,并且只有一个tabItem停止显示。然后,我开始调查并最终遇到与UISearchController
和UITabBarController
相关的问题。
要解决问题,请构建一个简单的应用来说明情况。
这是我在didFinishLaunchingWithOptions
:
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
与在主线程中渲染多个动画有关。
我想知道这个viewcontroller可视化问题是否与此相关。所以我评论了SearchController类中的searchController
实例化行:
self.navigationItem.searchController = searchController
现在UITabBarController
在我的第一个视图控制器中没有UISearchController
的情况下工作正常。
我的问题是:
GitHub存储库,示例代码为:sample code
答案 0 :(得分:0)
我的一位朋友建议在UITabBarController
添加UINavigationController
作为didFinishLaunchingWithOptions
的根,并且它可以完美地解决问题:
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
答案 1 :(得分:0)
在您的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! NewsCollectionViewController).searchController.isActive = false
}
return true
}
答案 2 :(得分:0)
在视图控制器上使用tableView设置definesPresentationContext = true
(在您的示例中为SearchController
)。当您切换标签页时,这将使UISearchController
保持活动状态。