How to use Core Text in SwiftUI

Viewed 626

I have a basic implementation of Core Text that prints Hello World in iOS, it works perfectly with UIKit.

import UIKit
import CoreText

class CTView: UIView {
    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        // Flip the coordinate system
        context.textMatrix = .identity
        context.translateBy(x: 0, y: bounds.size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        
        let path = CGMutablePath()
        path.addRect(bounds)
        
        let attrString = NSAttributedString(string: "Hello World")
        
        let framesetter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString)
        
        let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attrString.length), path, nil)
        
        CTFrameDraw(frame, context)
    }
}

I've tried to use this Core Text with SwiftUI instead of UIKit by applying the use of UIViewRepresentable:

import SwiftUI
import CoreText

struct CTView: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        return UIView()
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        
    }
}

But I couldn't figure out how to implement (or basically, override) the draw function, since we use structs instead of classes in SwiftUI.

In addition to that, how can we do the same thing for macOS?

1 Answers

Just wrap your previous CTView, as in

struct WrappedCTView: UIViewRepresentable {

    func makeUIView(context: Context) -> CTView {
        let view = CTView()       // << here !!
        view.isOpaque = false
        return view
    }
    
    func updateUIView(_ uiView: CTView, context: Context) {}
}
Related