Быстрое переопределение по умолчанию Init Нет подкласса - PullRequest
1 голос
/ 15 января 2020

Можно ли переопределить инициализацию по умолчанию без создания подклассов?

Я хочу, чтобы к каждому экземпляру DateFormatter, созданному в моем приложении, был присоединен тот же locale. Прямо сейчас, при каждом создании экземпляра, я должен:

let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX"

Возможно ли, чтобы это происходило без необходимости выписывать локаль каждый раз? Я бы предпочел , а не создать подкласс DateFormatter, так как я чувствую, что это немного излишне

Спасибо!

Ответы [ 2 ]

4 голосов
/ 15 января 2020

Невозможно переопределить существующий метод класса, не разделив его на подклассы или не изменив исходный код (что, очевидно, невозможно сделать в случае встроенных типов).

Однако для вашего В конкретном случае c вы можете просто добавить переменную метода / stati c, которая возвращает DateFormatter спецификацию c для ваших нужд.

extension DateFormatter {
    static func usPosix() -> DateFormatter {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
        return dateFormatter
    }
}

И затем вместо вызова let dateFormatter = DateFormatter(), ты делаешь let dateFormatter = DateFormatter.usPosix()

1 голос
/ 15 января 2020

Хотя я лично НАСТОЯТЕЛЬНО советую против пьянства, это, безусловно, вариант здесь.

Сначала начните с создания собственной локали, которую вы хотите использовать в своем приложении:

extension DateFormatter {
    // Note the "@objc" here, this is necessary for altering the runtime logic
    @objc var swizzledLocale: Locale {
        return Locale(identifier: "en_US_POSIX")
    }
}

Далее вы захотите сообщить Swift, что всякий раз, когда к языку DateFormatter обращаются, вы хотите использовать вместо него новый swizzledLocale:

// get reference to the two getter methods for the properties you want to "switch"
let orig = #selector(getter: DateFormatter.locale)
let new = #selector(getter: DateFormatter.swizzledLocale)
let origMethod = class_getInstanceMethod(DateFormatter.self, orig)!
let newMethod = class_getInstanceMethod(DateFormatter.self, new)!
// performs the actual switch so that whenever "locale" is accessed in code, the returned value will be the value of "swizzledLocale"
method_exchangeImplementations(origMethod, newMethod)

И это все, что нужно сделать ! Теперь, когда вы обращаетесь к любому DateFormatter locale, возвращается Locale("en_US_POSIX").

Некоторые вещи, на которые следует обратить внимание: во-первых, это изменит ВСЕ экземпляры locale, а не только locale s, которые вы лично используете в своем собственном коде. То есть, если есть какой-либо внутренний код, который использует форматировщик locale, всегда будет использоваться en_US_POSIX. Во-вторых, второй блок кода (тот, который выполняет фактический перебор) должен вызываться ровно один раз; Посмотрите на это в блок dispatch_once, чтобы убедиться, что он запускается только один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...