Как стать автором
Обновить

Комментарии 9

  1. "Ограничения"
    Я не сразу врубился о каких ограничениях идёт речь...

API функции не очень понятен. Почему офсеты optional, но имеют дефолтное значение 0, а не nil? Предполагается, что по-умолчанию subview должна растягиваться на всю площадь родителя? На моей практике это очень редкий юзкейс, чтобы быть дефолтом.


func test(value: CGFloat? = 0) {
    if let value = value {
        print("value is", value)
    }
}

test() // value is 0
test(value: nil) // no output

Для меня подобное поведение было бы неожиданным, я бы ожидал ровно обратного: по-умолчанию не происходит ничего, но если я задал офсет (в том числе нулевой) – то он применяется.


Про саму целесообразность введения подобного расширения можно порассуждать отдельно.

теперь врубился, статья-перевод

2: ISO8601DateFormatter.init()


By default, a formatter is initialized to use the GMT time zone, the RFC 3339 
standard format ("yyyy-MM-dd'T'HH:mm:ssZZZZZ"), and the following options: 
withInternetDateTime, withDashSeparatorInDate, withColonSeparatorInTime, and withTimeZone.

Если выкинуть доли секунды из этого формата, то можно пользоваться без дополнительной конфигурации. Если же очень сильно хочется знать время до микросекунды, то:


let f = ISO8601DateFormatter()
f.formatOptions = [.withInternetDateTime,
                   .withColonSeparatorInTime,
                   .withDashSeparatorInDate,
                   .withColonSeparatorInTimeZone,
                   .withFractionalSeconds]
f.date(from: "2021-04-03T14:00:00.000Z") // "Apr 3, 2021 at 3:00 PM"

3:


func urls(in s: String) -> [URL] {
    // never ever fails, and if it does you are in a bigger trouble
    let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
    let matches = detector.matches(in: s, options: [], range: NSMakeRange(0, s.utf16.count))
    return matches.compactMap { $0.url }
}

urls(in: "hi https://habr.com, bye https://stackoverflow.com")
// [https://habr.com, https://stackoverflow.com]

4: UIStackView


/* Removes a subview from the list of arranged subviews without removing it as
 a subview of the receiver.
    To remove the view as a subview, send it -removeFromSuperview as usual;
 the relevant UIStackView will remove it from its arrangedSubviews list
 automatically.
 */
open func removeArrangedSubview(_ view: UIView)

Судя по документации, достаточно просто: stackView.subviews.forEach { $0.removeFromSuperview() }.


Более того, строка NSLayoutConstraint.deactivate($0.constraints) очень напрягает. Зачем это делать? Эта строка мало того, что не сделает ничего полезного в плане взаимоотношений со StackView, так ещё и уничтожит все остальные существующие constraints (относящиеся к её subviews например, или же constraints на ширину или высоту).

5: "Должны быть", но всё равно Optional


Это одна из тех особенностей, которые должны быть включены в Bundle

Раз должны, то


extension Bundle {
    var releaseVersionNumber: String {
        infoDictionary!["CFBundleShortVersionString"] as! String
    }
    var buildVersionNumber: String {
        infoDictionary!["CFBundleVersion"] as! String
    }
}

6: Криволинейная логика


Здесь все довольно прямолинейно

"Сначала пытаемся отнять год одним способом, но если не получилось, то и второй сойдёт."


Почему же всегда не делать component(.year, from: Date()) - 1? Очень опасная функция, потому что она всегда возвращает предыдущий год на текущий момент времени. Мне было бы страшно вызывать её в каком-нибудь асинхронном коде 31 декабря в 23:59. Имхо предыдущий год можно брать только из какой-то конкретной даты, чтобы был как явный инпут, так и понятно откуда взявшийся результат.

9: Узкое расширение


Перед тем, как добавить какой-нибудь extension бывает полезно сделать cmd+click на свойстве, и понять, откуда оно взялось. В данном случае, можно было бы вместо UIViewController расширить UITraitEnvironment:


extension UITraitEnvironment {
    var dark: Bool {
        traitCollection.userInterfaceStyle == .dark
    }
}

и тогда расширение станет доступным и в UIView тоже.

> Создание объекта Date из строки в часовом поясе UTC
Вредный код. Форматтеры нужно кешировать. Их создание медленно. Настолько медленно, что вызывает лаг при прокрутке, если в ячейках таблицы содержится дата.

Обычно я кладу кешированный форматтер в `NSThread.currentThread.threadDictionary`
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.