1

I have a UITextView with a custom NSTextLayout:

VPLayoutManager.h

#import <UIKit/UIKit.h>

@interface VPLayoutManager : NSLayoutManager <NSLayoutManagerDelegate>

@end

VPLayoutManager.m

#import "VPLayoutManager.h"

@implementation VPLayoutManager

- (id)init
{
    self = [super init];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin
{
    //[super drawGlyphsForGlyphRange:glyphsToShow atPoint:origin];
    [self enumerateLineFragmentsForGlyphRange:glyphsToShow usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *textContainer, NSRange glyphRange, BOOL *stop) {
        NSRange characterRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:nil];
        NSRange paragraphRange = [self.textStorage.string paragraphRangeForRange:characterRange];
        if (characterRange.location == paragraphRange.location) {
            NSString *listCharacter = [self.textStorage.string substringWithRange:NSMakeRange(glyphRange.location, 1)];
            if ([listCharacter isEqualToString:@"\u2063"]) {
                CGRect listRect = CGRectOffset(CGRectMake(usedRect.origin.x - 10.0f, usedRect.origin.y, 40.0f, usedRect.size.height), origin.x, origin.y);
                NSDictionary *attributes = @{NSFontAttributeName : [UIFont systemFontOfSize:20.0f],
                                  NSForegroundColorAttributeName : [UIColor blackColor]};
                [@"-" drawInRect:listRect withAttributes:attributes];
                //[super drawGlyphsForGlyphRange:glyphRange atPoint:origin];
            }
            else {
                //[super drawGlyphsForGlyphRange:glyphRange atPoint:origin];
            }
        }
    }];
    [super drawGlyphsForGlyphRange:glyphsToShow atPoint:origin];
}

- (NSUInteger)layoutManager:(NSLayoutManager *)layoutManager shouldGenerateGlyphs:(const CGGlyph *)glyphs properties:(const NSGlyphProperty *)props characterIndexes:(const NSUInteger *)charIndexes font:(UIFont *)aFont forGlyphRange:(NSRange)glyphRange
{
    if (glyphRange.length > 1) {
        NSGlyphProperty *properties = malloc(sizeof(NSGlyphProperty) * glyphRange.length);
        NSString *substring = [self.textStorage.string substringWithRange:glyphRange];
        for (NSUInteger i = 0; i < glyphRange.length; i++) {
            properties[i] = props[i];
        }

        NSRange regex = [substring rangeOfString:@"\u2063" options:NSRegularExpressionSearch];
        if (regex.location != NSNotFound) {
            for (NSUInteger i = regex.location; i < regex.length; i++) {
#warning crash on new-line if not at the end of the list
                properties[i] = NSGlyphPropertyControlCharacter;
            }
        }
        [layoutManager setGlyphs:glyphs properties:properties characterIndexes:charIndexes font:aFont forGlyphRange:glyphRange];
        return glyphRange.length;
    }
    [layoutManager setGlyphs:glyphs properties:props characterIndexes:charIndexes font:aFont forGlyphRange:glyphRange];
    return glyphRange.length;
}

- (NSControlCharacterAction)layoutManager:(NSLayoutManager *)layoutManager shouldUseAction:(NSControlCharacterAction)action forControlCharacterAtIndex:(NSUInteger)charIndex
{
    NSString *substring = [layoutManager.textStorage.string substringWithRange:NSMakeRange(charIndex, 1)];
    if ([substring isEqualToString:@"\u2063"]) {
        return NSControlCharacterZeroAdvancementAction;
    }
    return action;
}

@end

This code hides the glyph but the UITextView still sees the glyph (the cursor still "shows" that there is a glyph in that position even if is now invisible)... so the question is: how do I completely hide a glyph?

I'm trying to create lists based on a character on the start of a paragraph, the idea was to add a unicode that identifies if the paragraph is part of a list, and inside NSTextLayout, hide this unicode and do the proper operation for "draw" the list.

genesisxyz
  • 778
  • 3
  • 14
  • 29

0 Answers0