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

Xamarin.Forms中NSDate格式化触发ObjectDisposedException问题排查

问题:Unix时间戳格式化方法抛出ObjectDisposedException异常

我有一个将UnixTimestamp格式化为日期的方法如下:

public string ConvertDateTimeToDeviceShortDateFormat(double unixTimestamp)
{
   using (var dateInNsDate = NSDate.FromTimeIntervalSince1970(unixTimestamp))
   {
        using (var formatter = new NSDateFormatter())
        {
            formatter.TimeStyle = NSDateFormatterStyle.None;
            formatter.DateStyle = NSDateFormatterStyle.Short;
            formatter.Locale = NSLocale.CurrentLocale;

            return formatter.ToString(dateInNsDate);
        }
    }
}

该方法在Xamarin.Forms应用中每秒被调用一次,有时会抛出ObjectDisposedException异常,异常堆栈如下:

Xamarin Exception Stack:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Foundation.NSDate'.
  at ObjCRuntime.ThrowHelper.ThrowObjectDisposedException (System.Object o) <0x101ca8be0 + 0x00038> in <153620f857f54f9c9ab1e7a1e6853772#0f6f385f46b536c4b979ed569af516e5>:0
  at ObjCRuntime.NativeObjectExtensions.GetNonNullHandle (ObjCRuntime.INativeObject self, System.String argumentName) <0x101ca5d70 + 0x00077> in <153620f857f54f9c9ab1e7a1e6853772#0f6f385f46b536c4b979ed569af516e5>:0
  at Foundation.NSDateFormatter.ToString (Foundation.NSDate date) <0x101c1f920 + 0x00027> in <153620f857f54f9c9ab1e7a1e6853772#0f6f385f46b536c4b979ed569af516e5>:0

请问每次调用时释放NSDate对象是否存在问题?


问题分析与解决方案

核心问题

  1. NSDate无需手动释放:NSDate.FromTimeIntervalSince1970创建的对象由Xamarin的GC和iOS的ARC共同管理生命周期,手动用using语句提前释放会导致底层Native对象被销毁,而NSDateFormatter.ToString内部可能仍在访问该对象(即使代码看起来是同步执行,Xamarin绑定层可能存在延迟释放的情况),从而抛出ObjectDisposedException。

  2. NSDateFormatter重复创建性能低下:NSDateFormatter是重量级对象,每秒创建一次会大幅消耗系统资源,同时增加GC压力,甚至可能引发线程安全问题。

修复后的代码

// 全局缓存NSDateFormatter,避免重复创建
private static readonly NSDateFormatter _shortDateFormatter;

// 静态构造函数中初始化一次
static YourClassName()
{
    _shortDateFormatter = new NSDateFormatter();
    _shortDateFormatter.TimeStyle = NSDateFormatterStyle.None;
    _shortDateFormatter.DateStyle = NSDateFormatterStyle.Short;
    _shortDateFormatter.Locale = NSLocale.CurrentLocale;
}

public string ConvertDateTimeToDeviceShortDateFormat(double unixTimestamp)
{
    // 无需using包裹NSDate,由GC自动管理
    var dateInNsDate = NSDate.FromTimeIntervalSince1970(unixTimestamp);
    return _shortDateFormatter.ToString(dateInNsDate);
}

额外注意事项

  • 如果方法在多线程环境下调用,NSDateFormatter不是线程安全的,需要改用ThreadLocal<NSDateFormatter>来为每个线程单独缓存实例,避免并发访问问题。
  • 若需要适配系统语言或区域设置变化,需监听NSLocale.CurrentLocale的变化事件,重新初始化格式化器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:07:06