159

我正在尝试获取属性字符串的矩形,但 boundingRectWithSize 调用不尊重我传入的大小,并且返回一个具有单行高度而不是大高度的矩形(它是一个长字符串)。我已经通过在下面的代码中传递一个非常大的高度值和 0 来进行实验,但是返回的矩形总是相同的。

CGRect paragraphRect = [attributedText boundingRectWithSize:CGSizeMake(300,0.0)
  options:NSStringDrawingUsesDeviceMetrics
  context:nil];

这是坏了,还是我需要做其他事情才能让它返回一个包装文本的矩形?

4

23 回答 23

322

看起来您没有提供正确的选项。对于包装标签,至少提供:

CGRect paragraphRect =
  [attributedText boundingRectWithSize:CGSizeMake(300.f, CGFLOAT_MAX)
  options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
  context:nil];

注意:如果原始文本宽度在 300.f 以下,则不会换行,因此请确保绑定大小正确,否则仍然会得到错误的结果。

于 2013-03-14T01:48:29.773 回答
51

出于某种原因,boundingRectWithSize 总是返回错误的大小。我想出了一个解决办法。UItextView -sizeThatFits 有一种方法可以返回文本集的正确大小。因此,不要使用 boundingRectWithSize,而是创建一个带有随机框架的 UITextView,并使用相应的宽度和 CGFLOAT_MAX 高度调用它的 sizeThatFits。它返回具有适当高度的尺寸。

   UITextView *view=[[UITextView alloc] initWithFrame:CGRectMake(0, 0, width, 10)];   
   view.text=text;
   CGSize size=[view sizeThatFits:CGSizeMake(width, CGFLOAT_MAX)];
   height=size.height; 

如果你在while循环中计算大小,不要忘记将它添加到自动释放池中,因为会创建n个UITextView,如果我们不使用自动释放池,应用程序的运行时内存会增加。

于 2014-12-04T08:25:36.910 回答
32

Ed McManus 无疑提供了实现这一点的关键。我发现了一个不起作用的案例

UIFont *font = ...
UIColor *color = ...
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                     font, NSFontAttributeName,
                                     color, NSForegroundColorAttributeName,
                                     nil];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString: someString attributes:attributesDictionary];

[string appendAttributedString: [[NSAttributedString alloc] initWithString: anotherString];

CGRect rect = [string boundingRectWithSize:constraint options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil];

rect没有正确的高度。请注意,anotherString(附加到string)是在没有属性字典的情况下初始化的。这是anotherString的合法初始化程序,但boundingRectWithSize:在这种情况下没有给出准确的大小。

于 2013-06-14T21:09:36.863 回答
30

经过长时间的调查,我的最终决定:
- boundingRectWithSize函数只为不间断的字符序列返回正确的大小!如果字符串包含空格或其他内容(由 Apple "Some of the glyphs" 调用),则无法获得显示文本所需的实际矩形大小!
我用字母替换了字符串中的空格并立即得到了正确的结果。

苹果在这里说: https ://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrectwithsize

"此方法返回字符串中字形的实际边界。某些字形(例如空格)被允许与传入的尺寸指定的布局约束重叠,因此在某些情况下尺寸分量的宽度值返回的CGRect可以超过 size 参数的宽度值。”

所以有必要找到另一种方法来计算实际的矩形......


经过长时间的排查过程终于找到解决办法!!!我不确定它是否适用于与 相关的所有情况UITextView,但主要和重要的事情被发现了!

boundingRectWithSizeCTFramesetterSuggestFrameSizeWithConstraints当使用正确的矩形时,函数以及(和许多其他方法)将计算正确的大小和文本部分。例如 - UITextViewhas textView.bounds.size.width- 这个值不是系统在绘制文本时使用的实际矩形UITextView

我发现了非常有趣的参数并在代码中进行了简单的计算:

CGFloat padding = textView.textContainer.lineFragmentPadding;  
CGFloat  actualPageWidth = textView.bounds.size.width - padding * 2;

还有神奇的作品——我所有的文字现在都计算正确了!享受!

于 2014-09-19T19:31:26.537 回答
20

斯威夫特四版

let string = "A great test string."
let font = UIFont.systemFont(ofSize: 14)
let attributes: [NSAttributedStringKey: Any] = [.font: font]
let attributedString = NSAttributedString(string: string, attributes: attributes)
let largestSize = CGSize(width: bounds.width, height: .greatestFiniteMagnitude)

//Option one (best option)
let framesetter = CTFramesetterCreateWithAttributedString(attributedString)
let textSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRange(), nil, largestSize, nil)

//Option two
let textSize = (string as NSString).boundingRect(with: largestSize, options: [.usesLineFragmentOrigin , .usesFontLeading], attributes: attributes, context: nil).size

//Option three
let textSize = attributedString.boundingRect(with: largestSize, options: [.usesLineFragmentOrigin , .usesFontLeading], context: nil).size

使用 CTFramesetter 测量文本效果最好,因为它提供整数大小并很好地处理表情符号和其他 unicode 字符。

于 2017-07-04T04:17:33.470 回答
12

这些建议中的任何一个我都没有运气。我的字符串包含 unicode 要点,我怀疑它们在计算中引起了悲伤。我注意到 UITextView 处理绘图很好,所以我查看了它来利用它的计算。我做了以下操作,这可能不如 NSString 绘图方法最佳,但至少它是准确的。它也比初始化 UITextView 来调用-sizeThatFits:.

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(width, CGFLOAT_MAX)];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[layoutManager addTextContainer:textContainer];

NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:formattedString];
[textStorage addLayoutManager:layoutManager];

const CGFloat formattedStringHeight = ceilf([layoutManager usedRectForTextContainer:textContainer].size.height);
于 2015-09-28T06:31:44.097 回答
10

事实证明,如果您希望 boundingRectWithSize 实际工作,则 NSAttributedString 的每个部分都必须具有至少设置了 NSFontAttributeName 和 NSForegroundColorAttributeName 的字典集!

我在任何地方都没有看到记录。

于 2017-06-10T18:25:27.617 回答
9

如果您想通过截断尾部来获得边界框,这个问题可以帮助您。

CGFloat maxTitleWidth = 200;

NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = NSLineBreakByTruncatingTail;

NSDictionary *attributes = @{NSFontAttributeName : self.textLabel.font,
                             NSParagraphStyleAttributeName: paragraph};

CGRect box = [self.textLabel.text
              boundingRectWithSize:CGSizeMake(maxTitleWidth, CGFLOAT_MAX)
              options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
              attributes:attributes context:nil];
于 2014-07-06T00:22:02.803 回答
8

我发现首选解决方案不处理换行符。

我发现这种方法适用于所有情况:

UILabel* dummyLabel = [UILabel new];
[dummyLabel setFrame:CGRectMake(0, 0, desiredWidth, CGFLOAT_MAX)];
dummyLabel.numberOfLines = 0;
[dummyLabel setLineBreakMode:NSLineBreakByWordWrapping];
dummyLabel.attributedText = myString;
[dummyLabel sizeToFit];
CGSize requiredSize = dummyLabel.frame.size;
于 2015-11-13T16:32:19.697 回答
7

@warrenm 很抱歉,framesetter 方法对我不起作用。

我明白了。这个函数可以帮助我们确定给定 Width 的 iphone/Ipad SDK 中 NSAttributedString 的字符串范围所需的帧大小:

可用于 UITableView Cells 的动态高度

- (CGSize)frameSizeForAttributedString:(NSAttributedString *)attributedString
{
    CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
    CGFloat width = YOUR_FIXED_WIDTH;

    CFIndex offset = 0, length;
    CGFloat y = 0;
    do {
        length = CTTypesetterSuggestLineBreak(typesetter, offset, width);
        CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(offset, length));

        CGFloat ascent, descent, leading;
        CTLineGetTypographicBounds(line, &ascent, &descent, &leading);

        CFRelease(line);

        offset += length;
        y += ascent + descent + leading;
    } while (offset < [attributedString length]);

    CFRelease(typesetter);

    return CGSizeMake(width, ceil(y));
}

感谢 HADDAD ISSA >>> http://haddadissa.blogspot.in/2010/09/compute-needed-heigh-for-fixed-width-of.html

于 2014-03-27T11:17:47.643 回答
4

使用这些技术无法获得准确的尺寸时,我遇到了同样的问题,我已经改变了我的方法以使其发挥作用。

我有一个很长的属性字符串,我一直在尝试将其放入滚动视图中,以便它正确显示而不会被截断。为了使文本可靠地工作,我所做的是根本不将高度设置为约束,而是允许固有大小接管。现在文本正确显示而不会被截断,我不必计算高度。

我想如果我确实需要可靠地获取高度,我会创建一个隐藏的视图和这些约束,并在应用约束后获取框架的高度。

于 2013-10-10T15:14:06.817 回答
3

我玩游戏有点晚了 - 但我一直在尝试找出一种方法来找到适合属性字符串的边界框,从而像在 Finder 中编辑文件一样制作焦点环。当字符串末尾有空格或字符串中有多个空格时,我尝试的所有操作都失败了。boundingRectWithSize为此以及CTFramesetterCreateWithAttributedString.

NSLayoutManager到目前为止,在我发现的所有情况下,使用以下代码似乎都可以解决问题,并返回一个完美绑定字符串的矩形。奖励:如果您选择文本,则选择的边缘会直接到达返回的矩形的边界。下面的代码使用来自NSTextView.

NSLayoutManager* layout = [self layoutManager];
NSTextContainer* container = [self textContainer];

CGRect focusRingFrame = [layout boundingRectForGlyphRange:NSMakeRange(0, [[self textStorage] length]) inTextContainer:container];
于 2016-01-12T14:48:09.657 回答
3

这里的许多答案都很棒,David Rees 很好地总结了这些选项

但有时当有特殊字符或多个空格时,大小似乎总是错误的。

无效字符串的示例(对我而言):

"hello    .   .  world"

我发现将紧缩设置为NSAttributedString有助于1返回正确的大小。

像这样:

NSAttributedString(
    string: "some string",
    attributes: [
        .font: NSFont.preferredFont(forTextStyle: .body), 
        .kern: 1])
于 2021-02-20T19:17:05.057 回答
2
textView.textContainerInset = UIEdgeInsetsZero;
NSString *string = @"Some string";
NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:12.0f], NSForegroundColorAttributeName:[UIColor blackColor]};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:string attributes:attributes];
[textView setAttributedText:attributedString];
CGRect textViewFrame = [textView.attributedText boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.view.frame)-8.0f, 9999.0f) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil];
NSLog(@"%f", ceilf(textViewFrame.size.height));

完美适用于所有字体!

于 2014-04-02T15:17:10.647 回答
1

我遇到了同样的问题,但我认识到高度约束已正确设置。所以我做了以下事情:

-(CGSize)MaxHeighForTextInRow:(NSString *)RowText width:(float)UITextviewWidth {

    CGSize constrainedSize = CGSizeMake(UITextviewWidth, CGFLOAT_MAX);

    NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                          [UIFont fontWithName:@"HelveticaNeue" size:11.0], NSFontAttributeName,
                                          nil];

    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:RowText attributes:attributesDictionary];

    CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];

    if (requiredHeight.size.width > UITextviewWidth) {
        requiredHeight = CGRectMake(0, 0, UITextviewWidth, requiredHeight.size.height);
    }

    return requiredHeight.size;
}
于 2013-12-11T08:02:10.217 回答
1
    NSDictionary *stringAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont systemFontOfSize:18], NSFontAttributeName,
                                      [UIColor blackColor], NSForegroundColorAttributeName,
                                      nil];

    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:myLabel.text attributes:stringAttributes];
    myLabel.attributedText = attributedString; //this is the key!

    CGSize maximumLabelSize = CGSizeMake (screenRect.size.width - 40, CGFLOAT_MAX);

    CGRect newRect = [myLabel.text boundingRectWithSize:maximumLabelSize
                                                       options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                    attributes:stringAttributes context:nil];

    self.myLabelHeightConstraint.constant = ceilf(newRect.size.height);

我尝试了此页面上的所有内容,但仍然有一个 UILabel 格式不正确的案例。实际上在标签上设置属性文本最终解决了这个问题。

于 2014-05-21T15:43:40.230 回答
1

我注意到的一件事是,将从中返回的矩形(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context的宽度比我传入的宽度要大。发生这种情况时,我的字符串将被截断。我是这样解决的:

NSString *aLongString = ...
NSInteger width = //some width;            
UIFont *font = //your font;
CGRect rect = [aLongString boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
                                        options:(NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin)
                                     attributes:@{ NSFontAttributeName : font,
                                                   NSForegroundColorAttributeName : [UIColor whiteColor]}
                                        context:nil];

if(rect.size.width > width)
{
    return rect.size.height + font.lineHeight;
}
return rect.size.height;

有关更多上下文;我有多行文本,我试图找到合适的高度来显示它。boundRectWithSize 有时返回的宽度大于我指定的宽度,因此当我使用过去的宽度和计算出的高度来显示我的文本时,它会截断。从 boundingRectWithSize 使用错误宽度的测试来看,它会使高度缩短的量是 1 行。所以我会检查宽度是否更大,如果是,则添加字体的 lineHeight 以提供足够的空间以避免截断。

于 2015-03-06T08:08:29.080 回答
0
    NSAttributedString *attributedText =[[[NSAttributedString alloc]
                                          initWithString:joyMeComment.content
                                          attributes:@{ NSFontAttributeName: [UIFont systemFontOfSize:TextFont]}] autorelease];

    CGRect paragraphRect =
    [attributedText boundingRectWithSize:CGSizeMake(kWith, CGFLOAT_MAX)
                                 options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                 context:nil];
    contentSize = paragraphRect.size;

    contentSize.size.height+=10;
    label.frame=contentSize;

如果标签的框架不加 10,此方法将永远无效!希望这可以帮到你!祝你好运。

于 2013-11-29T09:33:04.463 回答
0

我想补充一下我的想法,因为我遇到了完全相同的问题。

我正在使用UITextView它,因为它具有更好的文本对齐方式(justify,当时在 中不可用UILabel),但为了“模拟”非交互式非滚动UILabel,我将完全关闭滚动、弹跳和用户交互.

当然,问题是文本是动态的,虽然宽度是固定的,但每次我设置新的文本值时都应该重新计算高度。

boundingRectWithSize据我所见,对我来说根本不起作用,UITextView在顶部添加了一些边距,这boundingRectWithSize不会计入计数,因此,从中检索到的高度boundingRectWithSize小于应有的高度。

由于文本不会快速更新,它只是用于一些可能最多每 2-3 秒更新一次的信息,我决定采用以下方法:

/* This f is nested in a custom UIView-inherited class that is built using xib file */
-(void) setTextAndAutoSize:(NSString*)text inTextView:(UITextView*)tv
{
    CGFloat msgWidth = tv.frame.size.width; // get target's width

    // Make "test" UITextView to calculate correct size
    UITextView *temp = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, msgWidth, 300)]; // we set some height, really doesn't matter, just put some value like this one.
    // Set all font and text related parameters to be exact as the ones in targeted text view
    [temp setFont:tv.font];
    [temp setTextAlignment:tv.textAlignment];
    [temp setTextColor:tv.textColor];
    [temp setText:text];

    // Ask for size that fits :P
    CGSize tv_size = [temp sizeThatFits:CGSizeMake(msgWidth, 300)];

    // kill this "test" UITextView, it's purpose is over
    [temp release];
    temp = nil;

    // apply calculated size. if calcualted width differs, I choose to ignore it anyway and use only height because I want to have width absolutely fixed to designed value
    tv.frame = CGRectMake(tv.frame.origin.x, tv.frame.origin.y, msgWidth, tv_size.height );
}

*以上代码不是直接从我的源代码中复制的,我必须对其进行调整/从本文不需要的一堆其他东西中清除它。不要把它当作复制粘贴和工作代码。

明显的缺点是每次调用都有分配和释放。

但是,优点是您避免依赖于 boundingRectWithSize 如何绘制文本并计算它的大小和文本绘制的实现之间的兼容性UITextView(或者UILabel您也可以使用替换UITextViewUILabel)。通过这种方式可以避免 Apple 可能存在的任何“错误”。

PS看起来你不应该需要这个“临时”UITextView并且可以sizeThatFits直接从目标询问,但这对我不起作用。虽然逻辑会说它应该工作并且UITextView不需要临时分配/释放,但它没有。但是这个解决方案对于我要设置的任何文本都完美无缺。

于 2014-02-15T03:28:12.180 回答
0
Add Following methods in ur code for getting correct size of attribute string 
1.
    - (CGFloat)findHeightForText:(NSAttributedString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font
 {
    UITextView *textView = [[UITextView alloc] init];
    [textView setAttributedText:text];
    [textView setFont:font];
    CGSize size = [textView sizeThatFits:CGSizeMake(widthValue, FLT_MAX)];
    return size.height;

}

2. Call on heightForRowAtIndexPath method
     int h = [self findHeightForText:attrString havingWidth:yourScreenWidth andFont:urFont];
于 2015-12-19T06:30:12.580 回答
0

好的,所以我花了很多时间调试这个。我发现我的boundingRectWithSize允许显示文本定义的最大文本高度UITextView低于框架大小。

在我的情况下,框架最多为 140pt,但 UITextView 最多允许文本 131pt。

我必须手动计算并硬编码“真实”最大高度。

这是我的解决方案:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSString *proposedText = [textView.text stringByReplacingCharactersInRange:range withString:text];
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:proposedText];
    CGRect boundingRect;
    CGFloat maxFontSize = 100;
    CGFloat minFontSize = 30;
    CGFloat fontSize = maxFontSize + 1;
    BOOL fit;
    NSLog(@"Trying text: \"%@\"", proposedText);
    do {
        fontSize -= 1;
        //XXX Seems like trailing whitespaces count for 0. find a workaround
        [attributedText addAttribute:NSFontAttributeName value:[textView.font fontWithSize:fontSize] range:NSMakeRange(0, attributedText.length)];
        CGFloat padding = textView.textContainer.lineFragmentPadding;
        CGSize boundingSize = CGSizeMake(textView.frame.size.width - padding * 2, CGFLOAT_MAX);
        boundingRect = [attributedText boundingRectWithSize:boundingSize options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading context:nil];
        NSLog(@"bounding rect for font %f is %@; (max is %f %f). Padding: %f", fontSize, NSStringFromCGRect(boundingRect), textView.frame.size.width, 148.0, padding);
        fit =  boundingRect.size.height <= 131;
    } while (!fit && fontSize > minFontSize);
    if (fit) {
        self.textView.font = [self.textView.font fontWithSize:fontSize];
        NSLog(@"Fit!");
    } else {
        NSLog(@"No fit");
    }
    return fit;
}
于 2017-11-29T03:44:01.380 回答
0

遇到完全相同的问题。

对我来说,这个问题是由TTTAttributedLabel解决的

+ (CGSize)sizeThatFitsAttributedString:(NSAttributedString *)attributedString
                       withConstraints:(CGSize)size
                limitedToNumberOfLines:(NSUInteger)numberOfLines

方法,因为它提供了准确的结果。

于 2020-08-10T09:17:49.493 回答
0

我在计算NSTextField. 我尝试的任何方法总是返回太小的值。
对我来说,问题原来是,出于某种原因,NSTextField' 的attributedStringValue属性从未包含我通过 Interface Builder 设置的任何属性。如果我没有以编程方式设置属性字符串,它实际上根本不包含任何属性。连字体都没有。这就是为什么所有的高度计算都搞砸了。

为了让它工作,我创建了Category一个NSTextField自定义函数来获取正确的属性字符串。

这是它的实现文件Category

//
// --------------------------------------------------------------------------
// NSTextField+Additions.m
// Created for Mac Mouse Fix (https://github.com/noah-nuebling/mac-mouse-fix)
// Created by Noah Nuebling in 2021
// Licensed under MIT
// --------------------------------------------------------------------------
//

#import "NSTextField+Additions.h"

@implementation NSTextField (Additions)

// Copy paste template for adding attributes to an attributed string. Contains all possible attributes

//    [str addAttributes:@{
//        NSFontAttributeName:                NSNull.null,
//        NSParagraphStyleAttributeName:      NSNull.null,
//        NSForegroundColorAttributeName:     NSNull.null,
//        NSBackgroundColorAttributeName:     NSNull.null,
//        NSLigatureAttributeName:            NSNull.null,
//        NSKernAttributeName:                NSNull.null,
//        NSStrikethroughStyleAttributeName:  NSNull.null,
//        NSUnderlineStyleAttributeName:      NSNull.null,
//        NSStrokeColorAttributeName:         NSNull.null,
//        NSStrokeWidthAttributeName:         NSNull.null,
//        NSShadowAttributeName:              NSNull.null,
//        NSTextEffectAttributeName:          NSNull.null,
//        NSAttachmentAttributeName:          NSNull.null,
//        NSLinkAttributeName:                NSNull.null,
//        NSBaselineOffsetAttributeName:      NSNull.null,
//        NSUnderlineColorAttributeName:      NSNull.null,
//        NSStrikethroughColorAttributeName:  NSNull.null,
//        NSObliquenessAttributeName:         NSNull.null,
//        NSExpansionAttributeName:           NSNull.null,
//        NSWritingDirectionAttributeName:    NSNull.null,
//        NSVerticalGlyphFormAttributeName:   NSNull.null,
//    } range:NSMakeRange(0, str.length)];

/// In my testing NSTextField.attributedStringValue actually returned a string without _any_ attributes. Not even a font or anything.
/// This lead to issues when trying to calculate the fitting height for a certain width of the NSTextField.
/// This function takes some of the properties of the NSTextField and returns an NSAttributed string based on those.
/// I'm not sure this is perfect, but the returned attributed string describes the way that the text of the NSTextField is rendered close enough to be usable for my height calculations
- (NSAttributedString *)effectiveAttributedStringValue {
    
    NSMutableAttributedString *str = self.attributedStringValue.mutableCopy;

    // Create paragraph style from NSTextField properties
    
    // Not sure if we're setting these properties correctly, and there could be more properties we should be setting
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.alignment = self.alignment;
    paragraphStyle.baseWritingDirection = self.baseWritingDirection;
    paragraphStyle.lineBreakMode = self.lineBreakMode;
    paragraphStyle.allowsDefaultTighteningForTruncation = self.allowsDefaultTighteningForTruncation;
    if (@available(macOS 10.15, *)) paragraphStyle.lineBreakStrategy = self.lineBreakStrategy;
    
    // Add attributes to AttributedString based on NSTextField properties
     
    [str addAttributes:@{
        NSFontAttributeName:                self.font,
        NSParagraphStyleAttributeName:      paragraphStyle,
        NSForegroundColorAttributeName:     self.textColor,
        NSBackgroundColorAttributeName:     self.backgroundColor,
//        NSLigatureAttributeName:            NSNull.null,
//        NSKernAttributeName:                NSNull.null,
//        NSStrikethroughStyleAttributeName:  NSNull.null,
//        NSUnderlineStyleAttributeName:      NSNull.null,
//        NSStrokeColorAttributeName:         NSNull.null,
//        NSStrokeWidthAttributeName:         NSNull.null,
//        NSShadowAttributeName:              NSNull.null, //self.shadow,
//        NSTextEffectAttributeName:          NSNull.null,
//        NSAttachmentAttributeName:          NSNull.null,
//        NSLinkAttributeName:                NSNull.null,
//        NSBaselineOffsetAttributeName:      NSNull.null, //self.baselineOffsetFromBottom,
//        NSUnderlineColorAttributeName:      NSNull.null,
//        NSStrikethroughColorAttributeName:  NSNull.null,
//        NSObliquenessAttributeName:         NSNull.null,
//        NSExpansionAttributeName:           NSNull.null,
//        NSWritingDirectionAttributeName:    NSNull.null, //self.baseWritingDirection,
//        NSVerticalGlyphFormAttributeName:   NSNull.null,
    } range:NSMakeRange(0, str.length)];
    
    // return NSAttributedString
    
    return str;
    
}

@end


随机旁注

  • UILabel在这个线程中读到的一些关于人们的问题听起来很像他们可能相关。
  • 我最终决定使用NSTextViewover,NSTextField因为它获取属性字符串的方法是开箱即用的,并且NSTextField用于可点击链接的方法也完全拙劣。我的印象NSTextField是,除了最基本的用例之外,您应该避免的只是一个错误的混乱。
于 2021-03-20T14:29:48.807 回答