Agregar guiones con CFStringGetHyphenationLocationBeforeIndex

Estoy haciendo una revista con Core Text y estoy tratando de agregar automáticamente guiones al text. Creo que puedo hacer esto con la function

CFStringGetHyphenationLocationBeforeIndex 

Pero no funciona y no puedo encontrar ningún ejemplo en línea.

Lo que bash hacer es configurar el text y, si encuentro una position de guión, coloque allí un "-" y reemplace el text a través del acceso para que llame a setNeedsDisplay y dibuje de nuevo desde cero.

 - (void) setTexto:(NSAttributedString *)text { _text = text; 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)(_text)); self.ctFrame = CTFramesetterCreateFrame(ctFrameSetterRef, CFRangeMake(0, [_text 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.text.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.text.mutableCopy; [attributedString replaceCharactersInRange:replaceRange withAttributedString:[[NSAttributedString alloc] initWithString:@"-"]]; self.text = 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); } } } 

El problema es la segunda vez que entra en drawRect (con el nuevo text) lines.count log en 0. Y tampoco estoy seguro de que esta sea la forma correcta de hacerlo.

Tal vez hay otra forma de modificar las CTLines (agregando los caracteres restantes después del "-" de la línea anterior).

Antes de crear la cadena atribuida, puede agregar guiones separados. Entonces podrías hacer el dibujo.

Escribí una categoría para agregar "separación suave" a cualquier cadena. Estos son "-", que no son visibles cuando se representan, sino que simplemente hacen queues para CoreText o UITextKit para saber cómo dividir las palabras.

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

Salidas 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 

Espero que esto ayude 🙂