for my app, few month ago, i've take the code from this site to use CTRubyAnnotation.
This code, with few changes to make work with swift 4, work perfectly.
from this work I've create a class in which I written a function to use that code.
this is the class in swift 4
import UIKit
extension String {
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
}
}
}
class Utility: NSObject {
class var sharedInstance: Utility {
struct Singleton {
static let instance = Utility()
}
return Singleton.instance
}
func furigana(String:String) -> NSMutableAttributedString {
let attributed =
String
.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: [Unmanaged<CFString>?] = [Unmanaged<CFString>.passRetained(ruby as CFString) as Unmanaged<CFString>, .none, .none, .none]
let annotation = CTRubyAnnotationCreate(CTRubyAlignment.auto, CTRubyOverhang.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 }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 1.5
paragraphStyle.lineSpacing = 12
attributed.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, (attributed.length)))
attributed.addAttributes([NSAttributedStringKey.font: UIFont(name: "HiraMinProN-W3", size: 14.0)!, NSAttributedStringKey.verticalGlyphForm: false,],range: NSMakeRange(0, (attributed.length)))
return attributed
}
}
I don't know why but this code don't work.
this is the class that use this function:
class ViewController: UIViewController {
@IBOutlet weak var furiganaLabel: UILabel!
override func viewDidLoad() {
furiganaLabel.attributedText = Utility.sharedInstance.furigana(String: "|優勝《ゆうしょう》の|懸《か》かった|試合《しあい》。")
}
}
and this is the result: Result With my function
But with the original code work perfectly: Using original code
Some one can help me and explain the reason?
Thank you very much
I've found an great solution
Swift 4.2
This solution is an update of preview answers and let you write Japanese sentences and using an pattern you can show the sentences with furigana.
In this solution you use 3 extensions to String
This extension lets you to create an NSAttributed string to give to your label
Great solution written in Japanese but it possible to download the example project
I have same issue.
Your code as Swift4 works correctly on iOS10. It does not function correctly on iOS11.
It seems that there was a change in NSAttributedString of UILabel on iOS 11.
I wrote a general program to draw vertical writing characters in CoreText before. In CoreText, NSAttributedString works on iOS11 as well. Although it is a provisional method, you can avoid this problem by using CoreText.
I written sample code. Since this draws characters directly to context, there is no need for UILabel, but draw with UILabel 's drawText for the moment.
And, Use it like below.
I added the CustomLabel class which adapted SimpleVerticalGlyphViewProtocol.
Please set the CustomLabel class as UILabel 's Custom Class on Storyboard.
Font size auto scale, and specify line number 0
Fixed font size, specify line number 4, baseline alignCenters, and last line truncated.
Font size auto scale, and specify line number 0 with Ruby
The above code works perfectly but there is one problem. Overriding the method
drawText(in rect: CGRect)
, it loses every benefit of managing of text that is done by UILabel. In fact, the text isn't cut when the text goes out of size of the label.this is the result of code:
CustomTableViewCell
GQAsianLabel
Utility class with furigana function