1

Furigana (also known as rubi) is Japanese reading aid, consisting of smaller kana, or syllabic characters, printed next to a kanji (ideographic character)

I found on internet how to display furigana in UILable by the following code

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!

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


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.rangeAt(1))
                    let ruby = (x as NSString).substring(with: pair.rangeAt(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 String: 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
    }
}

I am new to Swift, so I just copy and paste to my x-code project, but it is not working (with error: Cannot convert value of type 'Unmanaged' to expected argument type 'UnsafeMutablePointer?>') I try to research much as I can, but nothing working. Please help

The result should be something like this enter image description here

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Shin622
  • 645
  • 3
  • 7
  • 22

1 Answers1

0

Not a full answer, but here is a quick snippet from my code where I am using ruby in Swift 4 - this can be cleaned up, but could be a valuable code sample as it's exceedingly difficult to find resources on these functions:

    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)
aehlke
  • 15,225
  • 5
  • 36
  • 45