You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native向Swift原生组件传递UIFont对象后值不匹配的问题求助

问题原因分析

你碰到的核心问题是React Native和iOS原生之间的桥接层不会自动把JS端的普通字典转换成UIFont对象。当你在RN端传递{name: "Arial", size: 15}这样的对象时,Objective-C的RCT_EXPORT_VIEW_PROPERTY默认没有内置这种结构到UIFont的转换逻辑,桥接层无法识别你的配置,就会自动 fallback 到iOS系统的默认字体(也就是你看到的.SFUI-Regular 14pt),所以你设置的字体和大小根本没被正确解析。

解决方案

下面提供两种可行的解决方式,你可以根据自己的需求选择:

方案一:手动解析字典(简单直接)

这种方式是把JS端传递的对象作为字典接收,在Swift端手动解析并创建UIFont:

  1. 修改Objective-C的属性暴露代码:
    把属性类型从UIFont改成NSDictionary:
@interface RCT_EXTERN_MODULE(RCTNativeSwiftViewManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(uiFontStyle, NSDictionary)
@end
  1. 更新Swift端的属性处理逻辑:
    将属性改为可选字典类型,在didSet中解析并创建字体:
@objc var uiFontStyle: NSDictionary? {
    didSet {
        guard let fontDict = uiFontStyle,
              let fontName = fontDict["name"] as? String,
              let fontSize = fontDict["size"] as? CGFloat else {
            // 处理无效输入,用默认字体兜底
            self.font = UIFont.systemFont(ofSize: 14)
            print("Invalid font parameters, using default font")
            return
        }
        
        // 尝试创建指定字体,不存在则用同字号的系统字体兜底
        if let targetFont = UIFont(name: fontName, size: fontSize) {
            self.font = targetFont
            print("Did set: ", targetFont)
        } else {
            print("Font \(fontName) not found, using system font with size \(fontSize)")
            self.font = UIFont.systemFont(ofSize: fontSize)
        }
    }
}

方案二:自定义桥接转换器(更优雅)

如果你希望保持UIFont作为属性类型,可以通过扩展RCTConvert来告诉桥接层如何将JS字典转换为UIFont:

  1. 创建RCTConvert的扩展文件:
    新建一个Objective-C文件(比如RCTConvert+UIFont.m),添加以下代码:
#import <React/RCTConvert.h>

@implementation RCTConvert (UIFont)

+ (UIFont *)UIFont:(id)json {
    if ([json isKindOfClass:[NSDictionary class]]) {
        NSString *fontName = [self NSString:json[@"name"]];
        CGFloat fontSize = [self CGFloat:json[@"size"]];
        
        // 优先使用指定字体,不存在则用同字号系统字体
        return [UIFont fontWithName:fontName size:fontSize] ?: [UIFont systemFontOfSize:fontSize];
    }
    // 输入无效时返回默认字体
    return [UIFont systemFontOfSize:14];
}

@end
  1. 保持原有的Objective-C属性暴露:
    还是用UIFont作为属性类型:
@interface RCT_EXTERN_MODULE(RCTNativeSwiftViewManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(uiFontStyle, UIFont)
@end
  1. 优化Swift端的属性定义:
    建议把属性改为可选类型,避免强制解包的风险:
@objc var uiFontStyle: UIFont? {
    didSet {
        if let validFont = uiFontStyle {
            self.font = validFont
            print("Did set: ", validFont)
        }
    }
}
额外注意事项
  • 确保你指定的字体在iOS系统中存在:比如Arial是iOS自带的,但如果是自定义字体,需要在Info.plist中添加Fonts provided by application项,把字体文件路径配置进去,否则会 fallback 到系统字体。
  • JS端传递的size必须是数字类型,桥接层会自动转换为iOS的CGFloat,如果传递字符串会导致解析失败。

内容的提问来源于stack exchange,提问作者stef000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 06:22:46