向 NSString 添加省略号

2024-02-17

我有以下代码,我试图使用核心文本来绘制它,这就是为什么我不能像 UILabel 那样剪切文本。换句话说,我必须自己找出省略号(“...”)。

 CGSize commentSize = [[self.sizeDictionary_ valueForKey:commentSizeKey] CGSizeValue];
        CGSize actualSize = [[self.sizeDictionary_ valueForKey:actualCommentSizeKey] CGSizeValue];

 NSString *actualComment = self.highlightItem_.comment;
        if (actualSize.height > commentSize.height){
            actualComment = [self.highlightItem_.comment stringByReplacingCharactersInRange:NSMakeRange(68, 3) withString:@"..."];
        }

我很难根据 CGSize 找到“...”的范围。解决这个问题的最佳方法是什么?

我是这样画的:

CFStringRef string = CFBridgingRetain(actualComment);
        CFMutableAttributedStringRef comment = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
        CFAttributedStringReplaceString (comment ,CFRangeMake(0, 0), string);

        CGColorRef blue = CGColorRetain([UIColor colorWithRed:131/255.f green:204/255.f blue:253/255.f alpha:1.0].CGColor);
        CGColorRef gray = CGColorRetain([UIColor colorWithWhite:165/255.f alpha:1.0].CGColor);

        CFAttributedStringSetAttribute(comment, CFRangeMake(0, [name length]),kCTForegroundColorAttributeName, blue);
        CFAttributedStringSetAttribute(comment, CFRangeMake([name length],  [self.highlightItem_.comment length] - [name length]),kCTForegroundColorAttributeName, gray);

        CGColorRelease (blue);
        CGColorRelease (gray);

        CTFontRef nameFont = CTFontCreateWithName(CFBridgingRetain(kProximaNovaBold), 13.0f, nil);
        CFAttributedStringSetAttribute(comment,CFRangeMake(0, [name length]),kCTFontAttributeName,nameFont);

        CTFontRef commentFont = CTFontCreateWithName(CFBridgingRetain(kProximaNovaRegular), 13.0f, nil);
        CFAttributedStringSetAttribute(comment, CFRangeMake([name length],  [self.highlightItem_.comment length] - [name length]),kCTFontAttributeName,commentFont);

        CGFloat commentYOffset = floorf((self.commentHeight_ - commentSize.height)/2);

        CGContextSaveGState(context);
        CGRect captionFrame = CGRectMake(0, 0, rect.size.width - 80, commentSize.height);
        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(comment);
        CGMutablePathRef captionFramePath = CGPathCreateMutable();
        CGPathAddRect(captionFramePath, NULL, captionFrame);

        CTFrameRef mainCaptionFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), captionFramePath, NULL);

        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetTextMatrix(context, CGAffineTransformIdentity);
        CGContextTranslateCTM(context, self.buttonSize_ + 25, self.imageHeight_ + self.commentHeight_ + 6 - commentYOffset);
        CGContextScaleCTM(context, 1.0, -1.0);

        CTFrameDraw(mainCaptionFrame, context);
        CGContextRestoreGState(context);

EDIT

(我原来的答案在这里没有用;它不处理多行。如果有人想查看它的历史兴趣,请查看编辑历史记录。我已经删除了它,因为它引起的混乱比它解决的问题更多。当前答案是正确的代码。)

你需要做的是让CTFramesetter计算出除最后一行之外的所有行。然后,如果需要,您可以手动截断最后一个。

- (void)drawRect:(CGRect)rect
{
  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSetTextMatrix(context, CGAffineTransformIdentity);

  CGRect pathRect = CGRectMake(50, 200, 200, 40);
  CGPathRef path = CGPathCreateWithRect(pathRect, NULL);

  CFAttributedStringRef attrString = (__bridge CFTypeRef)[self attributedString];

  // Create the framesetter using the attributed string
  CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);

  // Create a single frame using the entire string (CFRange(0,0))
  // that fits inside of path.
  CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);

  // Draw the lines except the last one
  CFArrayRef lines = CTFrameGetLines(frame);
  CFIndex lineCount = CFArrayGetCount(lines);
  CGPoint origins[lineCount]; // I'm assuming that a stack variable is safe here.
                              // This would be bad if there were thousdands of lines, but that's unlikely.
  CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins);
  for (CFIndex i = 0; i < lineCount - 1; ++i) {
    CGContextSetTextPosition(context, pathRect.origin.x + origins[i].x, pathRect.origin.y + origins[i].y);
    CTLineDraw(CFArrayGetValueAtIndex(lines, i), context);
  }

  ///
  /// HERE'S THE INTERESTING PART
  ///
  // Make a new last line that includes the rest of the string.
  // The last line is already truncated (just with no truncation mark), so we can't truncate it again
  CTLineRef lastLine = CFArrayGetValueAtIndex(lines, lineCount - 1);
  CFIndex lastLocation = CTLineGetStringRange(lastLine).location;
  CFRange restRange = CFRangeMake(lastLocation, CFAttributedStringGetLength(attrString) - lastLocation);
  CFAttributedStringRef restOfString = CFAttributedStringCreateWithSubstring(NULL, attrString, restRange);
  CTLineRef restLine = CTLineCreateWithAttributedString(restOfString);


  // We need to provide the truncation mark. This is an ellipsis (Cmd-semicolon).
  // You could also use "\u2026". Don't use dot-dot-dot. It'll work, it's just not correct.
  // Obviously you could cache this…
  CTLineRef ellipsis = CTLineCreateWithAttributedString((__bridge CFTypeRef)
                                                        [[NSAttributedString alloc] initWithString:@"…"]);

  // OK, now let's truncate it and draw it. I'm being a little sloppy here. If ellipsis could possibly
  // be wider than the path width, then this will fail and truncateLine will be NULL and we'll crash.
  // Don't do that.
  CTLineRef truncatedLine = CTLineCreateTruncatedLine(restLine,
                                                      CGRectGetWidth(pathRect),
                                                      kCTLineTruncationEnd,
                                                      ellipsis);
  CGContextSetTextPosition(context, pathRect.origin.x + origins[lineCount - 1].x, pathRect.origin.y + origins[lineCount - 1].y);
  CTLineDraw(truncatedLine, context);

  CFRelease(truncatedLine);
  CFRelease(ellipsis);
  CFRelease(restLine);
  CFRelease(restOfString);
  CFRelease(frame);
  CFRelease(framesetter);
  CGPathRelease(path);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

向 NSString 添加省略号 的相关文章

  • 理解 Objective-C 中选择器的唯一性

    我无法理解 选择器 的部分功能 如苹果指南中所述 我把我感到困惑的部分加粗了 在 Objective C 中 选择器有两个含义 可以用来参考 当在源代码消息中使用方法时 只需使用方法的名称 到一个物体 不过 它也指的是唯一标识符 编译源代码
  • 渐变方向从左到右

    我完全被这个问题难住了 它应该如此简单 以至于让我发疯 我正在使用这个苹果反射教程 苹果反射示例 http developer apple com library ios samplecode Reflection Listings MyV
  • 如何在iPhone中将字节数组转换为base64字符串?

    我有一段vb代码 我需要将字节数组转换为 Base 64 字符串 下面是vb代码 如果 arrLicence Count gt 0 那么 LicenseBytes CType Array CreateInstance GetType Byt
  • 从哪里开始使用适用于 Retina 显示屏的 OpenGL 绘制程序

    我知道由于这里提到的错误 我无法将 GLPainter 示例从苹果适应到视网膜 在 Retina iPad 上显示全屏 CAEAGLLayer 时出现问题 https stackoverflow com questions 9757052
  • iphone - 如何读取麦克风输入?

    如何从麦克风读取声音数据 我不想录制然后访问数据 我希望能够实时访问声音输入 您可以将麦克风中的声音 PCM 样本 录制到非常短的内存缓冲区 持续时间短至几毫秒 这与使用 iOS API 一样接近 实时 查看 aurioTouch 示例 了
  • 如何知道两个 NSDate 是否在同一天

    你知道如何知道两个NSDate是同一天 我想考虑到区域设置 使用a可能很容易timeIntervalSinceDate 但星期一 23H58 和星期二 00H01 不在同一天 处理NSDate和计算区域设置不是很容易 NSCalendar
  • 当表格为空时 iPhone UITableView 图像背景

    我想当我的 UITableView 为空时显示图像背景 目前 我尝试将 UIImageView 添加到包含表格的视图控制器 但 XCode 不允许这样做 有没有好的方法呢 您可以在表视图顶部添加图像视图或更改表视图的背景视图 Check i
  • 是否可以对 UILabel 的文本颜色变化进行动画处理? [复制]

    这个问题在这里已经有答案了 UIView animateWithDuration 5 animations myLabel textColor UIColor redColor 标签文本颜色立即改变 Try this UIView tran
  • Objective C 宏附加到字符串

    我认为这是一件非常简单的事情 但由于我是 iOS 开发和 Objective C 的新手 所以我无法弄清楚 define RESTFUL PATH PREFIX https gogch com gch restful define LOGI
  • 未找到符号,预计出现在平面命名空间 ObjC++ 中

    我可能遇到了一个简单的问题 但是在编译过程中没有任何信息错误或警告来提醒我出了什么问题 我有一个 Objective C 应用程序 其中包含 C 主文件和 ObjC 头文件 它构建得很好 但是当运行时 它会给出以下错误消息 Dyld Err
  • iOS5 和 Facebook API

    我想将我的应用程序与 Facebook 集成并从 github 下载 Facebook ios sdk 但是 该 sdk 适用于 Xcode 4 0 代码库 我正在使用 Xcode 4 2 for iOS 5 beta 5 应用程序 是否有
  • 在后台运行 URL 请求

    我想在一定的时间间隔内发出 url 请求 例如 每 10 分钟应用程序应该发出一次 url 调用并获取一些 json 数据 应用程序在后台运行时应该能够执行此操作 这可以做到吗 如果是这样 这是否违反 Apple 服务条款 有什么限制吗 i
  • 双击并滑动/拖动手指以放大/缩小

    如果有人使用过 iOS 版谷歌地图应用程序 那么它有一个很棒的功能 可以用一根手指放大 缩小 双击 uiscrollview 然后立即向上或向下滑动手指以放大 缩小 有谁知道这是如何实现的 谷歌发布了任何片段吗 我将此功能添加到我的 UIS
  • 如何在 iOS 应用程序中检测所有可用的 Wifi 网络并连接到其中之一

    在我的 iOS 应用程序中 我想检测所有可用的 wifi 网络 然后从列表中选择一个网络并连接到它 目标是不打开应用程序内置的设置来连接 Wi Fi 而是在我的应用程序中完成这一切 首先 这可能吗 如果可能的话 请指出要使用哪些框架和方法
  • 使用 UIWebView 显示 PDF 不起作用

    因此 我意识到有关使用 UIWebView 在应用程序 在 iPad 上 中显示 PDF 存在很多问题 我已经审查了我能找到的所有内容 但似乎找不到任何满意的东西 我想做的事情非常基本 所以我真的不知道为什么它不起作用 我需要做的就是在 U
  • admob ios7错误音频框架

    我正在将 admob SDK 当前的 集成到我的上一个应用程序 IOS7 Xcode5 中 并且出现了一个新错误 在新项目上也是如此 我想我错过了一些东西 但我多次重新启动该过程 但错误仍然存 在 Undefined symbols for
  • 播放循环声音的最简单方法是什么?

    在 iPhone 应用程序中播放循环声音的最简单方法是什么 可能最简单的解决方案是使用AVA音频播放器 http developer apple com library ios DOCUMENTATION AVFoundation Refe
  • ObjectiveC 和 JavaScriptCore:使用这种调用回调的方法会导致内存问题吗?

    免责声明 这是一篇很长的文章 但对于那些努力使用新的 ObjectiveC JavascriptCore 框架并在 ObjC 和 JS 之间进行异步编码的人来说可能非常有价值 您好 我对 Objective C 非常陌生 正在将 javas
  • AGVTool new-version 和 What-version 不对应

    当我做 agvtool new version all 99 它更新我的 Info plist 文件 但是 如果我这样做 agvtool what version or agvtool next version 我收到此错误 There d
  • GCD 与自定义队列

    我想知道这两者的性能有什么区别 dispatch async dispatch get global queue DISPATCH QUEUE PRIORITY HIGH 0 perform complex operation dispat

随机推荐

  • iOS 下载和解析大型 JSON 响应导致 CFData(存储)泄漏

    用户第一次打开我的应用程序时 我需要下载大量数据 我从服务器以 JSON 形式获取所有这些数据 根据用户的不同 这些 JSON 文件的大小可以从 10kb 到 30mb 不等 而且数量超过 10 个 当 JSON 的记录不超过 500 条左
  • 立场:React Native中的绝对问题

    我正在制作一个反应本机应用程序 其中有一个左侧和右侧部分 左侧部分包括flex 0 7右侧部分包括flex 0 2 在左侧部分内 我有一个容器 里面有一个ImageBackground https reactnative dev docs
  • MongoDB 查询 - 限制名称与模式匹配的字段

    我已经阅读了有关 MongoDB 中投影的所有内容 我希望这很简单 但由于 Mongo 查询的巨大灵活性 我错过了它 在我们的 MySql 数据库中 我们采用了一种业务实践 即为 隐藏 字段添加下划线前缀 我们的应用程序知道如何隐藏这些字段
  • PHP 中同时调用多个 API

    我正在处理一个场景搜索页面 http www idynbiz com web html carcrawler 该搜索页面必须同时对以下 5 个搜索引擎进行 API 调用 http www kijiji ca http www kijiji
  • C - RGB 值 - 计算模糊滤镜的 RGB 值的平均值

    前两个并不难 但第三个让我生气 模糊滤波器必须计算某些像素组的 RGB 值的平均值 以便替换中心像素的值 想象一个 3x3 的网格 其中中心的像素必须使用周围八个像素的平均值和中心像素本身的 RGB 值进行操作 到目前为止我所做的如下 Bl
  • 在 Magento 中根据 URL 参数加载对象

    我在为 Magento 商店创建自定义模块时遇到问题 我已成功添加路线 着陆 并创建 布局文件 在我的基本布局中显示模板内容 我现在需要稍微超越这一点 我希望能够从 URL 加载参数 根据该参数抓取一个对象 并根据对象的内容显示内容 示例
  • Magento - 从预调度观察者转发到不同的控制器操作

    是否可以根据我可以在控制器预调度事件中检查的特定条件转发到不同的操作 在同一控制器内 例如 要运行的操作是索引 如果我为预调度事件创建一个观察者 如果某个条件为真 我想运行不同的操作 myAction而不是indexAction 您可以在预
  • Angular JS 和部分

    是否可以在 Angular JS 中将 html 页面嵌入到另一个页面中 如果可以的话 该怎么办呢 Here http docs angularjs org tutorial step 08在他们的教程中 部分内容并未嵌入页面中 但它就像您
  • 使用 webview 中的 cookie 执行 HTTP 请求

    我有这样的场景 我的应用程序在 webView 中显示一个 2 页的登录过程 第一页仅询问您计划连接到哪个域 第二页要求提供凭据 我正在尝试在 webView 中执行登录 然后执行来自本机代码的请求 我意识到我需要从 webView 获取存
  • 左侧固定列与表 colspan

    我已经使用了这个 js 文件和以下方法 https code jquery com jquery 3 3 1 js https code jquery com jquery 3 3 1 js https cdn datatables net
  • UISplitViewController 的详细视图中缺少标题栏

    我有一个UISplitViewController嵌入到容器视图中 因为它不在我的应用程序的根目录中 其机制运行良好 除了一个问题 iPad 上缺少详细视图的导航栏 初始设置基本如下 在 IB 中 将分割视图控制器拖到情节提要上 这将创建分
  • 无法使用 AutoLayout 设置 UICollectionViewCell 的宽度

    我有一个带有动态高度单元格的集合视图 基于可能的多行标签和内部的文本视图 当我跨越多行时 它可以完美地适应高度 但是 当文本只有一个单词或者没有覆盖整个屏幕宽度时 单元格的宽度就与需要的一样宽 从而导致单元格彼此相邻而不是彼此下方 看看文本
  • SELECT 和 UPDATE 表,因此线程不会重叠

    假设我有下表 ID Read 1 true 2 false 3 false 4 false 我需要读取最小的 ID 其中 Read false 另外 更新一下我现在已经读过了 因此 如果我执行存储过程 dbo getMinID 它将返回 I
  • 使用反射调用泛型重载方法

    我需要使用反射调用重载方法 我的课程如下 public static Transformer Overloaded method with generics parameter First Transform Method public s
  • 在 C#/.Net 中创建/切换桌面

    我当前正在使用 CreateDesktop 本机 C 函数 并在我的 C 代码中调用它来创建桌面并在桌面之间切换 有没有办法使用 Process 类或任何 c Net 类来做到这一点 这是我现在在课堂上使用的用于桌面切换的示例代码 Flag
  • PHP AJAX登录,这种方式安全吗?

    我刚刚启动 PHP 和 MySQL 并创建了一个登录表单 一切正常 现在我想添加 ajax 我考虑的第一个方法是使用 jQuery post 方法 我对代码没问题 这里是我将要做什么的快速想法 function login post log
  • 当 debug 为 0 时,如何使用 CakePHP 记录 php 错误?

    我想在 debug 0 的 CakePHP 站点上记录 PHP 错误 但是 即使我打开错误日志 如下所示 error reporting E ALL E NOTICE E DEPRECATED log errors On 它不记录错误 问题
  • 加载属性文件时出现问题

    我在加载时遇到问题 test xml and test properties 在同一文件夹conf中 我在 dist 文件夹中有一个 myProject jar conf 文件夹内的 test xml 和 test properties 要
  • C 中的 strcat 两个无符号字符

    我目前正在尝试对两个无符号字符使用 strcat 但我不断收到警告 这是我对 strcat 的了解 unsigned char A 100 B 100 A 0 1 B 0 2 strcat A B 我试图将它们放在一起 以便我得到 A 作为
  • 向 NSString 添加省略号

    我有以下代码 我试图使用核心文本来绘制它 这就是为什么我不能像 UILabel 那样剪切文本 换句话说 我必须自己找出省略号 CGSize commentSize self sizeDictionary valueForKey commen