Swift Best Practices которые не стыдно знать

от автора

Предисловие

Всем, по традиции, 404! Я собрал коллекцию и частью Swift Best Practices ( которые не только упростят вам жизнь, но и покажут ваш профессионализм на код ревью) поделюсь с вами в этой статье. Хочу чтоб ваш код был чистым, красивым и вы сами ему радовались!

Стартуем от сюда

0. Начнём с UserDefaults, не буду говорить как много я штук видел с ними. Вот небольшая хитрость, которую я использую, чтобы добиться согласованности ключей UserDefault в Swift (#function заменяется именем свойства в геттерах / сеттерах). Просто не забудьте написать хороший набор тестов, которые защитят вас от ошибок при изменении имен свойств.

extension UserDefaults {     var onboardingCompleted: Bool {         get { return bool(forKey: #function) }         set { set(newValue, forKey: #function) }     } }


1. Все знают оператор === с js но почему-то мало кто им пользуется в Swift. (Напомню: Оператор === позволяет проверить, являются ли два объекта одним и тем же экземпляром.) Очень полезно при проверке того, что массив содержит экземпляр в тесте:

protocol InstanceEquatable: class, Equatable {}  extension InstanceEquatable {     static func ==(lhs: Self, rhs: Self) -> Bool {         return lhs === rhs     } }  extension Enemy: InstanceEquatable {}  func testDestroyingEnemy() {     player.attack(enemy)     XCTAssertTrue(player.destroyedEnemies.contains(enemy)) }

2. Используя DispatchWorkItem, вы можете легко отменить отложенную асинхронную задачу GCD, если она вам больше не нужна:

let workItem = DispatchWorkItem {     // Ваш асинхронный код здесь }  // Вызовем его через 1 секунду DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: workItem)  // А теперь можем прекратить его работу(в любое удобное для нас время) workItem.cancel()

3. С map можно придумать много крутых штук, но эта одна из самых полезных. Используя map, вы можете преобразовать Optional значение в optional Result тип, просто передав его в enum.

enum Result<Value> {     case value(Value)     case error(Error) }  class Promise<Value> {     private var result: Result<Value>?          init(value: Value? = nil) {         result = value.map(Result.value)     } }

4. Последний на сегодня большой пример. Когда у меня есть 3 свойства или локальные переменные с одним и тем же префиксом, я обычно пытаюсь извлечь их в их собственный метод или тип. Таким образом я могу избежать массовых типов и методов, а также повысить удобочитаемость, не попадая в ловушку «преждевременной оптимизации».

До

public func generate() throws {     let contentFolder = try folder.subfolder(named: "content")      let articleFolder = try contentFolder.subfolder(named: "posts")     let articleProcessor = ContentProcessor(folder: articleFolder)     let articles = try articleProcessor.process()      ... }

После

public func generate() throws {     let contentFolder = try folder.subfolder(named: "content")     let articles = try processArticles(in: contentFolder)     ... }  private func processArticles(in folder: Folder) throws -> [ContentItem] {     let folder = try folder.subfolder(named: "posts")     let processor = ContentProcessor(folder: folder)     return try processor.process() }

Ну красиво, удобно, элегантно же, да? Да. Надеюсь был полезен, всем спасибо за прочтение. Красивого UI и чистого кода!

ссылка на оригинал статьи https://habr.com/ru/post/517220/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *