Swift:为UISearchBar的ScopeBar设置图片而非标题
给UISearchBar的ScopeBar设置图片的解决方案
嘿,我刚好折腾过这个问题!其实UISearchBar的scopeBar本质就是个藏在内部的UISegmentedControl,所以操作思路和你熟悉的普通分段控件完全一致——先找到它,再给每个分段设置图片就行。
第一步:找到ScopeBar对应的UISegmentedControl
系统没有直接提供获取这个分段控件的API,所以我们需要遍历searchBar的子视图来定位它:
Swift 代码示例
// 假设你的UISearchBar实例名为searchBar if let scopeSegmentedControl = searchBar.subviews.first?.subviews.first(where: { $0 is UISegmentedControl }) as? UISegmentedControl { // 这里就拿到了scopeBar对应的分段控件 }
Objective-C 代码示例
UISegmentedControl *scopeSegmentedControl = nil; for (UIView *subview in self.searchBar.subviews) { for (UIView *innerSubview in subview.subviews) { if ([innerSubview isKindOfClass:[UISegmentedControl class]]) { scopeSegmentedControl = (UISegmentedControl *)innerSubview; break; } } if (scopeSegmentedControl) break; }
第二步:给分段设置图片
拿到分段控件后,就可以用你熟悉的方法来设置图片了,和普通分段控件操作完全一样:
Swift 完整示例
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if let scopeSegmentedControl = searchBar.subviews.first?.subviews.first(where: { $0 is UISegmentedControl }) as? UISegmentedControl { // 加载图片,记得设置渲染模式为alwaysOriginal避免系统 tint 干扰 let firstScopeImage = UIImage(named: "first_icon")?.withRenderingMode(.alwaysOriginal) let secondScopeImage = UIImage(named: "second_icon")?.withRenderingMode(.alwaysOriginal) // 给对应分段设置图片 scopeSegmentedControl.setImage(firstScopeImage, forSegmentAt: 0) scopeSegmentedControl.setImage(secondScopeImage, forSegmentAt: 1) // 如果只想显示图片、隐藏文字,可以设置空标题 scopeSegmentedControl.setTitle("", forSegmentAt: 0) scopeSegmentedControl.setTitle("", forSegmentAt: 1) } }
Objective-C 完整示例
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; UISegmentedControl *scopeSegmentedControl = nil; for (UIView *subview in self.searchBar.subviews) { for (UIView *innerSubview in subview.subviews) { if ([innerSubview isKindOfClass:[UISegmentedControl class]]) { scopeSegmentedControl = (UISegmentedControl *)innerSubview; break; } } if (scopeSegmentedControl) break; } if (scopeSegmentedControl) { UIImage *firstScopeImage = [[UIImage imageNamed:@"first_icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; UIImage *secondScopeImage = [[UIImage imageNamed:@"second_icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; [scopeSegmentedControl setImage:firstScopeImage forSegmentAtIndex:0]; [scopeSegmentedControl setImage:secondScopeImage forSegmentAtIndex:1]; // 隐藏文字设置空标题 [scopeSegmentedControl setTitle:@"" forSegmentAtIndex:0]; [scopeSegmentedControl setTitle:@"" forSegmentAtIndex:1]; } }
几个关键注意点
- 图片渲染模式:一定要设置
alwaysOriginal,不然系统会把图片渲染成searchBar的 tint 颜色,导致图片显示异常。 - 执行时机:建议在
viewDidAppear里执行这段代码,或者在自定义UISearchBar的layoutSubviews方法中处理,确保searchBar的子视图已经完全加载完成,避免找不到分段控件的情况。 - 兼容性提醒:遍历子视图的方式依赖于系统UISearchBar的内部结构,虽然目前iOS版本都能正常工作,但未来苹果可能调整内部布局。如果是商业项目,也可以考虑自定义一个分段控件放在searchBar下方,替代原生scopeBar,这样更稳定可控。
内容的提问来源于stack exchange,提问作者Wael
相关产品推荐
相关产品推荐

