使用CFStringGetHyphenationLocationBeforeIndex添加连字符

我正在制作一本带有Core Text的杂志,我正在尝试自动为文本添加连字符。 我想我可以用这个function做到这一点

CFStringGetHyphenationLocationBeforeIndex 

但它没有用,我在网上找不到任何例子。

我要做的是设置文本,如果我找到任何连字符位置,我在其中放置一个“ – ”并通过访问器替换文本,因此它调用setNeedsDisplay并从头开始绘制。

 - (void) setTexto:(NSAttributedString *)texto { _texto = texto; if (self.ctFrame != NULL) { CFRelease(self.ctFrame); self.ctFrame = NULL; } [self setNeedsDisplay]; } -(void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextScaleCTM(context, 1.0, -1.0); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, self.bounds); CTFramesetterRef ctFrameSetterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(_texto)); self.ctFrame = CTFramesetterCreateFrame(ctFrameSetterRef, CFRangeMake(0, [_texto length]), path, NULL); NSArray *lines = (__bridge NSArray *)(CTFrameGetLines(self.ctFrame)); CFIndex lineCount = [lines count]; NSLog(@"lines: %d", lines.count); for(CFIndex idx = 0; idx < lineCount; idx++) { CTLineRef line = CFArrayGetValueAtIndex((CFArrayRef)lines, idx); CFRange lineStringRange = CTLineGetStringRange(line); NSRange lineRange = NSMakeRange(lineStringRange.location, lineStringRange.length); NSString* lineString = [self.texto.string substringWithRange:lineRange]; CFStringRef localeIdent = CFSTR("es_ES"); CFLocaleRef localeRef = CFLocaleCreate(kCFAllocatorDefault, localeIdent); NSUInteger breakAt = CFStringGetHyphenationLocationBeforeIndex((__bridge CFStringRef)lineString, lineRange.length, CFRangeMake(0, lineRange.length), 0, localeRef, NULL); if(breakAt!=-1) { NSRange replaceRange = NSMakeRange(lineRange.location+breakAt, 0); NSMutableAttributedString* attributedString = self.texto.mutableCopy; [attributedString replaceCharactersInRange:replaceRange withAttributedString:[[NSAttributedString alloc] initWithString:@"-"]]; self.texto = attributedString.copy; break; } else { CGFloat ascent; CGFloat descent; CTLineGetTypographicBounds(line, &ascent, &descent, nil); CGContextSetTextPosition(context, 0.0, idx*-(ascent - 1 + descent)-ascent); CTLineDraw(line, context); } } } 

问题是它第二次进入drawRect(使用新文本)lines.count日志为0.而且我也不确定这是正确的方法。

也许有另一种修改CTLines的方法(在前一行的“ – ”之后添加剩余的字符)。

在创建属性字符串之前,您可以添加软连字符。 然后你可以做绘图。

我写了一个类别,为任何字符串添加“soft hyphenation”。 这些是“ – ”,在渲染时不可见,而只是排队等待CoreText或UITextKit知道如何分解单词。

 NSString *string = @"accessibility tests and frameworks checking"; NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"en_US"]; NSString *hyphenatedString = [string softHyphenatedStringWithLocale:locale error:nil]; NSLog(@"%@", hyphenatedString); 

输出ac-ces-si-bil-i-ty tests and frame-works check-ing


的NSString + SoftHyphenation.h

 typedef enum { NSStringSoftHyphenationErrorNotAvailableForLocale } NSStringSoftHyphenationError; extern NSString * const NSStringSoftHyphenationErrorDomain; extern NSString * const NSStringSoftHyphenationToken; @interface NSString (SoftHyphenation) - (BOOL)canSoftHyphenateStringWithLocale:(NSLocale *)locale; - (NSString *)softHyphenatedStringWithLocale:(NSLocale *)locale error:(out NSError **)error; @end 

的NSString + SoftHyphenation.m

 #import "NSString+SoftHyphenation.h" NSString * const NSStringSoftHyphenationErrorDomain = @"NSStringSoftHyphenationErrorDomain"; NSString * const NSStringSoftHyphenationToken = @""; // NOTE: UTF-8 soft hyphen! @implementation NSString (SoftHyphenation) - (BOOL)canSoftHyphenateStringWithLocale:(NSLocale *)locale { CFLocaleRef localeRef = (__bridge CFLocaleRef)(locale); return CFStringIsHyphenationAvailableForLocale(localeRef); } - (NSString *)softHyphenatedStringWithLocale:(NSLocale *)locale error:(out NSError **)error { if(![self canSoftHyphenateStringWithLocale:locale]) { if(error != NULL) { *error = [self hyphen_createOnlyError]; } return [self copy]; } else { NSMutableString *string = [self mutableCopy]; unsigned char hyphenationLocations[string.length]; memset(hyphenationLocations, 0, string.length); CFRange range = CFRangeMake(0, string.length); CFLocaleRef localeRef = (__bridge CFLocaleRef)(locale); for(int i = 0; i < string.length; i++) { CFIndex location = CFStringGetHyphenationLocationBeforeIndex((CFStringRef)string, i, range, 0, localeRef, NULL); if(location >= 0 && location < string.length) { hyphenationLocations[location] = 1; } } for(int i = string.length - 1; i > 0; i--) { if(hyphenationLocations[i]) { [string insertString:NSStringSoftHyphenationToken atIndex:i]; } } if(error != NULL) { *error = nil; } // Left here in case you want to test with visible results // return [string stringByReplacingOccurrencesOfString:NSStringSoftHyphenationToken withString:@"-"]; return string; } } - (NSError *)hyphen_createOnlyError { NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Hyphenation is not available for given locale", NSLocalizedFailureReasonErrorKey: @"Hyphenation is not available for given locale", NSLocalizedRecoverySuggestionErrorKey: @"You could try using a different locale even though it might not be 100% correct" }; return [NSError errorWithDomain:NSStringSoftHyphenationErrorDomain code:NSStringSoftHyphenationErrorNotAvailableForLocale userInfo:userInfo]; } @end 

希望这可以帮助 :)