

iOSアプリのUILabelにルビ付きのテキストを設定したいのですがUILabel.attributedTextにCFAttributedStringRef型のルビを付けたテキストをNSAttributedString型にキャストしたものを代入してもコンパイルは通るものの実行時エラーで止まります。  
下記コードの一部になります。
<http://dev.classmethod.jp/references/ios8-ctrubyannotationref/>
を参考にさせていただきました。

[code]

    UILabel *textLbl = (UILabel*)[cell viewWithTag:1];
    
    CFStringRef writing = (__bridge CFStringRef)@"東京都";
    
    CFStringRef furigana[kCTRubyPositionCount] = {
        (__bridge CFStringRef) @"とうきょうと", NULL, NULL, NULL
    };
    
    CTRubyAnnotationRef ruby = CTRubyAnnotationCreate(kCTRubyAlignmentAuto, kCTRubyOverhangAuto, 0.5, furigana);
    
    CFAttributedStringRef writingAttributedString = [self attributedString:writing ruby:ruby];
    
    // ここでsignal sigabrtと言われて止まります。
    textLbl.attributedText = (__bridge NSAttributedString *)(writingAttributedString);
    
    // [self attributedString:writing ruby:ruby]部
    - (CFAttributedStringRef)attributedString:(CFStringRef)string ruby:(CTRubyAnnotationRef)ruby
    {
        // Font style
        CTFontRef font = CTFontCreateWithName(CFSTR("Verdana"), 28, NULL);
    
        // Font color
        CGColorRef fontColor = [UIColor redColor].CGColor;
    
        // Paragraph
        CTTextAlignment alignment = kCTRightTextAlignment;
    
        CTParagraphStyleSetting settings[] = {
            {kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment}
        };
    
        CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0]));
    
        // Create an attributed string
        CFStringRef keys[] = { kCTFontAttributeName , kCTParagraphStyleAttributeName, kCTForegroundColorAttributeName, kCTRubyAnnotationAttributeName};
        CFTypeRef values[] = { font, paragraphStyle, fontColor, ruby};
    
        CFDictionaryRef attr = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values,
            sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
        CFAttributedStringRef attributes = CFAttributedStringCreate(NULL, string, attr);
        CFRelease(attr);
    
        return attributes;
    }
    
[/code]

他にUILabelにルビ付きテキストを設定するのに適した方法はありますか？


CC BY-SA 3.0
2015-08-28T02:45:18.573
14927
2022-08-13T00:03:50.513
2015-08-28T05:45:30.540
5519
11103
question
ios objective-c uilabel
UILabelにルビ付きのテキストを設定したい


Swift3です。  
殆どの処理は以下Qiitaの投稿を利用させて頂いています。一部をSwift3に書き換えています。

ルビを振る by @woxtu on @Qiita  
<http://qiita.com/woxtu/items/284369fd2654edac2248>

作成したNSAttributedStringをUILabelのattributedTextにセットするだけです。

[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
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2017-09-06T08:52:15.663
37756
2017-09-06T08:52:15.663
25244
14927
answer