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

如何将UIBarButtonItem数组转换为SwiftUI的ToolbarItem数组?

解决UIKit UIBarButtonItem转SwiftUI ToolbarContent的问题

错误原因分析

你的代码出现No exact matches in reference to static method 'buildExpression'报错,核心问题有几个:

  1. UIBarButtonItem未遵循Identifiable协议,ForEach无法直接遍历非可识别元素
  2. 自定义的toolbarButtons未整合到body中,SwiftUI无法识别这部分工具栏内容
  3. 强制解包item.title!存在崩溃风险,部分按钮(如系统图标按钮)可能没有标题
  4. 未处理UIBarButtonItem的多种类型(系统按钮、自定义视图等)

完整解决方案

以下是修复后的代码,同时适配了多种UIBarButtonItem类型:

// 给UIBarButtonItem添加Identifiable协议支持,让ForEach可以遍历
extension UIBarButtonItem: Identifiable {
    public var id: UUID {
        // 用UUID生成唯一标识,若需精准区分可结合item.target+item.action生成
        UUID()
    }
}

struct ToolBarItems: ToolbarContent {
    let barButtons: [UIBarButtonItem]
    
    var body: some ToolbarContent {
        // 主标题区域
        ToolbarItem(placement: .principal) {
            Text("principal Title")
        }
        
        // 遍历右侧按钮并转换为SwiftUI ToolbarItem
        ForEach(barButtons) { item in
            ToolbarItem(placement: .navigationBarTrailing) {
                // 适配不同类型的UIBarButtonItem
                switch item.systemItem {
                case .add:
                    Button(action: item.action ?? {}) {
                        Image(systemName: "plus")
                    }
                case .done:
                    Button(action: item.action ?? {}) {
                        Text("Done").bold()
                    }
                // 可继续添加其他系统按钮的适配逻辑
                default:
                    // 处理自定义标题或自定义视图的按钮
                    if let customView = item.customView {
                        UIViewWrapper(view: customView)
                    } else {
                        Button(action: item.action ?? {}) {
                            Text(item.title ?? "")
                        }
                    }
                }
            }
        }
    }
}

// 用于将UIKit视图包装为SwiftUI可识别视图的工具结构体
struct UIViewWrapper: UIViewRepresentable {
    let view: UIView
    
    func makeUIView(context: Context) -> UIView {
        view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {}
}

关键修复点说明

  • Identifiable扩展:让UIBarButtonItem满足ForEach的遍历要求
  • 内容整合:将右侧按钮的遍历逻辑直接放入body,确保SwiftUI能识别完整的工具栏内容
  • 安全处理:用item.title ?? ""替代强制解包,避免空值崩溃
  • 多类型适配:区分系统按钮、自定义视图按钮,保证不同UIKit按钮都能正确转换
  • 视图包装:通过UIViewRepresentable将UIBarButtonItem的自定义视图转换为SwiftUI兼容视图

使用示例

在SwiftUI视图中直接调用该ToolbarContent:

struct ContentView: View {
    // 模拟从UIKit传入的rightBarButtonItems数组
    let uiKitBarButtons: [UIBarButtonItem] = [
        UIBarButtonItem(title: "编辑", style: .plain, target: nil, action: nil),
        UIBarButtonItem(systemItem: .add)
    ]
    
    var body: some View {
        NavigationStack {
            Text("SwiftUI Content")
                .toolbar {
                    ToolBarItems(barButtons: uiKitBarButtons)
                }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:05:15