iOS 7和Helvetica Neue UltraLight:在旧版iOS中使用作为默认字体

10
据我所知,iOS 7 的默认字体是 Helvetica Neue UltraLight,与它的粗体前身相比要薄得多。为了提供一致的设计风格并使我的即将推出的应用在所有常见的 iOS 版本中看起来都一样,我想将 Helvetica Neue UltraLight 应用作应用程序的默认(主要)字体。
值得高兴的是,这个“新字体”自 iOS 5.0 版本就已经可用了,因此它已经受到早于 iOS 7 的版本的支持。不幸的是,我想到的唯一使用它的方法是在每个 UIView 的字体上手动调用 [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:size],这很繁琐且容易出现不一致性的错误。
所以我的问题是,你是如何处理这个设计变化的?

12
需要翻译的内容:One thing to consider - iOS 6 users want apps that look like iOS 6. iOS 7 users will want apps to look like iOS 7. Personally, I think your app should use a default iOS 6 font when run under iOS 6. Same with icons. But that is just one opinion.考虑一件事情- iOS 6 用户希望应用看起来像 iOS 6。iOS 7 用户将希望应用程序看起来像 iOS 7。个人认为,当在 iOS 6 下运行时,您的应用程序应该使用默认的 iOS 6 字体。图标也是如此。但这只是一个观点。 - rmaddy
4
如果整体"主题"允许,将iOS7的元素融入当前的iOS 6应用程序是个好主意。这样一来就不一定需要为6和7分别创建完全不同的版本,至少在大部分用户安装7之前是这样。 - brainray
1
@rmaddy:iOS7是一个巨大的飞跃。目前我认为iOS6用户会很幸运能够得到任何支持,更不用说一个专门针对iOS7运行但在iOS6中看起来正确的应用程序了。 - Kendall Helmstetter Gelner
1
不用道歉!我也很想有一个更好的解决方案。这种解决方案只是一种hack,但当没有其他解决方案时,hack就可以了。 - Léo Natan
2
从界面指南中得知:“应用程序在支持的所有iOS版本中使用相同的应用程序图标。如果您决定重新设计应用程序图标以适应iOS 7版本,则新图标应替换旧图标,即使应用程序在不同的iOS版本中显示不同的UI。”也许其他元素也应该采用相同的想法! - Peter V
显示剩余4条评论
4个回答

18

这里是Objective-C运行时的解决方案:

@interface UIFont (CustomSystemFont)

+ (UIFont *)ln_systemFontOfSize:(CGFloat)fontSize;
+ (UIFont *)ln_boldSystemFontOfSize:(CGFloat)fontSize;
+ (UIFont *)ln_italicSystemFontOfSize:(CGFloat)fontSize;

@end
@implementation UIFont (CustomSystemFont)

+ (void)load
{
    Method orig = class_getClassMethod([UIFont class], @selector(systemFontOfSize:));
    Method swiz = class_getClassMethod([UIFont class], @selector(ln_systemFontOfSize:));
    method_exchangeImplementations(orig, swiz);

    orig = class_getClassMethod([UIFont class], @selector(boldSystemFontOfSize:));
    swiz = class_getClassMethod([UIFont class], @selector(ln_boldSystemFontOfSize:));
    method_exchangeImplementations(orig, swiz);

    orig = class_getClassMethod([UIFont class], @selector(italicSystemFontOfSize:));
    swiz = class_getClassMethod([UIFont class], @selector(ln_italicSystemFontOfSize:));
    method_exchangeImplementations(orig, swiz);
}

+ (UIFont *)ln_systemFontOfSize:(CGFloat)fontSize
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
        //Call original implementation.
        return [self ln_systemFontOfSize:fontSize];
    }

    return [UIFont fontWithName:@"HelveticaNeue" size:fontSize];
}

+ (UIFont *)ln_boldSystemFontOfSize:(CGFloat)fontSize
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
        //Call original implementation.
        return [self ln_systemFontOfSize:fontSize];
    }

    return [UIFont fontWithName:@"HelveticaNeue-Medium" size:fontSize];
}

+ (UIFont *)ln_italicSystemFontOfSize:(CGFloat)fontSize
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
        //Call original implementation.
        return [self ln_systemFontOfSize:fontSize];
    }

    return [UIFont fontWithName:@"HelveticaNeue-Italic" size:fontSize];
}

@end
在这个例子中,我替换了三个系统字体方法,并测试系统版本是否为7或更高。如果是,我使用原始方法,否则返回我选择的字体(在这种情况下是Helvetica Neue UltraLight重量用于常规和斜体请求,以及Medium重量用于粗体请求)。
这对通过代码生成的所有内容都有效,包括系统创建的视图。但是它无法用于从Xib和Storyboard文件加载视图,因为字体已经硬编码在NIB文件本身中。使用字体选择器来选择所需的字体。

非常有趣。我的无知:我了解到每次创建UIFont对象时都会调用load方法。是谁或什么代码调用了这个方法?这是Objective-C的副作用吗? - zontar
当Objective C运行时加载类时,通常在应用程序启动期间(更具体地说,在iOS中加载动态库时)会调用load方法。 - Léo Natan
你可能想在类别上使用前缀,以防它们与 UIFont 的内部方法发生冲突。 - Zev Eisenberg
@LeoNatan 修复得非常好,谢谢!如果我们需要Helvetica的轻量版,您会推荐什么?systemFontOfSize:weight:仅适用于iOS 8.2及更高版本。 - Danik
@Danik 这并不是技术上正确的。systemFontOfSize:weight: 自 iOS 8.0 起就作为私有 API 可用。只要你的目标版本是 8.0 及以上,你就可以使用它。 - Léo Natan

11

为什么不直接使用外观 API 呢?

 [[UILabel appearance] setFont:[UIFont fontWithName:@"YourFontName" size:14.0]];

UIAppearance API


UIAppearance API

UILabelfont 属性没有标记为 UIAppearance 选择器。我认为这样不会起作用。 - rmaddy
2
如果您有需要不同字体大小的标签,那么它的效果并不是很好。这个解决方案只适用于简单的应用程序。 - CrimsonChris
它不起作用。异常抛出"NSInvalidArgumentException',原因:'+[UIFont systemFontOfSize:weight:]: 无法识别类别发送"。 - SerkanHocam

4

为什么不在UIFont上声明一个分类,以模仿动态类型的新方法(为了避免具体方法名称而不违反NDA)?


1
这实际上并没有回答问题 - 如何将应用程序的默认字体设置为“Helvetica Neue UltraLight”。目标不是模仿新的动态类型,而是设置默认字体。 - rmaddy
嗯,我认为它解决了每次使用“fontWithName:”都很繁琐和容易出错的部分。 - Adam Eberbach
你提到了要在某个类别中复制一些新方法。这如何告诉应用程序在整个应用程序中使用给定字体呢? - rmaddy
用[UIFont fontForTitles]替换[UIFont fontWithName:@"HelveticaNeue-UltraLight" size:size]是一种改进,不是吗?你至少可以通过更改样式类别来进行全局样式更改。 - Adam Eberbach

3

对于那些在故事板中寻找解决方案的人,我成功地在文本编辑器中打开了故事板文件并进行了搜索/替换。您必须捕捉每种要更改的字体类型(例如,粗体/斜体),但我能够通过替换以下内容将标准系统字体替换为HelveticaNeue UltraLight:

key="fontDescription" type="system"

使用

key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue"

对于加粗,您需要替换:

key="fontDescription" type="boldSystem"

我选择用同样的UltraLight字体替换我的粗体字,但对于那些想要“加粗”处理的人,可以选择“HelveticaNeue-Thin”。

在进行此操作之前,我建议使用版本控制或备份文件!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接