Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

CoreText' CTRunDraw can't draw underline attribute in iOS18 with Xcode 16 beta

demo code :

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

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

     NSDictionary *attrs = @{NSFontAttributeName: [UIFont systemFontOfSize:20],
                             NSForegroundColorAttributeName: [UIColor blueColor],
                             NSUnderlineStyleAttributeName: @(NSUnderlineStyleThick),
                             };

     // Make an attributed string
     NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:@"Hello CoreText!" attributes:attrs];
    CFAttributedStringRef attributedStringRef = (__bridge CFAttributedStringRef)attributedString;

     // Simple CoreText with CTFrameDraw
     CTFramesetterRef framesetter =  CTFramesetterCreateWithAttributedString(attributedStringRef);
     CGPathRef path = CGPathCreateWithRect(self.bounds,NULL);
     CTFrameRef frame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0, 0),path,NULL);
     //CTFrameDraw(frame, context);

     // You can comment the line 'CTFrameDraw' and use the following lines
     // draw with CTLineDraw
     CFArrayRef lines = CTFrameGetLines(frame);
     CGPoint lineOrigins[CFArrayGetCount(lines)];
     CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins);
     for (int i = 0; i < CFArrayGetCount(lines); i++) {
         CTLineRef line = CFArrayGetValueAtIndex(lines, i);
         CGContextSetTextPosition(context,  lineOrigins[i].x, lineOrigins[i].y);
//         CTLineDraw(line, context);

         // You can comment the line 'CTLineDraw' and use the following lines
         // draw with CTRunDraw
         // use CTRunDraw will lost some attributes like NSUnderlineStyleAttributeName,
         // so you need draw it by yourself
         CFArrayRef runs = CTLineGetGlyphRuns(line);
         for (int j = 0; j < CFArrayGetCount(runs); j++) {
             CTRunRef run = CFArrayGetValueAtIndex(runs, j);
             CTRunDraw(run, context, CFRangeMake(0, 0));
         }
     }
}

this code will use CTRunDraw to draw the content , and the underline will draw and show normally in iOS17 & Xcode 15 , But when you build it with XCode16 & iOS18 beta . the underline will be missing .

Same issue on macOS 15 Sequoia. CTRunDraw does properly draw the underline on macOS 14 and below, or when using Xcode 15 or below.

Using Xcode 16 + macOS 15 CTRunDraw does not draw an underline.

the same problem!!!

CoreText' CTRunDraw can't draw underline attribute in iOS18 with Xcode 16 beta
 
 
Q