Macos NSLayoutManager/NSTextContainer忽略比例因子

Macos NSLayoutManager/NSTextContainer忽略比例因子,macos,cocoa,nstextview,nslayoutmanager,nstextcontainer,Macos,Cocoa,Nstextview,Nslayoutmanager,Nstextcontainer,我正在尝试使用以下方法测量给定恒定宽度的NSAttributedString的高度: -(CGFloat)calculateHeightForAttributedString:(NSAttributedString*)attributedNotes { CGFloat scrollerWidth = [NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegac

我正在尝试使用以下方法测量给定恒定宽度的
NSAttributedString
的高度:

-(CGFloat)calculateHeightForAttributedString:(NSAttributedString*)attributedNotes {
    CGFloat scrollerWidth = [NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy];
    CGFloat width = self.tableView.frame.size.width - self.cellNotesWidthConstraint - scrollerWidth;
    // http://www.cocoabuilder.com/archive/cocoa/54083-height-of-string-with-fixed-width-and-given-font.html
    NSTextView *tv = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, width - 20, 1e7)];
    tv.font = [NSFont userFontOfSize:32];
    [tv.textStorage setAttributedString:attributedNotes];
    [self setScaleFactor:[self convertSliderValueToFontScale:self.fontScaleSlider] forTextView:tv];

    [tv.layoutManager glyphRangeForTextContainer:tv.textContainer];
    [tv.layoutManager ensureLayoutForTextContainer:tv.textContainer];

    return [tv.layoutManager usedRectForTextContainer:tv.textContainer].size.height + 10.0f; // add a little bit of a buffer
}
基本上,宽度是表视图的大小减去滚动条和用于显示其他信息的每个单元格的一小部分。只要文本比例(通过
convertSliderValueToFontScale:
)为1.0,此方法就可以正常工作。但是,如果我更改比例因子,则来自
usedRectForTextContainer
的结果是不正确的——就好像没有考虑比例因子一样

在NSTextView上的
setScaleFactor:forTextView:
中设置刻度,如下所示(标量是实际刻度量):

有没有办法解决这个问题


编辑:我有一个示例项目要在这里尝试:。奇怪的是,如果标度小于0,事情就会发生,有时它们会随机出现在4.XXX范围内……

答案很简单:将
NSTextView
添加为
NSClipView
的子视图,其框架与
NSTextView
相同

最终高度函数如下所示:

-(CGFloat)calculateHeightForAttributedString:(NSAttributedString*)attributedNotes {
    CGFloat width = self.textView.frame.size.width;
    // http://www.cocoabuilder.com/archive/cocoa/54083-height-of-string-with-fixed-width-and-given-font.html
    NSTextView *tv = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, width, 1e7)];
    tv.horizontallyResizable = NO;
    tv.font = [NSFont userFontOfSize:32];
    tv.alignment = NSTextAlignmentLeft;
    [tv.textStorage setAttributedString:attributedNotes];
    [self setScaleFactor:self.slider.floatValue forTextView:tv];

    // In order for usedRectForTextContainer: to be accurate with a scale, you MUST
    // set the NSTextView as a subview of an NSClipView!
    NSClipView *clipView = [[NSClipView alloc] initWithFrame:NSMakeRect(0, 0, width, 1e7)];
    [clipView addSubview:tv];

    [tv.layoutManager glyphRangeForTextContainer:tv.textContainer];
    [tv.layoutManager ensureLayoutForTextContainer:tv.textContainer];
    return [tv.layoutManager usedRectForTextContainer:tv.textContainer].size.height;
}

答案很简单:添加
NSTextView
作为
NSClipView
的子视图,其框架与
NSTextView
相同

最终高度函数如下所示:

-(CGFloat)calculateHeightForAttributedString:(NSAttributedString*)attributedNotes {
    CGFloat width = self.textView.frame.size.width;
    // http://www.cocoabuilder.com/archive/cocoa/54083-height-of-string-with-fixed-width-and-given-font.html
    NSTextView *tv = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, width, 1e7)];
    tv.horizontallyResizable = NO;
    tv.font = [NSFont userFontOfSize:32];
    tv.alignment = NSTextAlignmentLeft;
    [tv.textStorage setAttributedString:attributedNotes];
    [self setScaleFactor:self.slider.floatValue forTextView:tv];

    // In order for usedRectForTextContainer: to be accurate with a scale, you MUST
    // set the NSTextView as a subview of an NSClipView!
    NSClipView *clipView = [[NSClipView alloc] initWithFrame:NSMakeRect(0, 0, width, 1e7)];
    [clipView addSubview:tv];

    [tv.layoutManager glyphRangeForTextContainer:tv.textContainer];
    [tv.layoutManager ensureLayoutForTextContainer:tv.textContainer];
    return [tv.layoutManager usedRectForTextContainer:tv.textContainer].size.height;
}

在我看来,
scaleUnitSquareToSize
改变了点的大小,局部坐标中的点的数量保持不变。我可以想象NSLayoutManager/NSTextContainer对
scaleUnitSquareToSize
有所了解,因为随着文本的放大,文本包装会进行调整(假设您的NSScrollView已禁用水平滚动)。没有骰子。我这里有一个示例项目:。奇怪的是,有些值可以工作--但每次运行软件时它似乎都不同(尽管总是~4)。如果缩放小于0,它似乎也会起作用。感谢您迄今为止的建议。在我看来,
scaleUnitSquartoSize
会更改点的大小,局部坐标中的点的数量保持不变。考虑到文本应用程序会随着文本的放大而调整(假设您的NSScrollView禁用了水平滚动)。没有骰子。我这里有一个示例项目:。奇怪的是,有一些值可以工作--但每次运行软件时它似乎都不同(尽管它总是~4)。如果量表<0,它似乎也会起作用。感谢您迄今为止的建议。