iOS关于UITextView计算文本高度不准确的坑

问题: 字段由后端控制,里面出现换行的时候 \r\n是成对出现的 , 转义字符并未纳入字符串的计算范围 。。。 所以导致显示不全的bug

解决方案一:

由于这个方法计算字符串的大小的通过取得字符串的size来计算, 如果你计算的字符串中包含\r\n 这样的字符,也只会把它当成字符来计算。但是在显示的时候就是\n是转义字符,那么显示的计算的高度就不一样了,所以可以采用:计算的高度 = boundingRectWithSize计算出来的高度 + \r\n转义字符出现的个数 * 单行文本的高度。


///MARK:- 查询字串出现的次数 方法二
- (NSInteger)searchSubStringCountWithSubString:(NSString *)subStr
{
    NSUInteger count = 0, length = [subStr length];
    NSRange range = NSMakeRange(0, length);
    while(range.location != NSNotFound){
        range = [self rangeOfString: subStr options:0 range:range];
        if(range.location != NSNotFound){
            range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
            count++;
        }
    }
    return count;
}


解决方案二:

采用UILabel来展示文本就没有这个坑,主要看自己选择,毕竟有些特性只有UITextView才有的


@implementation NSString (Extension)

///MARK:- 查询字串出现的次数 方法一
- (NSInteger)countOccurencesOfString:(NSString*)searchString {
    NSInteger strCount = [self length] - [[self stringByReplacingOccurrencesOfString:searchString withString:@""] length];
    return strCount / [searchString length];
}

///MARK:- 查询字串出现的次数 方法二
- (NSInteger)searchSubStringCountWithSubString:(NSString *)subStr
{
    NSUInteger count = 0, length = [subStr length];
    NSRange range = NSMakeRange(0, length);
    while(range.location != NSNotFound){
        range = [self rangeOfString: subStr options:0 range:range];
        if(range.location != NSNotFound){
            range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
            count++;
        }
    }
    return count;
}


//计算单行文本宽度和高度,返回值与`UIFont.lineHeight`一致  [手动滑稽]方块字
- (CGSize)singleLineSizeWithText:(UIFont *)font{
    return [self sizeWithAttributes:@{NSFontAttributeName:font}];
}
@end

项目中展示控件使用的是UITextView 文本中包含\r\n来换行 同一个PHP后端这种既定的规则应该不会经常变。
所以:

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineBreakMode:NSLineBreakByCharWrapping];
    paragraphStyle.lineSpacing = 5;// 字体的行间距
    paragraphStyle.alignment = NSTextAlignmentLeft;
    NSDictionary *attributes = @{
                                 NSForegroundColorAttributeName : [UIColor whiteColor],
                                 NSParagraphStyleAttributeName : paragraphStyle,
                                 NSFontAttributeName : KFontSize(13)
                                 };
    //出现`\r` `\n` 关于计算高度不准确的问题 https://www.jianshu.com/p/c615a76dace2
    CGFloat textX = 35;
    CGFloat textW = KWIDTH - textX*2;
    NSString *realText = shareModel.tips ;
    NSInteger warpRowCount = [realText searchSubStringCountOccurencesOfString:@"\r\n"];
    CGFloat singleLineHeight = [@"哈哈哈哈哈哈哈哈哈" singleLineSizeWithText:KFontSize(13)].height + 5;
    CGFloat addHeight = warpRowCount *singleLineHeight;
    
    CGFloat textH = [realText boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:
                     NSStringDrawingUsesLineFragmentOrigin |
                     NSStringDrawingUsesFontLeading
                                               attributes: attributes context:nil].size.height + 0.5 + addHeight;
    self.textView.frame = CGRectMake(textX, 0, textW , textH);
    NSMutableAttributedString * attributeStr = [[NSMutableAttributedString alloc] initWithString: realText  attributes:attributes];
    self.textView.attributedText = attributeStr;

经过这么一番折腾之后,文本正常显示了 🤬

终极解决方案

2020年6月24日 其实根本不用这么麻烦,系统自适应方法即可计算准确,评论区已给出答案

参考博客:

boundingRectWithSize计算文字高度不准问题
使用boundingRectWithSize计算内容高度的坑

posted @   CoderWGB  阅读(3454)  评论(2编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示