Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 向NSString添加省略号_Iphone_Objective C_Ipad_Nsstring - Fatal编程技术网

Iphone 向NSString添加省略号

Iphone 向NSString添加省略号,iphone,objective-c,ipad,nsstring,Iphone,Objective C,Ipad,Nsstring,我有下面的代码,我正在尝试使用核心文本绘制,这就是为什么我不能像UILabel那样剪裁文本。换句话说,我必须自己找出省略号(“…”) 我很难根据CGSize找到“…”的范围。解决这个问题的最好办法是什么 我是这样画的: CFStringRef string = CFBridgingRetain(actualComment); CFMutableAttributedStringRef comment = CFAttributedStringCreateMutable(kCFAllo

我有下面的代码,我正在尝试使用核心文本绘制,这就是为什么我不能像UILabel那样剪裁文本。换句话说,我必须自己找出省略号(“…”)

我很难根据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);
编辑

(我在这里的原始答案没有用;它不能处理多行。如果有人想查看历史记录,请查看编辑历史记录。我删除了它,因为它造成的混乱比它解决的要多。当前答案是正确的代码。)

您需要做的是让
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);
}
-(void)drawRect:(CGRect)rect
{
CGContextRef context=UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(上下文,CGAffineTransformity);
CGRect pathRect=CGRectMake(5020020040);
CGPathRef path=CGPathCreateWithRect(pathRect,NULL);
CFAttributedStringRef属性字符串=(uu桥CFTypeRef)[自属性字符串];
//使用属性化字符串创建框架设置器
CTFramesetterRef framesetter=CTFramesetterCreateWithAttributedString(attrString);
//使用整个字符串创建单个帧(CFRange(0,0))
//这符合路径的内部。
CTFrameRef frame=CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0),path,NULL);
//画除最后一条线以外的线
CFArrayRef lines=CTFrameGetLines(帧);
CFIndex lineCount=CFArrayGetCount(行);
CGPoint origins[lineCount];//我假设堆栈变量在这里是安全的。
//如果有上千行的话,这会很糟糕,但这不太可能。
CTFrameGetLineOriginates(框架,CFRangeMake(0,0),原点);
对于(CFIndex i=0;i
像这样的东西怎么样

- (NSString *)truncate:(NSString *)string toWidth:(CGFloat)width withFont:(UIFont *)font {

    CGSize size = [string sizeWithFont:font];
    if (size.width <= width) return string;

    NSString *truncatedString = [string copy];
    NSString *ellipticalString = [truncatedString stringByAppendingString:@"..."];
    size = [ellipticalString sizeWithFont:font];

    while (size.width > width && truncatedString.length) {
        truncatedString = [truncatedString substringToIndex:(truncatedString.length-1)];
        ellipticalString = [truncatedString stringByAppendingString:@"..."];
        size = [ellipticalString sizeWithFont:font];
    }
    return ellipticalString;
}
-(NSString*)截断:(NSString*)字符串到宽度:(CGFloat)宽度,使用font:(UIFont*)字体{
CGSize size=[字符串大小WithFont:font];
if(size.width&&truncatedString.length){
truncatedString=[truncatedString子字符串到索引:(truncatedString.length-1)];
ellipticalString=[truncatedString stringByAppendingString:@“…”;
大小=[ellipticalString sizeWithFont:font];
}
返回椭圆字符串;
}

最简单的方法

NSString *theText = @"bla blah bla bhla bla bla";
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByTruncatingTail];
[theText drawInRect:dirtyRect withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:style, NSParagraphStyleAttributeName,nil]];

对于

,您可以使用
NSString drawAtPoint:forWidth:withFont:lineBreakMode:
(或类似)方法将
nslinebreakbytruncingtail
传递为换行模式吗?@rmaddy我编辑了上面的帖子,以显示我是如何绘制文本的。实际上我没有使用DrawatPoint,我很确定有一个自动生成椭圆的工具,尽管我现在找不到。(我想可能是NSFont,但我在那里没有看到。)是的..几天来我一直在试图弄清楚这一点,但找不到它将字符串勾入标签(不需要在任何地方显示)。使用sizeThatFits:确定字符串是否适合标签。在该示例中,我没有看到任何NSLineBreakMode。我实际上在最后调用了CFRelease,我现在在此处显示它是的,但是示例中有
kCTParagraphStyleSpecifierAlignment
,换行符基本上是一样的。虽然我非常喜欢这个解决方案,而且它是最接近的解决方案,但问题是KCTLineBreakByTruncingTail只显示第一行。我尝试添加一些属性来更改属性字符串的颜色,但被截断的椭圆不再起作用。。当我不在中添加颜色属性时。。它起作用了。。有什么想法吗
NSString *theText = @"bla blah bla bhla bla bla";
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByTruncatingTail];
[theText drawInRect:dirtyRect withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:style, NSParagraphStyleAttributeName,nil]];