我正在制作一本带有Core Text的杂志,我正在尝试自动为文本添加连字符。我想我可以用函数
来做到这一点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的方法(在前一行的“ - ”之后添加剩余的字符)。
答案 0 :(得分:6)
在创建属性字符串之前,您可以添加软连字符。然后你可以做绘图。
我写了一个类别,用于为任何字符串添加“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
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
#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
希望这会有所帮助:)