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

SwiftUI中如何动态更新并显示NSMutableAttributedString(Mac端)

Mac端SwiftUI显示带单个变色字符的NSMutableAttributedString

要在Mac端SwiftUI中实现类似Spritz的单字符变色文本显示,可通过封装NSViewRepresentable适配NSTextField来安全展示富文本,解决直接使用时的崩溃问题。以下是完整实现方案:

1. 封装富文本显示组件

先创建通用的AttributedText组件,专门用于在SwiftUI中展示NSAttributedString:

import SwiftUI

struct AttributedText: NSViewRepresentable {
    var attributedString: NSAttributedString
    
    func makeNSView(context: Context) -> NSTextField {
        let textField = NSTextField()
        textField.isEditable = false
        textField.isSelectable = false
        textField.drawsBackground = false
        textField.alignment = .center // 匹配Spritz居中显示需求
        textField.font = NSFont.systemFont(ofSize: 32) // 可按需调整字号
        return textField
    }
    
    func updateNSView(_ nsView: NSTextField, context: Context) {
        nsView.attributedStringValue = attributedString
    }
}

2. 修改主视图实现

调整SpritzViewMac,使用封装好的组件并优化更新逻辑避免崩溃:

struct SpritzViewMac: View {
    let spritz = Spritz(Eingabe:"Welcome to SpritzSwift! Spritz is a brand new revolutionary reading method that will help you to improve your number of words per minute. Take a look at SpritzSwift!", wordsPerMinute: 400)
    
    @State private var spritzWordForText = NSAttributedString(string: "Test")
    private let markerColor: NSColor = .systemRed // Mac平台用NSColor
    
    func updateWord(_ wordInput: SpritzWord){
        let attributedString = NSMutableAttributedString(string: wordInput.word)
        let attributes: [NSAttributedString.Key: Any] = [
            .foregroundColor: markerColor
        ]
        // 检查标记位置合法性,防止越界崩溃
        guard wordInput.markerPosition >= 0,
              wordInput.markerPosition < wordInput.word.count else {
            spritzWordForText = attributedString
            return
        }
        let range = NSRange(location: wordInput.markerPosition, length: 1)
        attributedString.setAttributes(attributes, range: range)
        spritzWordForText = attributedString
    }
    
    var body: some View {
        VStack {
            AttributedText(attributedString: spritzWordForText)
                .frame(width: 300, height: 100) // 按需调整尺寸
        }
    }
}

// 补充必要的类型定义(若未实现)
struct SpritzWord {
    let word: String
    let markerPosition: Int
}

class Spritz {
    init(Eingabe: String, wordsPerMinute: Int) {
        // 实现你的Spritz核心逻辑
    }
}

关键注意点

  • 组件通过updateNSView方法安全更新富文本,避免直接操作NSView引发崩溃;
  • 增加标记位置合法性检查,防止字符串越界访问;
  • 使用NSColor替代iOS的UIColor,适配Mac平台;
  • 将NSTextField设置为不可编辑、不可选中,符合阅读场景需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:27:43