Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ios7 font size change when create nsattributedstring from html

I have a UITextView where I'm managing an NSAttributedString, initially entered as normal via the keyboard. I save the attributed string as HTML, which looks fine. When I load it again, and convert it back to an attributed string from the HTML, the font size appears to change.

For example, the HTML on loading looks like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 21.0px Helvetica; color: #000000; -webkit-text-        stroke: #000000}
span.s1 {font-family: 'Helvetica'; font-weight: normal; font-style: normal; font-size:     21.00pt;     font-kerning: none}
</style>
</head>
<body>
<p class="p1"><span class="s1">There is some text as usual lots of text</span></p>
</body>
</html>

I convert it and check the attributes with the following code:

    // convert to attributed string
    NSError *err;
    NSAttributedString *as = [[NSAttributedString alloc] initWithData:data3
                            options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                      NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
                            documentAttributes:nil
                            error:&err] ;

    NSMutableAttributedString *res = [as mutableCopy];
    [res enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, res.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
        if (value) {
            UIFont *oldFont = (UIFont *)value;
            NSLog(@"On Loading: Font size %f, in range from %d length %d", oldFont.pointSize, range.location, range.length);
        }
    }];

The output shows that the font size has increased from 21 to 28:

On Loading: Font size 28.000000, in range from 0 length 40
On Loading: Font size 21.000000, in range from 40 length 1

Basically, each time I load the string, the font size increases. I need to store it as HTML rather than as NSData because it will also be used by other platforms.

Does anyone have any ideas why this is happening?

like image 882
Marion McKelvie Avatar asked Jan 08 '14 10:01

Marion McKelvie


People also ask

How to change the font size of the text in CSS?

The selector can either be our HTML tag or maybe a class or an ID. For example: // HTML <p> Any text whose font we want to change </p> // CSS p { font-size: 14px; }

What is the default font for NSAttributedString objects?

The default font for NSAttributedString objects is Helvetica 12-point, which may differ from the default system font for the platform.

What is the text size attribute?

This size attribute can take in value from 1-7 in which the text size increases from 1 to 7. But like I said, this has long been depreciated, and most people don't even know it existed. In case you are in a rush to see how you can change the size of your text, then here it is:

How do I use attributed strings in iOS?

In iOS 6 and later you can use attributed strings to display formatted text in text views, text fields, and some other controls. Both AppKit and UIKit also define extensions to the basic attributed string interface that allows you to draw their contents in the current graphic context.


3 Answers

I also faced this issue, I fixed it by iterating to the attributes and reseting the old font size as follows

NSMutableAttributedString *res = [attributedText mutableCopy];
[res beginEditing];
[res enumerateAttribute:NSFontAttributeName
                inRange:NSMakeRange(0, res.length)
                options:0
             usingBlock:^(id value, NSRange range, BOOL *stop) {
                 if (value) {
                     UIFont *oldFont = (UIFont *)value;
                     UIFont *newFont = [oldFont fontWithSize:15];
                     [res addAttribute:NSFontAttributeName value:newFont range:range];
                 }
             }];
[res endEditing];
[self.textFileInputView setAttributedText:res];
like image 151
KishoreThindaak Avatar answered Oct 31 '22 06:10

KishoreThindaak


Using <span> and css works for me, following Parsing HTML into NSAttributedText - how to set font?:

// HTML -> NSAttributedString
+ (NSAttributedString *)attributedStringFromHTML:(NSString *)html {
    NSError *error;
    NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:[html dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:&error];
    if(!attrString) {
        NSLog(@"creating attributed string from HTML failed: %@", error.debugDescription);
    }
    return attrString;
}

// force font thrugh <span> & css
+ (NSAttributedString *)attributedStringFromHTML:(NSString *)html withFont:(UIFont *)font    {
    return [Util attributedStringFromHTML:[NSString stringWithFormat:@"<span style=\"font-family: %@; font-size: %f\";>%@</span>", font.fontName, font.pointSize, html]];
}

This sets the font name and size but doesn't impact the styles.

like image 45
danomatika Avatar answered Oct 31 '22 06:10

danomatika


Fixed this magic Apple behaviour with following code:

static CGFloat const kListsLeading = 10.0;
static CGFloat const kListsAdditionalShift = 4.0;

//
// Fix Apple magic 4/3 koefficient
// http://stackoverflow.com/questions/20992950/ios7-font-size-change-when-create-nsattributedstring-from-html
//
static NSAttributedString *DecreaseFontSizeBecauseOfAppleMagic(NSAttributedString *astr) {
    NSMutableAttributedString *mastr = [astr mutableCopy];

    [mastr enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, astr.length) options:0 usingBlock:^(UIFont *_Nullable value, NSRange range, BOOL *_Nonnull stop) {
        if (value) {
            UIFont *font = [value fontWithSize:value.pointSize * 0.75];
            [mastr addAttribute:NSFontAttributeName value:font range:range];
        }
    }];

    [mastr enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, astr.length) options:0 usingBlock:^(NSParagraphStyle *_Nullable value, NSRange range, BOOL *_Nonnull stop) {
        if (value) {
            NSMutableParagraphStyle *style = [value mutableCopy];
            style.minimumLineHeight *= 0.75;
            if (style.firstLineHeadIndent == style.headIndent) {
                style.firstLineHeadIndent *= 0.75;
                style.headIndent *= 0.75;
            }
            else if (style.firstLineHeadIndent < kListsLeading) {
                CGFloat shift = (kListsLeading - style.firstLineHeadIndent);
                style.headIndent += shift + kListsAdditionalShift;
                style.firstLineHeadIndent = kListsLeading;
                NSMutableArray *tabs = [NSMutableArray array];
                NSInteger index = 0;
                for (NSTextTab *tab in style.tabStops) {
                    [tabs addObject:[[NSTextTab alloc] initWithTextAlignment:tab.alignment location:tab.location + shift + kListsAdditionalShift * (index ? 1 : 0) options:tab.options]];
                    index++;
                }
                style.tabStops = tabs;
            }
            style.tailIndent *= 0.75;
            [mastr addAttribute:NSParagraphStyleAttributeName value:style range:range];
        }
    }];

    return [mastr copy];
}
like image 24
k06a Avatar answered Oct 31 '22 07:10

k06a