iOS 如何全局修改项目字体

一. 引言

在产品或设计同学的走查过程中,经常会提出一个问题:在宽屏 iPhone 上,字体看起来好像变小了,需要进行适配。可能你会有点摸不着头脑------明明代码里写的都是 16pt,字体怎么会变小呢?

他们可能会说是屏幕分辨率高、屏幕宽度大之类的原因。先说结论:字体没有变小。在 iOS 里,字体的大小一直是 16pt,不会因为分辨率更高而变小。所谓"变小",其实是一种视觉错觉。

原因在于:随着屏幕宽度增加,内容布局相对变得更松散,人眼的感知就会觉得字体偏小。而 Retina 屏幕只是用更多像素去显示同样大小的文字,让字体更清晰,而不是更小。

不过他们的诉求应该还是确定的,就是希望把字体在宽手机上放大一点,所以我们还是要做一些调整。

二. iOS 字体渲染原理

在讲解解决方案之前呢,我们先看看 iOS 字体是如何渲染的。核心概念有两个:逻辑尺寸(pt)和物理像素(px)

2.1 pt 与 px 的区别

  • pt(point,点):iOS 中的逻辑尺寸单位。无论设备屏幕多大,16pt 的文字在逻辑上都是相同大小。
  • px(像素):屏幕的物理像素数量。Retina 屏幕用更多的像素去描绘同样大小的逻辑尺寸,从而让文字更清晰。

举个例子:

机型 屏幕宽度(pt) 屏幕像素(px) 字体 16pt 对应像素
iPhone 8 375pt 750px 32px(2x)
iPhone 15 Pro 393pt 1179px 48px(3x)

可以看到,逻辑尺寸(16pt)没有改变,只是物理像素更多了,字体更清晰而已。

2.2 为什么宽屏手机上字体"看起来小"?

即便逻辑尺寸没变,人的视觉仍然会有错觉,主要原因有两个:

1.屏幕宽度增加,布局变松散

  • 当屏幕宽度 > 375pt 时,原本紧凑的文字和控件之间的空间变大,文字在视觉上占比下降。
  • 结果就是"看起来比以前小"。

2.视觉感知规律

  • 人眼对大面积空间中的相对大小更敏感,小文字在宽屏上容易被周围空白"吞掉"。

所以,字体本身一直是 16pt,只是视觉上产生了"偏小"的错觉

iOS 字体大小由 pt 决定,不会因为分辨率高而变小,Retina 屏幕只是用更多像素描绘文字,让字体更清晰。

三. 如何全局修改字体大小?

在实际项目中,我们经常会遇到这样的问题:在宽屏 iPhone 上,原本写好的 16pt 字体看起来好像变小了。为了保证视觉一致性,我们需要在全项目范围内统一调整字体大小。不过,不同技术栈的项目实现方式有所不同,这与项目的前期建设密切相关。

下面我们从多种技术栈出发,讲解几种全局修改字体的方法。

3.1 Hook 字体方法(不推荐,但全局生效最快)

Hook 方法是通过 runtime 替换系统字体方法,让所有控件默认使用缩放后的字体。这样做的优点是:

  • 无论是 Objective-C、Swift,甚至第三方控件都可以生效
  • 不需要手动替换每个控件的字体

但是,这种方式也有明显缺点:

  • 系统内部控件字体也会被改,可能引发布局或显示问题
  • 第三方库控件可能出现意料之外的效果
  • 调试难度大,风险较高

代码实现如下:

objectivec 复制代码
#import <UIKit/UIKit.h>

@interface UIFont (Hook)

@end
objectivec 复制代码
#import "UIFont+Hook.h"
#import <objc/runtime.h>

#define kFontScale   ([UIScreen mainScreen].bounds.size.width > 375.0 ? 1.048 : 1.0)

@implementation UIFont (Hook)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        // systemFontOfSize:
        Method originalSystem = class_getClassMethod(self, @selector(systemFontOfSize:));
        Method swizzledSystem = class_getClassMethod(self, @selector(ph_systemFontOfSize:));
        method_exchangeImplementations(originalSystem, swizzledSystem);

        // boldSystemFontOfSize:
        Method originalBold = class_getClassMethod(self, @selector(boldSystemFontOfSize:));
        Method swizzledBold = class_getClassMethod(self, @selector(ph_boldSystemFontOfSize:));
        method_exchangeImplementations(originalBold, swizzledBold);

        // fontWithName:size:
        Method originalName = class_getClassMethod(self, @selector(fontWithName:size:));
        Method swizzledName = class_getClassMethod(self, @selector(ph_fontWithName:size:));
        method_exchangeImplementations(originalName, swizzledName);
    });
}

+ (UIFont *)ph_systemFontOfSize:(CGFloat)fontSize {
    return [self ph_systemFontOfSize:(fontSize * kFontScale)];
}

+ (UIFont *)ph_boldSystemFontOfSize:(CGFloat)fontSize {
    return [self ph_boldSystemFontOfSize:(fontSize * kFontScale)];
}

+ (UIFont *)ph_fontWithName:(NSString *)fontName size:(CGFloat)fontSize {
    return [self ph_fontWithName:fontName size:(fontSize * kFontScale)];
}

@end

3.2 Objective-C 项目常用方法:宏定义

在纯 OC 项目中,最常见、可控的做法是使用宏定义。例如我们项目中定义了如下宏:

objectivec 复制代码
#define kFontScale   ([UIScreen mainScreen].bounds.size.width > 375.0 ? 1.048 : 1.0)
#define kSystemFont(x)   [UIFont systemFontOfSize:(x * kFontScale)]
#define kBoldFont(x)     [UIFont boldSystemFontOfSize:(x * kFontScale)]
#define kNumberFont(x)   [UIFont bebasFontOfSize:(x * kFontScale)]

使用方式非常简单:

objectivec 复制代码
label.font = kSystemFont(16);
button.titleLabel.font = kBoldFont(18);

这种方式的优点是:

  • 简单明了,统一管理
  • 易于维护和修改比例

缺点是:

  • 需要在项目中统一替换原来的 systemFontOfSize 调用

总的来说,这是 OC 项目中最稳妥的全局字体适配方案。

3.3 Swift 项目统一方法

在 Swift 项目中,可以封装一个统一的字体 Helper,或者分了,例如我们的 ZMFontHelper:

Swift 复制代码
/// 设置字体
/// - Parameters:
///  - fontType: 字体类型
///  - fontSize: 字体大小
///  - fontWeight: 字体粗细
/// - Returns: UIFont
public class func font(fontType: ZMFontType = .system,
                       fontSize: CGFloat,
                       fontWeight: UIFont.Weight = .regular) -> UIFont {
    let scale: CGFloat = UIScreen.main.bounds.size.width > 375 ? 1.048 : 1.0
    let finalSize = fontSize * scale
    switch fontType {
    case .system:
        return UIFont.systemFont(ofSize: finalSize, weight: fontWeight)
    }
}

使用方式:

Swift 复制代码
label.font = ZMFontHelper.font(fontSize: 16)
button.titleLabel?.font = ZMFontHelper.font(fontSize: 18, fontWeight: .bold)

优点:

  • 面向对象,易于扩展
  • 可以兼顾 OC + Swift 混合项目(通过桥接)
  • 易于统一调整字体比例

3.4 SwiftUI 项目

在 SwiftUI 中,推荐使用自定义 ViewModifier 来实现全局字体适配:

Swift 复制代码
struct ScaledFont: ViewModifier {
    var size: CGFloat
    var scaledSize: CGFloat {
        UIScreen.main.bounds.width > 375 ? size * 1.048 : size
    }
    func body(content: Content) -> some View {
        content.font(.system(size: scaledSize))
    }
}

extension View {
    func scaledFont(_ size: CGFloat) -> some View {
        self.modifier(ScaledFont(size: size))
    }
}

使用方式:

Swift 复制代码
Text("Hello World")
    .scaledFont(16)

优点:

  • 全局统一,代码优雅
  • 易于维护和扩展
  • 完美契合 SwiftUI 生态

3.5 项目中每个地方都单独写字体

如果项目中每个控件都是单独设置字体(没有统一规范),目前只能通过搜索替换的方式逐步改成统一方法或宏/Helper。

  • 建议在后续项目中尽量使用统一方法
  • 避免重复手动修改,提高可维护性

四. 结语

在 iOS 项目中,字体大小并不会因为屏幕分辨率高而变小。所谓在宽屏手机上字体"变小",只是视觉错觉:屏幕宽度增加、布局相对变得更松散,导致人眼感知上觉得字体偏小。

理解这一点之后,我们就可以科学地在全项目范围内统一调整字体大小。无论是使用宏定义、Swift Helper、SwiftUI Modifier,还是在特殊情况下采用 Hook 方法,每种方案都有其适用场景。关键在于选择与项目技术栈和维护需求相匹配的方案,从而既满足设计师在大屏设备上的视觉需求,又保证项目的可维护性和一致性。

最终,全局字体适配不是简单地放大字号,而是基于 iOS 渲染原理和视觉平衡的合理调整,让用户在不同机型上都能获得最佳阅读体验。

相关推荐
专注VB编程开发20年7 小时前
SetWinEventHook监控事件频率最多的事件和回调过程详解
microsoft·hook
岁月向前15 小时前
Jenkins实现iOS自动化打包
ios
2501_915909062 天前
手机崩溃日志导出的工程化体系,从系统级诊断到应用行为分析的多工具协同方法
android·ios·智能手机·小程序·uni-app·iphone·webview
2501_915106322 天前
App HTTPS 抓包实战解析,从代理调试到真实网络流量观察的完整抓包思路
网络协议·http·ios·小程序·https·uni-app·iphone
要站在顶端2 天前
iOS自动化测试全流程教程(基于WebDriverAgent+go-ios)
开发语言·ios·golang
2501_916008892 天前
深入理解 iPhone 文件管理,从沙盒结构到开发调试的多工具协同实践
android·ios·小程序·https·uni-app·iphone·webview
腾讯云qcloud07552 天前
腾讯位置商业授权iOS 轨迹SDK
macos·ios·cocoa
2501_916007472 天前
没有 Mac,如何在 Windows 上架 iOS 应用?一套可落地的工程方案
android·macos·ios·小程序·uni-app·iphone·webview
2501_915106322 天前
uni-app 上架 iOS 的完整实践,从跨端开发到稳定提交的工程路径
android·ios·小程序·uni-app·cocoa·iphone·webview
2501_916007472 天前
HTTPS工作原理与重要性:全面安全指南
网络协议·安全·ios·小程序·https·uni-app·iphone