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

SwiftUI日志视图:如何实现隔行变色且支持跨全选文本?

解决SwiftUI日志视图隔行变色+跨行文本选择的兼容问题

核心思路是使用AttributedString将所有日志行合并为一个富文本对象,既可以为每一行(段落)设置独立的背景色,又能保持单个Text视图的跨文本选择能力。

实现代码

import SwiftUI

struct LogView: View {
    let lines: [String] = sampleText3.components(separatedBy: "\n")
    
    // 合并带格式的富文本
    private var attributedLog: AttributedString {
        var fullAttributedString = AttributedString()
        
        for (index, line) in lines.enumerated() {
            var lineAttr = AttributedString(line)
            
            // 设置文字颜色
            lineAttr.foregroundColor = adaptiveLineColor(line)
            
            // 设置隔行背景色
            let backgroundColor = index % 2 == 0 ? Color.gray.opacity(0.1) : Color.black.opacity(0.1)
            lineAttr.backgroundColor = backgroundColor
            
            // 添加行内边距(模拟原布局的padding)
            lineAttr.padding(.horizontal, 5)
            
            fullAttributedString.append(lineAttr)
            // 每行末尾添加换行(最后一行省略多余空行)
            if index != lines.endIndex - 1 {
                fullAttributedString.append(AttributedString("\n"))
            }
        }
        
        return fullAttributedString
    }
    
    var body: some View {
        ScrollView {
            Text(attributedLog)
                .textSelection(.enabled)
                .border(.gray.opacity(0.1), width: 1)
                .padding()
        }
        .padding()
    }
    
    // 优化后的日志行颜色判断
    func adaptiveLineColor(_ line: String) -> Color {
        enum Tag: String {
            case task = "[Task]"
            case info = "[info]"
            case warning = "[warning]"
            case error = "[error]"
        }
        
        guard let tag = Tag(rawValue: line.prefix(6).trimmingCharacters(in: .whitespaces)) else {
            return .primary
        }
        
        switch tag {
        case .task:
            return .green
        case .info:
            return .primary
        case .warning:
            return .yellow
        case .error:
            return .red
        }
    }
}

let sampleText3: String = """
[Task] Process started. 30. Sep 2023, 21:26:20
[info] input file /someFolder/someData
[warning] invalid metadata
[error] error -1234
"""

关键说明

  1. AttributedString段落背景:给每一行对应的AttributedString设置backgroundColor实现隔行变色,所有行合并为一个整体后,仍能支持跨文本选择。
  2. 保留原有样式:原有的文字颜色逻辑优化为switch语句,同时通过padding属性模拟原布局的行内边距。
  3. 跨选能力生效:单个Text视图承载全部内容,.textSelection(.enabled)可正常支持跨多行选择文本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:55:06