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 并设定文本内容
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attString];
// 创建 NSLayoutManager 并关联 NSTextStorage
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
// 创建 NSTextContainer 并设定其属性
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);
}