标签: nslayoutmanager

Swift协议:方法不会覆盖其超类中的任何方法

由于Xcode 6仍然有很多Swift漏洞,我不确定它是一个还是我遗漏了一些东西.我的类采用协议NSLayoutManagerDelegate.但似乎不可能覆盖我需要的方法.我做文件描述:

override func layoutManager(_ aLayoutManager: NSLayoutManager!,
        didCompleteLayoutForTextContainer aTextContainer: NSTextContainer!,
        atEnd flag: Bool) {

    }
Run Code Online (Sandbox Code Playgroud)

但是我在这里得到错误:方法不会覆盖其超类中的任何方法.我该怎么办?

cocoa nslayoutmanager swift

43
推荐指数
1
解决办法
6万
查看次数

行间距如何在Core Text中工作?(为什么它与NSLayoutManager不同?)

我正在尝试使用Core Text函数绘制文本,其行间距尽可能接近使用NSTextView时的行间距.

以此字体为例:

NSFont *font = [NSFont fontWithName:@"Times New Roman" size:96.0];
Run Code Online (Sandbox Code Playgroud)

如果我在NSTextView中使用它,这个字体的行高是111.0.

NSLayoutManager *lm = [[NSLayoutManager alloc] init];
NSLog(@"%f", [lm defaultLineHeightForFont:font]); // this is 111.0
Run Code Online (Sandbox Code Playgroud)

现在,如果我使用Core Text做同样的事情,结果是110.4(假设您可以通过添加上升,下降和前导来计算线高).

CTFontRef cFont = CTFontCreateWithName(CFSTR("Times New Roman"), 96.0, NULL);
NSLog(@"%f", CTFontGetDescent(cFont) + CTFontGetAscent(cFont) + 
             CTFontGetLeading(cFont)); // this is 110.390625
Run Code Online (Sandbox Code Playgroud)

这非常接近111.0,但对于某些字体,差异要大得多.例如,对于Helvetica,NSLayoutManager给出115.0而CTFont上升+下降+领先= 96.0.很明显,对于Helvetica,我无法使用上升+下降+导致计算线之间的间距.

所以我想我会使用CTFrame和CTFramesetter来布局几行并从中获取行间距.但这也给出了不同的价值观.

CTFontRef cFont = CTFontCreateWithName(CFSTR("Times New Roman"), 96.0, NULL);
NSDictionary *attrs = [NSDictionary dictionaryWithObject:(id)cFont forKey:(id)kCTFontAttributeName];
NSAttributedString *threeLines = [[NSAttributedString alloc] initWithString:@"abcdefg\nabcdefg\nabcdefg" attributes:attrs];

CTFramesetterRef threeLineFramesetter =  CTFramesetterCreateWithAttributedString((CFAttributedStringRef)threeLines);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0.0, …
Run Code Online (Sandbox Code Playgroud)

macos objective-c nslayoutmanager nstextview core-text

26
推荐指数
1
解决办法
1万
查看次数

使用TextKit在UITextView中动画UIImage

我有一个UIImage包含多个图像帧和一个从动画GIF文件切片的持续时间.如果我将图像加载到UIWebView其中将按预期动画,但我想使用UITextView替代.显而易见的选择是使用带有自定义NSLayoutManger和许多自定义NSAttributedString属性的TextKit 来实现各种绘图效果.我有一个单一的UITextView,我想给一个NSAttributedString包含NSTextAttachments的所有图像我需要内联显示.它工作得很好,除了当我加载其中一个动画时UIImages,它们没有动画通过它们的帧.有关如何实现这一点的任何想法?我想出了一个理论选择:

  1. 对于每个动画图像,添加自定义属性
  2. 当布局管理器去绘制背景时,迭代此属性以定位附件的位置.
  3. 回调到文本视图以UIImageView使用动画图像创建s,添加为子视图并调用startAnimating

我还没有试过这个,但它相当hacky.我想知道是否有更好的选择.

总结:我想一个动画UIImageUITextView通过NSTextAttachment内部NSAttributedString而不需要额外的UIImageView对象.你可以忽略这个以前用a做的事实UIWebView.UIImage具有用于设置动画帧的属性(images,duration),我目前已配置.如果我将它分配给UIImageView它动画,如果我将其设置为a NSTextAttachment,则不动画.

我将不胜感激任何反馈.谢谢!

nslayoutmanager uitextview ios textkit

16
推荐指数
1
解决办法
1334
查看次数

使用NSLayoutManager计算每个字形的帧

在这个帖子中,Core Text计算iOS中的字母框架,他们能够使用Core Text非常精确地计算每个字形的框架.最终的rects完美地拥抱了实际绘制的字形.

使用NSLayoutManager boundingRectForGlyphRange:inTextContainer:似乎不会返回精确的字形边界框:

使用boundingRectForGlyphRange:inTextContainer的字形框架

返回的rects并没有完全包含更复杂的字体(Zapfino示例):

使用boundingRectForGlyphRange:inTextContainer的Zapfino f字形

有没有人知道如何复制上述讨论的结果而不进入iOS 7专用应用程序下的核心文本?

谢谢.

iphone glyph nslayoutmanager ipad ios7

14
推荐指数
1
解决办法
2107
查看次数

使用NSLayoutManager创建动画文本效果?

WWDC 2013的会话220(高级文本布局和带有文本工具包的效果)中,他们明确地说NSLayoutManager可以与创建高级文本动画一起使用NSTextStorageNSTextContainer创建高级文本动画.他们没怎么说.

我想使用NSLayoutManager/ NSTextStorage/ NSTextContainer来创建自定义文本动画.简单地说,我想为各个字形的大小和位置设置动画,并淡化和解开特定的字形.

似乎没有专门的方法和动画文档,NSLayoutManager我发现的唯一教程就在这里.然而,它展示了如何破解NSLayoutManager动画,而不是如何以它应该使用的方式使用它们(它们CATextLayer为每个单独的字形创建!).

有人能指出我正确的方向吗?我知道如何使用NSLayoutManager/ NSTextStorage/ NSTextContainer来呈现静态文本.一些演示,显示动画文本的原理NSLayoutManager将是完美的.为了让我开始,我可以自己弄清楚细节.

animation nslayoutmanager uilabel ios textkit

14
推荐指数
1
解决办法
870
查看次数

从UITextView和NSLayoutManager获取行信息

为了支持该UIAccessibilityReadingContent协议,我需要我的UITextView来回答有关其行的问题.这些是我需要实现的协议的方法:

  • accessibilityLineNumberForPoint: < - 提供坐标,返回行号
  • accessibilityContentForLineNumber: < - 返回给定行的文本
  • accessibilityFrameForLineNumber: < - 给定行号,返回其帧
  • accessibilityPageContent< - 整个文本内容.我有.:)

我认为NSLayoutManager可以帮助我,但我对它没有经验.我已经想到了一些(我认为),但仍然需要一些帮助.

Apple有一些示例代码(此处)可以获取文本视图中的行数:

NSLayoutManager *layoutManager = [textView layoutManager];
unsigned numberOfLines, index, numberOfGlyphs =
        [layoutManager numberOfGlyphs];
NSRange lineRange;
for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){
    (void) [layoutManager lineFragmentRectForGlyphAtIndex:index
            effectiveRange:&lineRange];
    index = NSMaxRange(lineRange);
}
Run Code Online (Sandbox Code Playgroud)

我用lineRange上面的数字来计算,我可以使用这个方法计算行数NSLayoutManager:

- (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container
Run Code Online (Sandbox Code Playgroud)

鉴于lineRanges我应该能够计算一个点的行号(通过找到lineRange包含字形索引的行号):

- (NSUInteger)glyphIndexForPoint:(CGPoint)point inTextContainer:(NSTextContainer *)container fractionOfDistanceThroughGlyph:(CGFloat *)partialFraction
Run Code Online (Sandbox Code Playgroud)

剩下的是,如果给出行号,我如何得到一行(作为一个NSString)的内容?

objective-c nslayoutmanager ios voiceover textkit

12
推荐指数
1
解决办法
2538
查看次数

斯威夫特:点击UILabel文本的一部分

我有一个问题,"boundingRectForGlyphRange"总是返回CGRect.zero"0.0,0.0,0.0,0.0"."boundingRectForGlyphRange"无效.例如,我正在编写触摸UILabel功能的部分文本.我的文字的第一部分是"任何文字",第二部分是"阅读更多".我希望点击识别器仅在我触摸"READ MORE"时才能工作.如果我触摸UILabel上的任何一点,"CGRectContainsPoint"总是返回true,然后调用该动作

这是我的代码:

override func viewDidLoad() {
        super.viewDidLoad()

        // The full string

        let firstPart:NSMutableAttributedString = NSMutableAttributedString(string: "Lorem ipsum dolor set amit ", attributes: [NSFontAttributeName: UIFont.systemFontOfSize(13)])
        firstPart.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(),
            range: NSRange(location: 0, length: firstPart.length))
        info.appendAttributedString(firstPart)

        // The "Read More" string that should be touchable
        let secondPart:NSMutableAttributedString = NSMutableAttributedString(string: "READ MORE", attributes: [NSFontAttributeName: UIFont.systemFontOfSize(14)])
        secondPart.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(),
            range: NSRange(location: 0, length: secondPart.length))
        info.appendAttributedString(secondPart)

        lblTest.attributedText = info

        // Store range of chars we want to detect touches for
        moreStringRange = NSMakeRange(firstPart.length, secondPart.length)
        print("moreStringRange\(moreStringRange)") …
Run Code Online (Sandbox Code Playgroud)

nslayoutmanager nsattributedstring uilabel ios swift

11
推荐指数
7
解决办法
2万
查看次数

在单元格中编辑UITextView时,iOS 7中的UITableView无法滚动到正确的位置

我有一个静态单元格的表视图.一个单元格包含a UITextView并且heightForRowAtIndexPath:是动态计算的,因此单元格总是足够高以容纳文本(该部分在iOS 7下进行了一些工作,实际上,因为它不再可能只是简单地询问textView contentSize).

当我在文本视图中点击开始编辑时,键盘动画到位,tableView上的contentInsets会自动调整以解决此问题(即,iPhone纵向方向的216px底部插入),光标/插入符号变为可见,然后表格视图滚动到另一个位置.它最终看起来像一个反弹.

以下是模拟器中的视频:https://www.dropbox.com/s/htdbb0t7985u6n4/textview-bounce.mov

请注意,插入符号位于键盘上方.我一直在记录表视图contentOffset,我可以看到它滚动到一个很好的值,然后突然"转身"并向后滚动.

奇怪的是,如果我在模拟器中打开慢动画,问题就会消失; 在contentOffset逆转不会发生的事情和工作,我希望(即iOS 6的行为).

以下是动画速度较慢的视频:https://www.dropbox.com/s/nhn7vspx86t4exb/textview-nobounce.mov

实施说明:

  • 文本视图为粉红色,并具有AutoLayout约束,使其固定在距离0处的单元格(左侧除外,即10pts)
  • 我正在使用boundingRectWithSize:计算表视图高度,调整lineFragmentPadding和任何顶部/底部插入.似乎工作.
  • 我已将textView设置为不可滚动,但在scrollEnabled== YES 时没有注意到任何不同
  • 这是一个表视图控制器,automaticallyAdjustsScrollViewInsets== YES

nslayoutmanager uitableview uitextview ios ios7

10
推荐指数
1
解决办法
3546
查看次数

在AppKit中测量文本宽度的性能

在AppKit中有没有办法快速测量大量NSString对象(比如一百万)的宽度?我尝试了3种不同的方法:

  • [NSString sizeWithAttributes:]
  • [NSAttributedString size]
  • NSLayoutManager(获取文本宽度而不是高度)

    以下是一些性能指标

    Count\Mechanism    sizeWithAttributes    NSAttributedString    NSLayoutManager
    1000               0.057                 0.031                 0.007
    10000              0.329                 0.325                 0.064
    100000             3.06                  3.14                  0.689
    1000000            29.5                  31.3                  7.06



    NSLayoutManager显然是要走的路,但问题在于

  • 由于创建了重量级的NSTextStorage对象,因此内存占用空间很大(根据分析器而超过1GB).
  • 创作时间长.所有花费的时间都是在创建上述字符串的过程中,这本身就是一个交易破坏者.(随后测量NSTextStorage对象,其中创建和布置的字形只需要大约0.0002秒).
  • 对于我想要做的事情,7秒仍然太慢.有更快的方法吗?在大约一秒钟内测量一百万个字符串?

    如果你想玩,是github项目.

  • cocoa objective-c nslayoutmanager nsattributedstring nstextstorage

    10
    推荐指数
    1
    解决办法
    763
    查看次数

    将文本视图的属性字符串细分为(首选)部分

    我正在尝试实现一个非常简单的文本编辑器,该文本编辑器应可同时NSTextView在macOS和UITextViewiOS上使用。该文本编辑器有一个工具栏按钮“分符”,每次单击它都会在当前光标位置插入一个新节。一节应为:

    1. 在视觉上可识别为一个部分(通过在两个后续部分之间添加视觉分隔符,并可能添加一些垂直空白),

    2. 参考。用户应该能够在编辑器中看到所有部分的列表,并且通过单击该列表中的项目,文本视图应立即滚动到该部分的开头。

    另一个问题,我问怎么解决的第一个问题,不幸的是,我还没有发现在这部分的答案,但(即使一个解决方案,仅在MacOS作品)。

    但是,这个问题集中在第二个方面:
    如何在我的文本视图中维护所有部分的列表,其中每个部分都能准确地引用相关文本?

    此任务的复杂性在于用户可以随时复制和粘贴或简单地编辑文本的任何部分。因此,我无法保留简单的段落编号数组或类似的内容。

    文本视图中几个部分的屏幕截图


    我尝试过的事情以及为什么这看起来是如此艰巨的任务:

    1. 我曾经有一个想法是继承NSTextStorage并使用可变属性字符串数组作为其内部存储。然后,我将使用的特殊子类NSTextAttachment并将其用作文本存储中的分节符指示符。问题在于,每当用户编辑文本时,文本视图仅调用以下方法

      func replaceCharacters(in range: NSRange, 
                             with str: String)
      
      Run Code Online (Sandbox Code Playgroud)

      func setAttributes(_ attrs: [NSAttributedString.Key : Any]?, 
                           range: NSRange)
      
      Run Code Online (Sandbox Code Playgroud)

      第一种方法仅传递不带任何属性的纯字符串,第二种方法仅获取属性。这意味着在第一种方法中,我无法确定替换字符是否实际上应该是分节符,因此我无法确定此时在内部文本存储数组中的哪个位置创建新元素。

      在第二种方法中,我不知道用户是否实际添加了新文本(在这种情况下,我将不得不在文本存储数组中为每个分节符属性添加一个新元素)还是用户只是更改了现有的某些属性文本(在这种情况下,先前已经创建了新的数组元素)。

    2. 我还考虑了在表视图或堆栈视图中使用多个文本视图的想法。但是,这不起作用,因为它将使用户无法选择(和删除)多个后续部分中的文本。

    3. 最后,我尝试了子类化NSLayoutManager,但是关于它的文档确实很薄,对我来说似乎是错误的地方。(毕竟,布局经理的职责是文本的布局,而不是跟踪其结构。)

    有任何想法吗?

    nslayoutmanager nstextview uitextview ios nstextstorage

    10
    推荐指数
    1
    解决办法
    203
    查看次数