Подтвердить что ты не робот

Создание NSDateFormatter в Swift?

Я новичок в быстрой и очень незнакомой с Objective-C. Может ли кто-нибудь помочь мне преобразовать это в Свифт? Я получил этот код от лучших методов IOS от Ray Wenderlich - http://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Где бы вы поместили этот код? Пойдет ли он в файл класса, полный глобальных переменных?

- (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;
}
4b9b3361

Ответ 1

  • Если вы действительно ищете прямой аналог метода в своем вопросе, в Swift 3 вы можете сделать что-то вроде:

    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)
        }
    }
    

    Или в Swift 2:

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

    Свойства static, такие как глобальные, имеют поведение dispatch_once для значений по умолчанию. Для получения дополнительной информации см. Обсуждение dispatch_once в конце записи Файлы и инициализация в блоге Apple Swift.

  • Что касается лучших практик в форматах даты, я бы предложил:

    • Да, разумно не излишне создавать и уничтожать форматировщики, которые вам, скорее всего, понадобятся. В видеоролике WWDC 2012 Производительность приложений iOS: отзывчивость Apple явно поощряет нас к

      • Кэш одного формата для формата даты,

      • Добавить наблюдателя для NSLocale.currentLocaleDidChangeNotification в Swift 3 (NSCurrentLocaleDidChangeNotification в Swift 2) через NSNotificationCenter и очистить/сбросить кешированные форматиры, если это произойдет; и

      • Обратите внимание, что сброс формата столь же дорог, как и воссоздание, поэтому избегайте многократного изменения формата форматирования.

      Нижняя строка, повторное использование даты, когда это возможно, если вы используете один и тот же формат даты несколько раз.

    • Если вы используете NSDateFormatter для синтаксического анализа строк даты, которые должны быть обменены с веб-службой (или сохранены в базе данных), вы должны использовать локаль en_US_POSIX, чтобы избежать проблем с международными пользователями, которые не могут использовать григорианские календари, См. Apple Technical Q & A # 1480. (Или в iOS 10 и macOS 10.12 используйте ISO8601DateFormatter.)

      Но при использовании dateFormat с NSDateFormatter/DateFormatter используйте текущий язык для создания строк, которые будут представлены конечному пользователю, но используйте en_US_POSIX local при создании/синтаксическом анализе строк, которые будут использоваться внутри внутри приложения или для обмена с веб-службой.

    • Если строки даты форматирования для пользовательского интерфейса, локализуйте строки, избегая при этом использовать строковые литералы для dateFormat, если это возможно. Используйте dateStyle и timeStyle, где можете. И если вы должны использовать пользовательский dateFormat, используйте шаблоны для локализации ваших строк. Например, вместо строчного кодирования E, MMM d в Swift 3 вы должны использовать dateFormat(fromTemplate:options:locale:):

      formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "EdMMM", options: 0, locale: Locale.current)
      

      Или в Swift 2, dateFormatFromTemplate(_:options:locale:):

      formatter.dateFormat = NSDateFormatter.dateFormatFromTemplate("EdMMM", options: 0, locale: NSLocale.currentLocale())
      

      Это автоматически отобразит, например, "Mon, Sep 5" для пользователей США, но "Mon 5 Sep" для пользователей Великобритании.

    • NSDateFormatter теперь потокобезопасен для iOS 7 и более поздних версий и 64-разрядных приложений, работающих на macOS 10.9 и более поздних версиях.

Ответ 2

Как говорится в Rob, вы должны быть осторожны с производительностью, создающей DateFormatters, используя советы из этой сессии WWDC.

Я делаю это как расширения NSDate и NSDateFormatter (код протестирован в Swift 2.0):

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

extension NSDateFormatter {
    private 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()

Ответ 3

Я попытался применить метод Singleton, найденный здесь. Это создает синглтон, который может быть загружен различными форматами, которые вы используете в своем приложении. Например, вы можете получить доступ к нему в любом месте приложения с помощью 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"
    }

}

Ответ 4

Вы можете сделать это так и переместить NSDateFormatter и onceToken вне вашей функции. Затем вы можете сделать это, как в своем примере:

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, вы должны взглянуть на вопрос d ispatch_once singleton.