Question

I am trying to allow users the ability to set text they will type as underline, without having text currently selected. This is for an iOS 6 app, entering text in a UITextView. It will be saved as an NSAttributedString. Bold and italic work fine. Something about underline is keeping it from working.

UITextView *textView = [self noteTextView];
NSMutableDictionary *typingAttributes = [[textView typingAttributes] mutableCopy];
[typingAttributes setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName];
NSLog(@"attributes after: %@", typingAttributes);
[textView setTypingAttributes:typingAttributes];
NSLog(@"text view attributes after: %@", [textView typingAttributes]);

My initial log statement indicates it is set to underline:

attributes after: {
    NSColor = "UIDeviceRGBColorSpace 0 0 0 1";
    NSFont = "<UICFFont: 0xa9c5e30> font-family: \"Verdana\"; font-weight: normal; font-style: normal; font-size: 17px";
    NSKern = 0;
    NSStrokeColor = "UIDeviceRGBColorSpace 0 0 0 1";
    NSStrokeWidth = 0;
    NSUnderline = 1;
}

But the log statement immediately after doesn't show an nsunderline attribute. Removing the textView setTypingAttributes line has no affect.

text view attributes after: {
    NSColor = "UIDeviceRGBColorSpace 0 0 0 1";
    NSFont = "<UICFFont: 0xa9c5e30> font-family: \"Verdana\"; font-weight: normal; font-style: normal; font-size: 17px";
    NSKern = 0;
    NSStrokeColor = "UIDeviceRGBColorSpace 0 0 0 1";
    NSStrokeWidth = 0;
}

I'm stumped why I have it working for bold and italic, but not underline. Also why it seems to initially get the attribute, then forget it. Please share any insight you may have. Thanks.

Was it helpful?

Solution

I think you've found a bug, or at least some undocumented behavior. If I set the typing attributes to red, I can do it:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
        replacementString:(NSString *)string {
    NSDictionary* d = textField.typingAttributes;
    NSLog(@"%@", d);
    NSMutableDictionary* md = [NSMutableDictionary dictionaryWithDictionary:d];
    // md[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleSingle);
    md[NSForegroundColorAttributeName] = [UIColor redColor];
    textField.typingAttributes = md;
    return YES;
}

With that code, all the user's new typing comes out red. But if I uncomment the commented line, trying to add underlining to the typing attributes, it breaks the whole thing - I don't get underlining, and I don't get red coloring either!

The answer to the other part of your question, though, is documented. You have to do it the way I'm doing it, reasserting the typing attributes as the user types, because, as the documentation clearly states, "When the text field’s selection changes, the contents of the dictionary are cleared automatically" (that's the "forgetting" you asked about).

OTHER TIPS

As of iOS 6, UITextView now declares property attributedText which allows you to underline text by creating an NSAttributedString. Here is the modified code:

UITextView *textView = [self noteTextView];
NSMutableDictionary *typingAttributes = [[textView typingAttributes] mutableCopy];
[typingAttributes setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName];
NSLog(@"attributes after: %@", typingAttributes);
textView.attributedText = [[NSAttributedString alloc] initWithString:[textView text] attributes:typingAttributes];
NSLog(@"text view attributes after: %@", [textView typingAttributes]);

By using this code, any further text that is typed will also conform to the format set out in your NSAttributedString e.g. underlining

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top