IOS 18 uses TextKit to calculate the height of attributed strings, but the calculation is inaccurate.

In iOS 18, using TextKit to calculate the height of attributed strings is inaccurate. The same method produces correct results in systems below iOS 18.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 40, 100, 0)];
    textView.editable = NO;
    textView.scrollEnabled = NO;
    textView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0);
    textView.textContainer.lineFragmentPadding = 0;
    textView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:textView];
    
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"陈家坝好吃的撒海程邦达不差大撒把传达是吧才打卡吃吧金卡多措并举哈不好吃大杯茶十八次是吧"];
    
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineSpacing = 4;
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attributedString.length)];
    
    [attributedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:NSMakeRange(0, attributedString.length)];
    
    [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, attributedString.length)];
    
    
    textView.attributedText = attributedString;
    
    CGFloat height = [self test:attributedString];
    
    textView.frame = CGRectMake(20, 40, 100, height);
    
}

- (CGFloat)test:(NSAttributedString *)attString {

    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attString];

    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    [textStorage addLayoutManager:layoutManager];

    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(100, CGFLOAT_MAX)];
    textContainer.lineFragmentPadding = 0;

    [layoutManager addTextContainer:textContainer];

    [layoutManager ensureLayoutForTextContainer:textContainer];
    
    CGFloat height = [layoutManager usedRectForTextContainer:textContainer].size.height;

    return ceil(height);
}

IOS 18 uses TextKit to calculate the height of attributed strings, but the calculation is inaccurate.
 
 
Q