iOS11中显示UISearchController后跳转UIViewController出现黑块问题
我之前也碰到过完全一样的坑!iOS 11开始把UISearchController直接挂到navigationItem上时,系统会动态调整导航栏高度,但如果跳转页面时没正确处理搜索栏的状态,很容易出现导航区域的黑块——本质是旧的布局约束残留或者导航栏层级没有正确更新导致的。下面是我亲测有效的几种解决方法,按优先级推荐:
方法一:跳转前主动清理搜索控制器状态
这是最直接的解决方案,在执行页面跳转(push/present)之前,先手动重置搜索栏的状态并移除搜索控制器,确保导航栏布局回到正常状态:
// 1. 收起键盘并取消搜索激活状态 searchController.searchBar.resignFirstResponder() searchController.isActive = false // 2. 从导航项中移除搜索控制器 navigationItem.searchController = nil // 3. 强制触发导航栏布局更新,避免约束残留 navigationController?.navigationBar.setNeedsLayout() navigationController?.navigationBar.layoutIfNeeded() // 4. 执行跳转操作 navigationController?.pushViewController(nextViewController, animated: true)
这种方法的好处是精准控制时机,不会影响其他场景下的搜索栏使用。
方法二:在viewWillDisappear中统一处理
如果你的跳转逻辑比较分散,不想在每个跳转点都加代码,可以在当前控制器的viewWillDisappear方法里统一做清理:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 只有当搜索控制器处于激活状态时才处理 guard searchController.isActive else { return } searchController.isActive = false navigationItem.searchController = nil // 强制更新布局,修复黑块 navigationController?.navigationBar.setNeedsLayout() navigationController?.navigationBar.layoutIfNeeded() }
这里要注意:如果是从下一个页面pop回来,你需要在viewWillAppear里重新把searchController设置回navigationItem,确保搜索栏能正常显示。
方法三:修复导航栏背景/阴影层
有时候黑块并不是约束问题,而是导航栏的背景图或阴影层在搜索栏移除后没有正确恢复。比如你之前为了适配搜索栏修改过导航栏的背景设置,可以在清理搜索控制器后手动恢复:
// 移除搜索控制器后,恢复导航栏默认背景(如果之前有自定义的话) navigationController?.navigationBar.setBackgroundImage(nil, for: .default) navigationController?.navigationBar.shadowImage = nil
如果是自定义了导航栏背景,记得在布局更新后重新设置正确的背景图片或颜色。
问题根源补充
iOS 11对UISearchController的导航栏集成做了重构,系统会动态添加/修改导航栏的布局约束来适配搜索栏的展开/收起状态。当页面跳转时,如果搜索控制器还处于激活状态,这些动态约束没有被正确移除,就会导致导航栏的布局计算出错,出现黑块(其实是导航栏的背景没有填充到正确的高度区域)。
内容的提问来源于stack exchange,提问作者just

