在UILabel展示日本Furigana

时间:2017-11-10 18:07:45

标签: ios swift uilabel cjk

Furigana(也称为rubi)是日语阅读辅助工具,由汉字(表意字符)旁边印刷的小假名或音节字符组成

我在互联网上找到了如何通过以下代码在UILable中显示假名:

<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger"  class="display nowrap" cellspacing="0" width="100%" >

我是Swift的新手,所以我只是复制并粘贴到我的x-code项目,但它无法正常工作(错误:无法将类型&#39;未管理&#39;的值转换为预期的参数类型&# 39; UnsafeMutablePointer&GT;&#39;) 我尽可能地研究,但没有任何效果。请帮忙

结果应该是这样的 enter image description here

3 个答案:

答案 0 :(得分:2)

Swift 4

class ViewController: UIViewController {
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        let text = "|東京都《とうきょうと》"
        label.attributedText = text.attributedStringWithRuby()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
extension String {

    func attributedStringWithRuby() -> NSMutableAttributedString {

        // "|": ルビを振る対象の文字列を判定し区切る為の記号(全角). ルビを振る文字列の先頭に挿入する
        // "《》": ルビを振る対象の漢字の直後に挿入しルビを囲う(全角)

        let attributed =
            self.replace(pattern: "(|.+?《.+?》)", template: ",$1,")
                .components(separatedBy: ",")
                .map { x -> NSAttributedString in
                    if let pair = x.find(pattern: "|(.+?)《(.+?)》") {
                        let string = (x as NSString).substring(with: pair.range(at: 1))
                        let ruby = (x as NSString).substring(with: pair.range(at: 2))

                        var text = [.passRetained(ruby as CFString) as Unmanaged<CFString>?, .none, .none, .none]
                        let annotation = CTRubyAnnotationCreate(.auto, .auto, 0.5, &text[0])

                        return NSAttributedString(
                            string: string,
                            attributes: [kCTRubyAnnotationAttributeName as NSAttributedStringKey: annotation])
                    } else {
                        return NSAttributedString(string: x, attributes: nil)
                    }
                }
                .reduce(NSMutableAttributedString()) { $0.append($1); return $0 }

        return attributed
    }

    func find(pattern: String) -> NSTextCheckingResult? {
        do {
            let re = try NSRegularExpression(pattern: pattern, options: [])
            return re.firstMatch(
                in: self,
                options: [],
                range: NSMakeRange(0, self.utf16.count))
        } catch {
            return nil
        }
    }

    func replace(pattern: String, template: String) -> String {
        do {
            let re = try NSRegularExpression(pattern: pattern, options: [])
            return re.stringByReplacingMatches(
                in: self,
                options: [],
                range: NSMakeRange(0, self.utf16.count),
                withTemplate: template)
        } catch {
            return self
        }
    }
}

由于苹果公司在iOS 11中的错误,这个解决方案毫无用处。

Code Result: As you can see, there isn't furigana

我在一个月前向Apple发出此错误的信号,但我还没有回答。

一个用户建议覆盖uilabel的方法drawText,但是存在很多问题,因为uilabel所做的每一个文本管理都没有。

无论如何,如果你想看到他的解决方案,这就是他的回答https://stackoverflow.com/a/47377024/3489707

请,如果您找到解决方案,请发布。这非常重要

答案 1 :(得分:0)

不是一个完整的答案,但这是我在Swift 4中使用ruby的代码中的一个简短摘要-可以清除,但可能是一个有价值的代码示例,因为要在这些函数上查找资源非常困难:

    let annotationAttribs: [AnyHashable: Any] = [
        kCTRubyAnnotationSizeFactorAttributeName: rubySizeFactor,
        kCTRubyAnnotationScaleToFitAttributeName: true,
    ]
    let annotation = CTRubyAnnotationCreateWithAttributes(
        alignment, .auto, CTRubyPosition.before, ruby as CFString, annotationAttribs as CFDictionary)

    let attribs: [NSAttributedStringKey: Any] = [
        NSAttributedStringKey(kCTRubyAnnotationAttributeName as String): annotation, //.takeUnretainedValue(),
        NSAttributedStringKey("RubyText"): ruby,
    ]
    return NSAttributedString(
        string: string,
        attributes: attribs)

答案 2 :(得分:-1)

我找到了一个很好的解决方案

Swift 4.2

此解决方案是对预览答案的更新,可以让您编写日语句子,并使用一种模式可以显示带有假名的句子。

在此解决方案中,您使用3个String扩展名

func find(pattern: String) -> NSTextCheckingResult? {
do {
    let findRubyText = try NSRegularExpression(pattern: pattern, options: [])
    return findRubyText.firstMatch(
        in: self,
        options: [],
        range: NSMakeRange(0, self.utf16.count))
} catch {
    return nil
}
}

func replace(pattern: String, template: String) -> String {
do {
    let replaceRubyText = try NSRegularExpression(pattern: pattern, options: [])
    return replaceRubyText.stringByReplacingMatches(
        in: self,
        options: [],
        range: NSMakeRange(0, self.utf16.count),
        withTemplate: template)
} catch {
    return self
}
}

func rubyAttributedString(font: UIFont, textColor: UIColor) -> NSMutableAttributedString {
let attributed =
    self.replace(pattern: "(|.+?《.+?》)", template: ",$1,")
        .components(separatedBy: ",")
        .map { x -> NSAttributedString in
            if let pair = x.find(pattern: "|(.+?)《(.+?)》") {
                let baseText = (x as NSString).substring(with: pair.range(at: 1))
                let ruby = (x as NSString).substring(with: pair.range(at: 2))

                let rubyAttribute: [AnyHashable: Any] = [
                    kCTRubyAnnotationSizeFactorAttributeName: 0.5,
                    kCTForegroundColorAttributeName: textColor
                ]

                let annotation = CTRubyAnnotationCreateWithAttributes(.auto, .auto, .before, ruby as CFString, rubyAttribute as CFDictionary)

                return NSAttributedString(
                    string: baseText,
                    attributes: [.font: font,
                                 .foregroundColor: textColor,
                                 kCTRubyAnnotationAttributeName as NSAttributedString.Key: annotation])

            } else {
                return NSAttributedString(
                    string: x,
                    attributes: [.font: font,
                                 .foregroundColor: textColor]
                )
            }
        }
        .reduce(NSMutableAttributedString()) { $0.append($1); return $0     }

return attributed
}

此扩展允许您创建一个NSAttributed字符串以提供给标签

Great solution written in Japanese but it possible to download the example project