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

Apple Silicon设备上dispatch_time计算异常问题求助

dispatch_time 在Apple Silicon及iOS设备上的计算异常问题

我有一段在Intel Mac上可正常运行的Objective-C代码,但在搭载M1芯片的Mac设备上运行失败。代码如下:

dispatch_time_t now = dispatch_time(DISPATCH_TIME_NOW, 0);
dispatch_time_t delta = (uint64_t)(1 * NSEC_PER_SEC);
dispatch_time_t when = dispatch_time(now, delta);

NSLog(@"now: %llu", now);
NSLog(@"delta: %llu", delta);
NSLog(@"when: %llu", when);
NSLog(@"real delta: %llu", when-now);

运行后输出示例如下:

now: 1272914827933
delta: 1000000000
when: 1272938827933
real delta: 24000000

按照计算,1272914827933 + 1000000000 应等于1273914827933,而非1272938827933。为何该问题仅在部分Mac设备上出现?

补充说明:此问题在真实iPhone设备上同样存在。只需创建一个新的Objective-C Xcode项目,将代码粘贴到AppDelegate中并在手机上运行即可复现。


问题原因

你错误理解了dispatch_time函数的参数用法。第二个参数不是直接的纳秒偏移量,而是一个带符号的偏移值,且dispatch_time_t的底层存储格式在不同架构上有差异:

  • 在Intel(x86_64)架构上,dispatch_time_t直接存储纳秒时间戳,所以你的代码碰巧能得到预期结果;
  • 在Apple Silicon(arm64)架构以及iOS设备上,dispatch_time_t是一个复合结构:高几位标记时间类型(比如相对时间/绝对时间),低几位存储偏移值,直接用数值相加或相减完全不符合其设计逻辑。

正确的用法是,dispatch_time的第二个参数应该是相对于第一个参数的带符号偏移,如果要基于当前时间创建延迟,正确的写法是:

dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);

而不是先获取now再传入。另外,如果你需要计算时间差,应该使用dispatch_time的配套逻辑,或者将dispatch_time_t转换为绝对时间戳后再计算:

uint64_t nowAbs = dispatch_walltime(NULL, 0);
uint64_t whenAbs = dispatch_walltime(NULL, 1 * NSEC_PER_SEC);
NSLog(@"real delta: %llu", whenAbs - nowAbs);

总结

  • dispatch_time_t不是简单的64位纳秒数值,其内部格式依赖架构,不能直接做算术运算;
  • 不要将dispatch_time的返回值作为第一个参数再次传入该函数,这属于错误用法;
  • 跨架构的时间处理,应该使用dispatch_walltime来获取统一的绝对时间戳,或者使用NSDate等高层API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:35:16