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

如何让autoupdatingCurrentCalendar获取的时区随系统设置实时更新?

解决macOS下autoupdatingCurrentCalendar时区不随系统更新的问题

你的代码问题在于主线程RunLoop没有运行,导致autoupdatingCurrentCalendar无法接收系统时区变化的通知,也就不会更新内部状态。sleep()会完全阻塞线程,Cocoa的通知机制和自动更新逻辑依赖RunLoop处理事件,所以必须让RunLoop正常运转。

方法一:在循环中运行RunLoop替代sleep

修改代码,用runUntilDate:让RunLoop处理1秒内的事件,同时实现定时打印:

#include <Foundation/Foundation.h>

int main() {
    @autoreleasepool {
        while (1) {
            const char *tz = [[[[NSCalendar autoupdatingCurrentCalendar] timeZone] name] UTF8String];
            printf("%s\n", tz);
            
            // 让RunLoop运行1秒,处理系统通知和事件
            NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:1.0];
            [[NSRunLoop currentRunLoop] runUntilDate:timeout];
        }
    }
    return 0;
}

方法二:监听时区变化通知(更高效)

注册NSSystemTimeZoneDidChangeNotification通知,只在时区实际变化时打印更新,同时保持RunLoop运行:

#include <Foundation/Foundation.h>

void handleTimeZoneChange(NSNotification *_Nonnull note) {
    const char *tz = [[[[NSCalendar autoupdatingCurrentCalendar] timeZone] name] UTF8String];
    printf("时区已更新:%s\n", tz);
}

int main() {
    @autoreleasepool {
        // 注册时区变化通知
        [[NSNotificationCenter defaultCenter] addObserverForName:NSSystemTimeZoneDidChangeNotification
                                                          object:nil
                                                           queue:[NSOperationQueue mainQueue]
                                                      usingBlock:^(NSNotification *note) {
                                                          handleTimeZoneChange(note);
                                                      }];
        
        // 打印初始时区
        const char *initialTz = [[[[NSCalendar autoupdatingCurrentCalendar] timeZone] name] UTF8String];
        printf("初始时区:%s\n", initialTz);
        
        // 启动主RunLoop,保持程序运行并处理事件
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

核心原因解释

autoupdatingCurrentCalendar的动态更新依赖Cocoa的通知机制:当系统时区变化时,系统会发送NSSystemTimeZoneDidChangeNotification,日历对象收到通知后才会同步最新设置。你的原代码用sleep()阻塞线程,RunLoop无法处理任何事件,自然接收不到通知,日历对象也就不会更新。

另外,代码中必须加上@autoreleasepool,否则Foundation对象会产生内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:26:11