Swift中如何用CoreText替换UILabel?

How to use CoreText to replace UILabel in Swift?

目前我正在使用 UILabel 在屏幕上放置文本:

var label = UILabel()
view.addSubView(label)
label.backgroundColor = UIColor.whiteColor()
label.numberOfLines = 2
label.font = UIFont.systemFontOfSize(20, weight: UIFontWeightMedium)
label.frame = CGRectMake(0, 0, 100, 50)
label.text = "Hi, this is some text..."

Swift如何用CoreText替换上面的?

试试这个:

func drawText(context: CGContextRef, text: NSString, attributes: [String: AnyObject], x: CGFloat, y: CGFloat) -> CGSize {
    let font = attributes[NSFontAttributeName] as UIFont
    let attributedString = NSAttributedString(string: text, attributes: attributes)

    let textSize = text.sizeWithAttributes(attributes)

    // y: Add font.descender (its a negative value) to align the text at the baseline
    let textPath    = CGPathCreateWithRect(CGRect(x: x, y: y + font.descender, width: ceil(textSize.width), height: ceil(textSize.height)), nil)
    let frameSetter = CTFramesetterCreateWithAttributedString(attributedString)
    let frame       = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: attributedString.length), textPath, nil)

    CTFrameDraw(frame, context)

    return textSize
    }

然后这样调用:

var textAttributes: [String: AnyObject] = [
    NSForegroundColorAttributeName : UIColor(white: 1.0, alpha: 1.0).CGColor,
    NSFontAttributeName : UIFont.systemFontOfSize(17)
]

drawText(ctx, text: "Hello, World!", attributes: textAttributes, x: 50, y: 50)

希望这有效!

以下代码解决了我的问题:

override func drawRect(rect: CGRect) {
    super.drawRect(rect)

    let  context  = UIGraphicsGetCurrentContext()

    // Flip the coordinate system
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    let path = CGPathCreateMutable()
    CGPathAddRect(path, nil, self.bounds)

    let str = NSMutableAttributedString(string: "some text goes here...")

    // set font color
    str.addAttribute(kCTForegroundColorAttributeName as String, value:UIColor.blackColor() , range: NSMakeRange(0,str.length))
    // set font name & size
    let fontRef = UIFont.systemFontOfSize(20, weight: UIFontWeightMedium)
    str.addAttribute(kCTFontAttributeName as String, value: fontRef, range:NSMakeRange(0, str.length))

    let frameSetter = CTFramesetterCreateWithAttributedString(str)
    let ctFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0,str.length), path, nil)

    CTFrameDraw(ctFrame, context!)
}

已针对 swift 3.0 更新:

if let context  = UIGraphicsGetCurrentContext(){

            // Flip the coordinate system
            context.textMatrix = CGAffineTransform.identity;
            context.translateBy(x: 0, y: self.bounds.size.height);
            context.scaleBy(x: 1.0, y: -1.0);

            let path = CGMutablePath()
            path.addRect(self.bounds)

            let str = NSMutableAttributedString(string: "some text goes here...")

            // set font color
            str.addAttribute(kCTForegroundColorAttributeName as String, value:UIColor.black , range: NSMakeRange(0,str.length))
            // set font name & size
            let fontRef = UIFont.systemFont(ofSize: 20, weight: UIFontWeightMedium)
            str.addAttribute(kCTFontAttributeName as String, value: fontRef, range:NSMakeRange(0, str.length))

            let frameSetter = CTFramesetterCreateWithAttributedString(str)
            let ctFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0,str.length), path, nil)

            CTFrameDraw(ctFrame, context)
        }

Swift4.0 更新:

override func draw(_ rect: CGRect) {
     super.draw(rect)

    // context allows you to manipulate the drawing context (i'm setup to draw or bail out)
    guard let context: CGContext = UIGraphicsGetCurrentContext() else {
        return
    }

    // Flip the coordinate system
    context.textMatrix = CGAffineTransform.identity;
    context.translateBy(x: 0, y: self.bounds.size.height);
    context.scaleBy(x: 1.0, y: -1.0);

    let path = CGMutablePath()
    path.addRect(self.bounds)

    let str = NSMutableAttributedString(string: "00:00:00")

    // set font color
    str.addAttribute(NSAttributedStringKey(rawValue: kCTForegroundColorAttributeName as String), value:UIColor.purple , range: NSMakeRange(0,str.length))
    // set font name & size
    let fontRef = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.bold)
    str.addAttribute(NSAttributedStringKey(rawValue: kCTFontAttributeName as String), value: fontRef, range:NSMakeRange(0, str.length))

    let frameSetter = CTFramesetterCreateWithAttributedString(str)
    let ctFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0,str.length), path, nil)

    CTFrameDraw(ctFrame, context)       
}