在 Swift 中创建 NSDateFormatter?

Creating an NSDateFormatter in Swift?

我是 swift 的新手,对 Objective-C 非常陌生。有人可以帮我把它转换成 Swift 吗?我从 Ray Wenderlich 的最佳 iOS 实践中获得了这段代码 - http://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

你会把这段代码放在哪里?它会进入一个充满全局变量的 class 文件吗?

- (NSDateFormatter *)formatter {
    static NSDateFormatter *formatter;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _formatter = [[NSDateFormatter alloc] init];
        _formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; // twitter date format
    });
    return formatter;
}

你可以那样做,将 NSDateFormatteronceToken 移到你的函数之外。然后你可以像你的例子那样做:

var theFormatter:NSDateFormatter!
var token: dispatch_once_t = 0
func formatter() ->NSDateFormatter {
    dispatch_once(&token) {
        theFormatter = NSDateFormatter()
        theFormatter.dateFormat = "EEE MMM dd HH:mm:ss Z yyyy"
    }
    return theFormatter

}

但是作为David suggested, you should take a look at the dispatch_once singleton question.

我尝试应用发现的单例方法 here。这将创建一个单例,可以加载您在应用程序中使用的不同格式。例如,您可以使用 formatter.fromDateTime(myString)

在应用程序的任何位置访问它
let formatter = FormatterFormats()

class FormatterFormats {
    var dateTime: NSDateFormatter = NSDateFormatter()

    class var sharedInstance:FormatterFormats {
        return formatter
    }

    func fromDateTime(dateString: String) -> NSDate {
        return dateTime.dateFromString(dateString)!
    }

    init() {
        dateTime.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    }

}
  1. 如果你真的在寻找问题中方法的直接模拟,你可以这样做:

    class MyObject {
    
        // define static variable
    
        private static let formatter: DateFormatter = {
            let formatter = DateFormatter()
            formatter.dateFormat = "EEE MMM dd HH:mm:ss Z yyyy"
            return formatter
        }()
    
        // you could use it like so
    
        func someMethod(date: Date) -> String {
            return MyObject.formatter.string(from: date)
        }
    }
    

    static 属性,如全局变量,享有 dispatch_once 默认值的行为。有关详细信息,请参阅 Apple 的 Swift 博客中 Files and Initialization 条目末尾的 dispatch_once 讨论。

  2. 关于日期格式化程序的最佳实践,我建议:

    • 是的,谨慎的做法是不要不必要地创建和销毁您可能再次需要的格式化程序。在 WWDC 2012 视频 iOS App Performance: Responsiveness 中,Apple 明确鼓励我们

      • 为每个日期格式缓存一个格式化程序;

      • 通过 NotificationCenter 和 clearing/resetting 缓存格式化程序为 NSLocale.currentLocaleDidChangeNotification 添加观察者(如果发生这种情况);和

      • 请注意,重置格式与重新创建一样昂贵,因此请避免重复更改格式化程序的格式字符串。

      最重要的是,如果您重复使用相同的日期格式,请尽可能重复使用日期格式化程序。

    • 如果使用 DateFormatter 解析要与网络服务交换的日期字符串(或存储在数据库中),您应该使用 en_US_POSIX 区域设置以避免国际问题可能不使用公历的用户。参见 Apple Technical Q&A #1480 or the “Working With Fixed Format Date Representations” discussion in the DateFormatter documentation. (Or in iOS 10 and macOS 10.12, use ISO8601DateFormatter。)

      但是当 dateFormatDateFormatter 一起使用时,使用当前语言环境来创建要呈现给最终用户的字符串,但是当 creating/parsing 字符串时使用 en_US_POSIX 本地在应用程序内部使用或与网络服务交换。

    • 如果为用户界面格式化日期字符串,请尽可能避免使用 dateFormat 的字符串文字来本地化字符串。尽可能使用 dateStyletimeStyle。如果您必须使用自定义 dateFormat,请使用模板来本地化您的字符串。例如,在 Swift 3 和更高版本中,您可以使用 dateFormat(fromTemplate:options:locale:):

      而不是硬编码 E, MMM d
      formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "EdMMM", options: 0, locale: Locale.current)
      

      这将自动显示,例如,美国用户显示 "Mon, Sep 5",英国用户显示 "Mon 5 Sep"。

    • DateFormatter 现在在 iOS 7 及更高版本以及 64 位应用程序 运行 在 macOS 10.9 及更高版本上是线程安全的。

有关 Swift 2 个示例,请参阅 previous revision of this answer

正如 Rob 所说,您必须小心创建 DateFormatters 的性能,使用来自 WWDC session 的提示。

我这样做是作为 NSDate 和 NSDateFormatter 的扩展(在 Swift 2、3 和 4 中测试的代码):

extension NSDate {
    func PR2DateFormatterUTC() -> String {
        return NSDateFormatter.PR2DateFormatterUTC.stringFromDate(self)
    }
    //... more formats
}

extension NSDateFormatter {
    fileprivate static let PR2DateFormatterUTC: NSDateFormatter = {
        let formatter = NSDateFormatter()
        let timeZone = NSTimeZone(name:"UTC")
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        formatter.timeZone = timeZone
        return formatter
    }()
    //... more formats
}

用法:

    let dateStringUTC  = NSDate().PR2DateFormatterUTC()