34

NSDateFormatters の作成が「高価」であることはよく知られてます

Apple のData Formatting Guide (2014-02 更新) でさえ、次のように述べています。

日付フォーマッタの作成は安価な操作ではありません。フォーマッタを頻繁に使用する可能性が高い場合は、通常、複数のインスタンスを作成して破棄するよりも、単一のインスタンスをキャッシュする方が効率的です。1 つの方法は、静的変数を使用することです。

しかし、そのドキュメントはswiftで実際には最新ではないようであり、フォーマッターのキャッシュに関する最新のNSDateFormatterクラスリファレンスでもそれについて何も見つけることができないので、それはobjective-cの場合と同じくらいswiftの場合と同じくらい高価であるとしか思えません.

多くの情報源は、コントローラーやビューなど、それを使用するクラス内でフォーマッターをキャッシュすることを提案しています。

日付ピッカーを保存するためにシングルトン クラスをプロジェクトに追加するのが便利なのか、それとも「安価」なのかと思っていたので、もう一度作成する必要はありません。これは、アプリ内のどこでも使用できます。複数の日付ピッカーを含む複数の共有インスタンスを作成することもできます。たとえば、日付を表示するための日付ピッカーと時間表記のための日付ピッカーがあります。

class DateformatterManager {
    var formatter = NSDateFormatter()

    class var dateFormatManager : DateformatterManager {
        struct Static {
            static let instance : DateformatterManager = DateformatterManager()
        }
        // date shown as date in some tableviews
        Static.instance.formatter.dateFormat = "yyyy-MM-dd"
        return Static.instance
    }

    class var timeFormatManager : DateformatterManager {
        struct Static {
            static let instance : DateformatterManager = DateformatterManager()
        }
        // date shown as time in some tableviews
        Static.instance.formatter.dateFormat = "HH:mm"
        return Static.instance
    }

    // MARK: - Helpers
    func stringFromDate(date: NSDate) -> String {
        return self.formatter.stringFromDate(date)
    }
    func dateFromString(date: String) -> NSDate? {
        return self.formatter.dateFromString(date)!
    }
}

// Usage would be something like: 
DateformatterManager.dateFormatManager.dateFromString("2014-12-05")

別の同様のアプローチは、シングルトンを 1 つだけ作成し、必要に応じてフォーマットを切り替えることです。

class DateformatterManager {
    var formatter = NSDateFormatter()

    var dateFormatter : NSDateFormatter{
        get {
            // date shown as date in some tableviews
            formatter.dateFormat = "yyyy-MM-dd"
            return formatter
        }
    }

    var timeFormatter : NSDateFormatter{
        get {
            // date shown as time in some tableviews
            formatter.dateFormat = "HH:mm"
            return formatter
        }
    }

    class var sharedManager : DateformatterManager {
        struct Static {
            static let instance : DateformatterManager = DateformatterManager()
        }
        return Static.instance
    }

    // MARK: - Helpers
    func dateStringFromDate(date: NSDate) -> String {
        return self.dateFormatter.stringFromDate(date)
    }
    func dateFromDateString(date: String) -> NSDate? {
        return self.dateFormatter.dateFromString(date)!
    }
    func timeStringFromDate(date: NSDate) -> String {
        return self.timeFormatter.stringFromDate(date)
    }
    func dateFromTimeString(date: String) -> NSDate? {
        return self.timeFormatter.dateFromString(date)!
    }
}

// Usage would be something like: 
var DateformatterManager.sharedManager.dateFromDateString("2014-12-05")

それらのどちらかが良いアイデアでしょうか、それとも恐ろしいアイデアでしょうか? また、フォーマットの切り替えにも費用がかかりますか?

更新: Hot LicksLorenzo Rossiが指摘しているように、フォーマットを切り替えることはおそらくあまり良い考えではありません (スレッドセーフではなく、再作成と同じくらいコストがかかります..) 。

4

8 に答える 8

0

スウィフトの例

@Mobile Ben の回答に基づく: これは単純な Swift シングルトンの例です。

class YourDateFormatter {

    // MARK: - Properties

    static let sharedFormatter = YourDateFormatter()
    /// only date format
    private let dateFormatter: NSDateFormatter
    /// only time format
    private let timeFormatter: NSDateFormatter

    // MARK: - private init

    private init() {

        // init the formatters

        dateFormatter = NSDateFormatter()
        timeFormatter = NSDateFormatter()

        // config the format

        dateFormatter.dateStyle = .MediumStyle
        dateFormatter.timeStyle = .NoStyle
        dateFormatter.doesRelativeDateFormatting = true

        timeFormatter.dateStyle = .NoStyle
        timeFormatter.timeStyle = .MediumStyle

    }

    // MARK: - Public 

    func dateFormat(date: NSDate) -> String {
        return dateFormatter.stringFromDate(date)
    }

    func timeFormat(date: NSDate) -> String {
        return timeFormatter.stringFromDate(date)
    }

    func dateTimeFormat(date: NSDate) -> String {
        let dateFormat = self.dateFormat(date)
        let timeFormat = self.timeFormat(date)

        return dateFormat + " - " + timeFormat
    }
}
于 2016-02-29T08:57:18.570 に答える
0

また、例を提供してMobile Benの回答を拡張したいと思います。

import Foundation

public class DateFormatter : NSDateFormatter{

  public class func sharedFormatter() -> NSDateFormatter {
    // current thread's hash
    let threadHash = NSThread.currentThread().hash
    // check if a date formatter has already been created for this thread
    if let existingFormatter = NSThread.currentThread().threadDictionary[threadHash] as? NSDateFormatter{
      // a date formatter has already been created, return that
      return existingFormatter
    }else{
      // otherwise, create a new date formatter 
      let dateFormatter = NSDateFormatter()
      // and store it in the threadDictionary (so that we can access it later on in the current thread)
      NSThread.currentThread().threadDictionary[threadHash] = dateFormatter
      return dateFormatter

    }

  }

}

これはライブラリで使用されるため、public修飾子が全体に表示されます。

于 2016-03-11T11:06:17.157 に答える