UITableView的cellForRowAt中DateFormatters的使用优化及相关疑问
日期格式化与UITableView性能相关问题
我有一个包含多个cell的UITableView,需要将从API获取的原始日期字符串(格式为yyyy-MM-dd'T'HH:mm:ssX)转换为易读格式MMMM dd, yyyy 'at' hh:mm a展示。目前通过调用convertToDate函数实现转换,已知DateFormatter创建成本较高,结合下方代码,希望解答以下问题:
注:我在UITableView的
cellForRowAt方法中调用convertToDate函数
- 创建单例类维护唯一
DateFormatter实例是否为最佳实践? - 创建并发
DispatchQueue保证DateFormatter线程安全是否合理? - 在
cellForRowAt中调用该带并发处理的方法是否会导致列表滑动卡顿? - 有没有处理/创建
DateFormatter的标准参考资料?
示例代码
下方代码可将2023-12-22T13:17:27Z转换为December 22, 2023 at 01:17 PM
import Foundation class DateUtils { static let shared = DateUtils() let dateFormatter = DateFormatter() // Date formatter are not thread safe and adding this to a concurrent queue makes if safer. // For table views cells this may have minimal impact and needs to have performance tested in different cases where used. private let dateFormatterQueue = DispatchQueue(label: "com.example.dateformatter", attributes: .concurrent) private init(){} func convertToDate(from date: String, with format: String = "yyyy-MM-dd'T'HH:mm:ssX", to: String = "MMMM dd, yyyy 'at' hh:mm a") -> String? { var formattedDate: String? dateFormatter.dateFormat = format guard let date = dateFormatter.date(from: date) else { return nil } dateFormatter.dateFormat = to dateFormatterQueue.sync { formattedDate = dateFormatter.string(from: date) } return formattedDate } }
问题解答
1. 创建单例类维护唯一DateFormatter实例是否为最佳实践?
是,但有前提。DateFormatter的创建和初始化成本确实很高,复用单例能避免重复创建带来的性能损耗。不过要注意:
- 若需同时处理多种固定格式的日期,更优方案是在单例中维护多个
DateFormatter实例(每个对应一种格式),而非反复修改同一个实例的dateFormat——反复修改格式会引入额外开销,还可能因线程问题导致格式混乱。 - 单例必须保证线程安全,不能在多线程环境下直接修改或调用其方法。
2. 创建并发DispatchQueue保证DateFormatter线程安全是否合理?
你的实现存在隐患,并发队列配合sync调用无法完全保证安全。正确思路是:
DateFormatter并非线程安全,任何对它的读写操作都必须在同一个串行队列中执行,或加锁保护。- 你的代码中先修改
dateFormat再执行转换,属于读写混合操作,用并发队列+sync会有线程竞争风险。更稳妥的方式是用串行队列包裹所有对DateFormatter的操作,确保同一时间只有一个线程访问它。
3. 在cellForRowAt中调用该带并发处理的方法是否会导致列表滑动卡顿?
大概率会。cellForRowAt在主线程执行,代码中的sync调用会阻塞主线程等待队列任务完成。若列表滑动速度快,大量sync调用会让主线程等待,直接引发掉帧、卡顿。
正确做法是提前格式化日期:
- 在API数据解析完成后,后台线程批量处理所有日期的格式化,将结果存入数据模型,
cellForRowAt直接读取格式化好的字符串展示。 - 若必须在
cellForRowAt中处理,需把格式化操作放到后台线程异步执行,完成后切回主线程更新cell,避免阻塞主线程。
4. 有没有处理/创建DateFormatter的标准参考资料?
苹果官方文档有明确的性能与线程安全说明:
- 线程安全:明确指出
DateFormatter非线程安全,所有访问必须在同一线程,或通过同步机制保护。 - 性能优化:推荐复用
DateFormatter实例,避免频繁创建;若需多种格式,维护多个实例而非反复修改格式。 - 此外,苹果WWDC的性能相关session(如UI性能、后台处理主题)也提到过
DateFormatter的优化方案,核心思路是减少创建次数、避免主线程阻塞。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

