核心文本:在后台线程中统计页面

问题描述:

假设我正在使用核心文本为iPhone编写文本查看器。每次用户更改基本字体大小时,我需要计算需要多少页(固定大小的CGRects)来显示给定字体大小的整个NSAttributedString。核心文本:在后台线程中统计页面

我想在单独的NSOperation中这样做,以便用户不会遇到不必要的UI滞后。

不幸的是,为了统计我需要使用不可见文本绘制模式绘制帧(CTFrameDraw)的页数,然后使用CTFrameGetVisibleStringRange来计算字符数。但是为了绘制文本,我需要一个CGContext。这里的问题开始......通过调用UIGraphicsGetCurrentContext

我可以得到我的drawRect一个CGContext上,但在这种情况下:

  1. 我要调用,使用performSelectorOnMainThread,就在CGContext上运行任何方法?
  2. 另一个线程应该CFRain这个上下文。使用drawRect的CGContext外部drawRect方法是否可以接受?

其他解决方案?在工作线程中创建单独的CGContext?怎么样? CGBitmapContext?我怎样才能确定所有条件(我不知道,分辨率等)将与drawRect的CGContext中的相同,以便页面被正确计数?

+0

嗯,似乎在核心文本(不像石英),你不必绘制隐形文字来衡量它。所以只需要调用CTFramesetterCreateFrame,然后调用CTFrameGetVisibleStringRange而不用CGContext!任何人都可以确认吗? – 2010-07-09 16:03:03

你不需要CTFrameDraw从CTFrameGetVisibleStringRange得到结果

您可以使用CTFramesetterSuggestFrameSizeWithConstraints。

见我的问题在这里:How to split long NSString into pages

+0

不要相信CTFramesetterSuggestFrameSizeWithConstraints!看到这里:http://web.archiveorange.com/archive/v/nagQXwVJ6Gzix0veMh09 – 2010-10-06 13:08:52

+0

据我了解,它只是CGSize是坏的。在我的代码中,我忽略了返回的大小,我使用我用作约束的原始大小,并且它似乎迄今工作正常。尽管如此,它还没有广泛的测试过。 – 2010-10-08 08:44:21

+0

我想我不需要返回的大小,因为当您有适合约束的范围时,还有其他方法可以测量文本。 – 2010-10-08 08:49:48

使用CTFramesetterSuggestFrameSizeWithConstraints之前,如果指定fitRange的参数,它返回字符串

的实际范围
+ (NSArray*) pagesWithString:(NSString*)string size:(CGSize)size font:(UIFont*)font; 
{ 
    NSMutableArray* result = [[NSMutableArray alloc] initWithCapacity:32]; 
    CTFontRef fnt = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize,NULL); 
    CFAttributedStringRef str = CFAttributedStringCreate(kCFAllocatorDefault, 
                 (CFStringRef)string, 
                 (CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(id)fnt,kCTFontAttributeName,nil]); 
    CTFramesetterRef fs = CTFramesetterCreateWithAttributedString(str); 
    CFRange r = {0,0}; 
    CFRange res = {0,0}; 
    NSInteger str_len = [string length]; 
    do { 
    CTFramesetterSuggestFrameSizeWithConstraints(fs,r, NULL, size, &res); 
    r.location += res.length; 
    [result addObject:[NSNumber numberWithInt:res.length]]; 
    } while(r.location < str_len); 

    CFRelease(fs); 
    CFRelease(str); 
    CFRelease(fnt); 
    return result; 
}