You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:44:34