Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Under iOS13 (Beta 7) TimesNewRomanPSMT will be used instead of SFUI #1168

Closed
jingx23 opened this issue Aug 21, 2019 · 22 comments
Closed

Under iOS13 (Beta 7) TimesNewRomanPSMT will be used instead of SFUI #1168

jingx23 opened this issue Aug 21, 2019 · 22 comments

Comments

@jingx23
Copy link

jingx23 commented Aug 21, 2019

If you set DTDefaultFontFamily and DTDefaultFontName to iOS13 system font (family: .AppleSystemUIFont name: .SFUI-Regular) e.g. in initWithHTMLData:

NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:data options:@{ DTUseiOS6Attributes: @YES, DTDefaultFontFamily: [UIFont systemFontOfSize:[UIFont systemFontSize]].familyName, DTDefaultFontName : [UIFont systemFontOfSize:[UIFont systemFontSize]].fontName, DTDefaultFontSize : @([UIFont systemFontSize])} documentAttributes:nil];

you will get the following message:

CoreText performance note: Client called CTFontCreateWithName() using name ".SFUI-Regular" and got font with PostScript name "TimesNewRomanPSMT". For best performance, only use PostScript names when calling this API.

@jingx23 jingx23 changed the title Under iOS13 TimesNewRomanPSMT will be used instead of SFUI Under iOS13 (Beta 7) TimesNewRomanPSMT will be used instead of SFUI Aug 21, 2019
@yichengchen
Copy link

same problem here

@odrobnik
Copy link
Collaborator

What is the correct post script font name for San Francisco? This is the one you should use.

@yichengchen
Copy link

if we use

CTFontCreateWithName(UIFont.systemFont(ofSize: 10).fontName as CFString, 10, nil)

it log above error message and get error TimesNewRoman. When changing to follow method

 CTFontCreateWithFontDescriptor(UIFont.systemFont(ofSize: 10).fontDescriptor, 10, nil)

then we can return correct result. is there way to use fontDescriptor?

a bug feedback is sent to apple.

@yichengchen
Copy link

yichengchen commented Aug 30, 2019

@odrobnik The following is the feedback from apple. Maybe we should provide a way to pass UIFont directly or fontDescriptor as DTDefaultFont?

because we are adopting dynamic font, it's not suitable to hardcode the font name

This issue behaves as intended.

As mentioned in numerous WWDC sessions, dot-prefixed font names are not to be directly used.

I would also note that UIFont and CTFont are toll-free bridged, so they can be used interchangeably with casts.

Please update your feedback report to let us know if this is still an issue for you.

@odrobnik
Copy link
Collaborator

Why don't you specify the proper family name for San Francisco?

@jcaccavale-mdsol
Copy link

I used the PostScript Names SFProDisplay-Regular, SFProDisplay-Semibold, etc, which resolved my issue.

@yichengchen
Copy link

Why don't you specify the proper family name for San Francisco?

because we want to follow dynamic font or Dynamic Type. setting such as UIFont.preferredFont(forTextStyle: .subheadline). it may become bold or other type due to system settings.

it's ok for us to manually maintain an mapping table from ".SFUI-Regular"->"SFProDisplay-Regular" and Semibold etc and for different languages. But it just no pretty enough.

@fruitcoder
Copy link

I have the same problem as @yichengchen with supporting dynamic fonts. Is providing the postscript name also working for < iOS 13?

@yichengchen
Copy link

yichengchen commented Sep 9, 2019

I have the same problem as @yichengchen with supporting dynamic fonts. Is providing the postscript name also working for < iOS 13?

Have you come out with any solutions? I found that font would be different default font on different language. E.g: the PingFang in Chinese. also i can't find the postscript name of San Francisco

@jcaccavale-mdsol I tried CTFontCreateWithName("SFProDisplay-Semibold" as CFString, 20, nil) it return me

 <UICTFont: 0x7fdca6e0d510> font-family: "Helvetica"; font-weight: normal; font-style: normal;

look likes any wrong font name not start with a dot would return Helvetica, it's this really solve your problem?

@yichengchen
Copy link

I found we set .AppleSystemUIFont as DTDefaultFontName can avoid the above warning and get correct, but in DTHTMLElement.m line 148 UIFont *uiFont = [UIFont fontWithCTFont:font]; it return time's new roman back……

@fruitcoder
Copy link

Yeah I thought the post script names would solve the issue but we also noticed that it's actually Helvetica that's being rendered... For now we manually copied the font in our bundle and reference it by our custom name :(

@odrobnik
Copy link
Collaborator

Well, the problem is that we have no API that would allow you to set the font instance itself, but only to set a name. In DTHTMLAttributedStringBuilder.m:229 the _defaultFontDescriptor is initialized with the font name only. Then while parsing it keeps attaching updated versions of this font descriptor to tags.

What you need instead is to be able to provide a default font descriptor and make sure that the extra attributes which dynamic text adds to that are also preserved. Then to use CTFontCreateWithFontDescriptor to get the font. There are two kinds of font creation, a fast or a slow one and except for some exceptions, like Chinese characters. But the options of default font or default font family omit these extra parameters that dynamic text adds.

If somebody were to sponsor the creation of this functionality, I'd be happy to add it. You can email me at oliver@cocoanetics.com to inquire.

@odrobnik
Copy link
Collaborator

PS: Of course you can also implement this functionality yourself and provide a PR.

@phamanhvan24
Copy link

iOS 13 not support UIWebView

@odrobnik
Copy link
Collaborator

@phamanhvan24 please see #1169 - already addressed by a PR

@iOSDeveloperL
Copy link

for those who are wondering, here's a temporary workaround for this issue until there's fix in the library.

What I did was to use method swizzling and overwrite the library method with my own implementation.

+ (void)load {
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        Class originalClass = object_getClass([UIFont class]);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
        SEL originalSelector = @selector(fontWithCTFont:); // the DTCoreText method we're overriding
        SEL ourSelector = @selector(ourFontWithCTFont:); // our custom implementation
#pragma clang diagnostic pop

        Method originalMethod = class_getClassMethod(originalClass, originalSelector);
        Method swizzledMethod = class_getClassMethod(originalClass, ourSelector);

        method_exchangeImplementations(originalMethod, swizzledMethod);
    });
}
// .h file
@interface UIFont (OurFont_DTCoreText)
+ (UIFont *)ourFontWithCTFont:(CTFontRef)ctFont;
@end

// .m file
@implementation UIFont (OurFont_DTCoreText)
+ (UIFont *)ourFontWithCTFont::(CTFontRef)ctFont {
    CGFloat fontSize = CTFontGetSize(ctFont);
    UIFont *font = [UIFont systemFontOfSize:fontSize];
    return font;
}
@end

@dgattey
Copy link

dgattey commented Mar 7, 2020

Any ways to work around this without swizzling? Totally blocking me from using DTCoreText on iOS 13. The swizzling method also doesn't work if you have bold, italic, etc fonts.

@odrobnik
Copy link
Collaborator

I think you should also be able to specify a font name override for a combination of family and bold/italic flags:

setOverrideFontName:(NSString *)fontName forFontFamily:(NSString *)fontFamily bold:(BOOL)bold italic:(BOOL)italic

@odrobnik
Copy link
Collaborator

I believe that this has been addressed by a different way of finding a matching font.

bdotdub added a commit to bdotdub/DTCoreText that referenced this issue Nov 3, 2021
…uilder

* See Cocoanetics#1168 for
  reference
* Basically, using system fonts will yield a font family name that we
  cannot directly instantiate from.
* Instead, we need to use the font descriptor and create using that. This
  should be mutually exclusive with font family/name
bdotdub added a commit to bdotdub/DTCoreText that referenced this issue Nov 4, 2021
…uilder

* See Cocoanetics#1168 for
  reference
* Basically, using system fonts will yield a font family name that we
  cannot directly instantiate from.
* Instead, we need to use the font descriptor and create using that. This
  should be mutually exclusive with font family/name
@avium
Copy link

avium commented Dec 1, 2021

I know this issue was closed, but isn't there still an addressable problem here? It looks like a solution along the lines of @bdotdub's code changes in #1245 would still be welcome.

@odrobnik
Copy link
Collaborator

odrobnik commented Dec 1, 2021

@avium were you able that the PR doesn't break anything else? If I can find some time to verify that then I could try to merge it.

@odrobnik
Copy link
Collaborator

I've made two changes for this...

  1. if the font face name begins with . then it doesn't use CTFontCreateWithName any more, but instead searches for a matching descriptor.
  2. I re-implemented the Add ability to pass in a UIFontDescriptor for DTHTMLAttributedStringBuilder #1245 changes to work for iOS and macOS and not drag along a UIFontDescriptor any more. i.e. the option still works, but properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants