Комментарии 9
- "Ограничения"
Я не сразу врубился о каких ограничениях идёт речь...
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
тоже.
Вредный код. Форматтеры нужно кешировать. Их создание медленно. Настолько медленно, что вызывает лаг при прокрутке, если в ячейках таблицы содержится дата.
Обычно я кладу кешированный форматтер в `NSThread.currentThread.threadDictionary`
10 расширений Swift, которые мы используем на Livefront