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

SwiftUI中使用UIBlurEffect为按钮添加模糊效果卡顿问题排查

问题分析与解决

卡顿原因

  • 模糊效果本身的性能开销:systemThinMaterial这类动态模糊需要GPU实时计算背景内容的模糊处理,每个按钮单独实例化UIVisualEffectView时,多个实例同时渲染会大幅增加GPU负载,滚动时屏幕刷新频率高,卡顿问题就会凸显。
  • 实现方式的不合理性:
    • 每个按钮都创建独立的UIVisualEffectView实例,无复用机制,若按钮在滚动列表中,会频繁创建、销毁视图,加重性能负担。
    • updateUIView方法中每次都重新创建UIBlurEffect,即使样式未变化,会触发不必要的视图更新,浪费资源。

优化方案

方案1:使用SwiftUI原生模糊背景(iOS 15+)

苹果在iOS 15后提供了原生模糊背景样式,无需自定义封装UIViewRepresentable,SwiftUI会统一优化渲染逻辑,性能远优于自定义实现。修改按钮样式代码如下:

struct DefaultStyle: ButtonStyle {
    @Environment(.colorScheme) var colorScheme

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .background(.systemThinMaterial) // 替换为原生模糊背景
            .foregroundColor(colorScheme == .dark ? .white : .black)
            .opacity(configuration.isPressed ? 0.7 : 1.0)
    }
}

方案2:优化自定义封装(兼容iOS 15以下)

如果需要兼容旧版本iOS,可对自定义的BlurryButton做以下优化:

  1. 避免不必要的视图更新,仅当样式变化时才更新模糊效果:
struct BlurryButton: UIViewRepresentable {
    var style: UIBlurEffect.Style
    
    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView {
        UIVisualEffectView(effect: UIBlurEffect(style: style))
    }
    
    func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) {
        // 仅当样式变化时才更新效果
        guard let currentEffect = uiView.effect as? UIBlurEffect, 
              currentEffect.style != style else {
            return
        }
        uiView.effect = UIBlurEffect(style: style)
    }
}
  1. 若按钮在滚动列表中,使用LazyVStack/LazyHStack替代普通VStack/HStack,仅创建可见区域的按钮,减少同时存在的模糊视图数量。

方案3:全局复用模糊背景(按需使用)

如果布局允许,可在父视图层面创建一个全局模糊背景视图,所有按钮放置在该背景之上,仅需一个模糊效果实例,大幅降低性能开销。

内容的提问来源于stack exchange,提问作者ProtonFission

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:08:16