如何自定义UISearchBar取消按钮样式?代码仅对SearchController的SearchBar生效
问题原因与解决方案
直接通过@IBOutlet引入的UISearchBar,其取消按钮并不受全局UIBarButtonItem.appearance()的样式影响——因为它的视图层级和归属逻辑,和UISearchController绑定的searchBar不同,后者是嵌入在导航栏相关组件体系里,所以全局样式能生效。
下面是两种可行的解决方法:
方法一:针对性设置Appearance
修改全局样式的作用范围,只针对UISearchBar内部的UIBarButtonItem生效,这样你的直接IBOutlet的searchBar也能应用样式:
fileprivate static func applyStyle() { // 仅对UISearchBar内部的BarButtonItem应用样式 let appearance = UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]) let commonAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.bodySmall, .foregroundColor: ColorEnum.black, .kern: NSNumber(value: Float(NLLetterSpacing.bodySmall)) ] appearance.setTitleTextAttributes(commonAttributes, for: .normal) appearance.setTitleTextAttributes(commonAttributes, for: .highlighted) appearance.setTitleTextAttributes([ .font: UIFont.bodySmall, .foregroundColor: ColorEnum.pinkishGrey, .kern: NSNumber(value: Float(NLLetterSpacing.bodySmall)) ], for: .disabled) }
方法二:手动查找取消按钮设置样式
如果方法一存在版本兼容性问题,可以直接遍历searchBar的子视图找到取消按钮,手动设置其富文本样式:
// 在ViewController的viewDidLoad或searchBar的初始化方法中调用 func setupSearchBarCancelButtonStyle() { guard let cancelButton = searchBar.value(forKey: "cancelButton") as? UIButton else { return } let commonAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.bodySmall, .foregroundColor: ColorEnum.black, .kern: NSNumber(value: Float(NLLetterSpacing.bodySmall)) ] // 设置正常和高亮状态 cancelButton.setAttributedTitle(NSAttributedString(string: "取消", attributes: commonAttributes), for: .normal) cancelButton.setAttributedTitle(NSAttributedString(string: "取消", attributes: commonAttributes), for: .highlighted) // 设置禁用状态 let disabledAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.bodySmall, .foregroundColor: ColorEnum.pinkishGrey, .kern: NSNumber(value: Float(NLLetterSpacing.bodySmall)) ] cancelButton.setAttributedTitle(NSAttributedString(string: "取消", attributes: disabledAttributes), for: .disabled) }
注:
value(forKey: "cancelButton")是访问UISearchBar的私有属性,仅用于获取视图设置样式,这种操作在App Store审核中通常是允许的。
内容的提问来源于stack exchange,提问作者bruno
相关产品推荐
相关产品推荐

