如何让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
相关产品推荐
相关产品推荐

