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

使用objc_msgSend_fpret()获取cpm属性返回NaN,控制台可见值却无法获取求助

问题分析与解决建议

Hey,刚好之前也踩过objc_msgSend系列函数的坑,来给你拆解下可能的原因和解决办法:

可能的问题根源

  • 类型不匹配:objc_msgSend_fpret是专门用来处理返回浮点基本类型(比如float、double)的消息发送,但如果你的cpm属性是NSNumber这类包装对象,直接用它就会因为类型解析错误返回NaN——毕竟它没法把对象指针解析成浮点数。
  • 调用约定或声明缺失:如果没有提前正确声明objc_msgSend_fpret的函数原型,编译器可能会错误处理返回值的传递逻辑(浮点返回值在部分架构下是通过专门的浮点寄存器传递的),导致拿到无效的NaN值。
  • SEL与实际getter不匹配:如果cpm属性有自定义getter方法(比如不是默认的-cpm),传错SEL也会导致调用失败,返回无意义的结果。

解决步骤

  1. 先确认cpm的实际类型
    先通过类的头文件或者runtime工具确认属性类型:

    • 如果是浮点基本类型(float/double):确保正确声明函数原型后再调用:
      #import <objc/message.h>
      // 提前声明函数原型,避免编译器报错
      extern double objc_msgSend_fpret(id self, SEL _cmd, ...);
      
      // 调用示例
      double cpmValue = objc_msgSend_fpret(yourTargetObject, @selector(cpm));
      
      注意:如果是float类型,可将返回值强转为float,适配对应类型。
    • 如果是NSNumber对象:不能用objc_msgSend_fpret,改用普通objc_msgSend获取对象再取值:
      NSNumber *cpmObj = ((NSNumber *(*)(id, SEL))objc_msgSend)(yourTargetObject, @selector(cpm));
      double cpmValue = [cpmObj doubleValue];
      
  2. 验证调用的SEL正确性
    打印属性的编码信息,确认getter方法名和你传入的SEL一致:

    objc_property_t property = class_getProperty([yourTargetObject class], "cpm");
    const char *attrs = property_getAttributes(property);
    NSLog(@"Property attributes: %s", attrs);
    

    比如编码里的G,cpm就表示getter是cpm,确保SEL和它完全对应。

  3. 用runtime动态适配类型(可选)
    如果不确定属性类型,可以通过属性编码动态选择调用的msgSend函数:

    objc_property_t property = class_getProperty([yourTargetObject class], "cpm");
    const char *attrs = property_getAttributes(property);
    NSString *attrStr = [NSString stringWithUTF8String:attrs];
    
    if ([attrStr containsString:@"f"] || [attrStr containsString:@"d"]) {
        // 浮点类型,用objc_msgSend_fpret
        double value = objc_msgSend_fpret(yourTargetObject, @selector(cpm));
        NSLog(@"cpm value: %f", value);
    } else if ([attrStr containsString:@"@"]) {
        // 对象类型,用objc_msgSend
        id valueObj = ((id (*)(id, SEL))objc_msgSend)(yourTargetObject, @selector(cpm));
        NSLog(@"cpm value: %@", valueObj);
    }
    

额外提示

控制台能看到属性值,说明属性本身是有正确赋值的,问题大概率出在objc_msgSend_fpret的使用场景和属性类型不匹配上,先从类型验证入手应该就能解决~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:10:17