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

如何使用SwiftUI实现日语振假名(Furigana/ruby文本)展示?

SwiftUI 实现日语振假名(Ruby注音)方案

首先明确两个路径的可行性:纯SwiftUI在新系统版本上可以零桥接直接实现,低版本下通过极简的UIKit桥接也能完成需求,不需要深入学习UIKit知识。


纯SwiftUI原生实现(推荐,iOS 15.0+ 可用)

iOS 15 开始SwiftUI的Text组件原生支持AttributedString的Ruby注音属性,渲染逻辑和系统文本完全对齐,不会出现注音错位、排版异常问题,同时自动支持动态字体、深色模式、VoiceOver 等所有系统文本特性。
核心实现是给对应汉字段绑定rubyAnnotation属性,示例代码如下:

import SwiftUI

struct FuriganaDemoView: View {
    private var demoText: AttributedString {
        var content = AttributedString("新しいiPhone")
        // 给「新」加注音あたら
        if let range = content.range(of: "新") {
            content[range].rubyAnnotation = AttributeContainer()
                .rubyText(AttributedString("あたら"))
        }
        return content
    }
    
    var body: some View {
        Text(demoText)
            .font(.title2)
            .padding()
    }
}

如果你的应用最低支持版本设定在iOS15及以上,直接用这个方案就够,不需要引入任何第三方或者桥接代码。


低版本兼容方案:UIKit桥接实现(支持iOS 8.0+)

如果需要兼容iOS14及更早版本,只需要用SwiftUI提供的UIViewRepresentable协议对UIKit的UILabel做一层极薄的封装即可,不需要掌握复杂的UIKit开发知识,封装完成后和普通SwiftUI组件用法完全一致。
UILabel从iOS8开始就通过CoreText的CTRubyAnnotation接口支持振假名渲染,稳定性经过了长期验证。可直接复用的封装代码如下:

import SwiftUI
import UIKit
import CoreText

struct RubyAttributedText: UIViewRepresentable {
    private let content: NSAttributedString
    
    /// 初始化方法
    /// - Parameters:
    ///   - plainText: 原始日语文本
    ///   - rubyMap: 汉字与对应振假名的键值对,比如 ["日本":"にほん"]
    init(plainText: String, rubyMap: [String: String]) {
        let attrStr = NSMutableAttributedString(string: plainText)
        rubyMap.forEach { kanji, kana in
            let range = (plainText as NSString).range(of: kanji)
            guard range.location != NSNotFound else { return }
            // 配置注音属性
            let ruby = CTRubyAnnotationCreateWithAttributes(
                .auto, .auto, .before,
                [kCTRubyAnnotationTextAttribute as String: kana as CFString] as CFDictionary
            )
            attrStr.addAttribute(kCTRubyAnnotationAttributeName as NSAttributedString.Key,
                                 value: ruby,
                                 range: range)
        }
        self.content = attrStr
    }
    
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.numberOfLines = 0
        label.attributedText = content
        return label
    }
    
    func updateUIView(_ uiView: UILabel, context: Context) {
        uiView.attributedText = content
    }
}

// 调用示例
// RubyAttributedText(plainText: "日本語のテスト", rubyMap: ["日本語":"にほんご"])

如果需要处理大量长文本,不需要手动维护汉字和假名的映射表,可以调用系统NaturalLanguage框架的日语分词和读音识别接口,自动生成注音映射,效率更高。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:42:11