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

По мере того, как мы приближаемся к WWDC 2022 и, возможно, к версии 4.0 SwiftUI, фреймворка, с которым мне посчастливилось играть почти столько же, сколько он существует, я подумал, что могу опубликовать небольшую коллекцию расширений, которые я использую снова и снова. . Я надеюсь, что некоторые из них войдут в следующий выпуск.

1. Скрыть

Это модификатор представления, который позволяет отображать или скрывать представления, которые обычно недоступны. Стоит отметить, что модификатор представления — очень полезный паттерн, который вам не мешало бы запомнить.

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

.modifier(Show(isVisible: condition))

Это работает хорошо, но, как вы заметите, освобождает место на view и вызывает перерисовку — так что это удар по производительности. Кроме того, вы всегда можете использовать вкладку opacity, чтобы получить аналогичный эффект. Он будет работать быстрее, но не освободит место, которое вы использовали.

2. Филиал

Этот модификатор, с которым я столкнулся, является идеальным решением для управления включением/исключением атрибутов.

extension View {
  @ViewBuilder
  func `if`<Transform: View>(_ condition: Bool, transform: (Self) ->  Transform) -> some View {
    if condition { transform(self) }
    else { self }
  }
}

Код, который вы используете таким образом, опять же с переменной, окрашенной в этом примере.

.if(colored) { view in
  view.background(Color.blue)
}

3. Печать

Если вы новичок в SwiftUI, первое, что вас зацепит, это print. Это может быть динозавр методов отладки, но они все еще преподают его в классах, и обнаружить, что вы не можете использовать его в представлениях SwiftUI, болезненно. Итак, этот фрагмент кода бесценен.

extension View {
    func Print(_ vars: Any...) -> some View {
        for v in vars { print(v) }
        return EmptyView()
    }
}

Это позволяет вам использовать подобный оператор в вашем коде.

self.Print("Inside ForEach", varOne, varTwo ...)

4. Задержка

Это только что изменилось в iOS15, и, хотя это не SwiftUI как таковой, это определенно то, что вы делаете в своем коде.

extension Task where Success == Never, Failure == Never {
  static func sleep(seconds: Double) async throws {
  let duration = UInt64(seconds * 1000_000_000)
  try await sleep(nanoseconds: duration)
  }
}

Конечно, код, который вы хотите запустить после задержки, должен следовать Task, который сам создает задержку.

Task { try! await Task.sleep(seconds: 0.5) }

5. PassThruSubjects

Когда я начал использовать Combine со SwiftUI, я обнаружил, что PassThroughSubjects очень полезный способ связать старое с новым. Я написал статью об их использовании с покупками в приложении, но они не идеальны, и я часто срабатываю более одного раза, когда вы отправляете их. Этот код может помочь вам решить эту проблему.

let changeColor = PassthroughSubject<Int,Never>()

Код, который вы используете, выглядит следующим образом:

.onReceive(signalButton
  .eraseToAnyPublisher()
  .throttle(for: .milliseconds(10), scheduler: RunLoop.main, latest: true))
{ value in
  if value == 2 {
    button2 = true
    levelColor = Color.red
  }
}

В данном случае с подпрограммой calling число, используемое здесь, позволяет мне назвать одну тему, чтобы я мог запускать несколько ветвей в одном и том же коде SwiftUI.

changeColor.send(3)

6. Подписки

Еще одна альтернатива запуску кода, хотя и не SwiftUI, — бесценный элемент, который я неоднократно использовал в своем коде SwiftUI. Вы настраиваете его с помощью этого кода:

let cameraGesture = PassthroughSubject<cameraActions,Never>()
var cameraSubscription:AnyCancellable? = nil

Затем используются два объявления combine следующим образом:

cameraSubscription = cameraGesture
  .eraseToAnyPublisher()
  .throttle(for: .milliseconds(10), scheduler: RunLoop.main, latest: true)
   .sink(receiveValue: { value in   
  // do something with the value                 
})

Отправив сообщение combine, как и раньше.

cameraGesture.send(._1orbitTurntable)

7. Таймер

publisher — отличный способ создать таймер. Я обнаружил, что использую его почти в каждом проекте, который придумываю.

let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

Вот код.

Примечание. У меня есть значение времени в переменной _ unused. Это, в отличие от send, работает более надежно, так как отправляет одно сообщение, а не кучу.

.onReceive(timer) { _ in
  // do something
}

8. Координаты/размер

Я никак не могу вспомнить, что я имел в виду, поэтому вот пример. Это также немного сложно, потому что размер, который он возвращает, является родительским, а не дочерним, в котором вы его используете.

Таким образом, вы обычно используете его в качестве фона. Вот как вернуть размер представления с помощью этой команды:

.background(returnSize())

9. Строки атрибутов

Супер полезное расширение, которое я наткнулся на Stack Overflow; он применяется к атрибутам в объектах Text iOS 15.

Вы можете использовать приведенные выше фрагменты следующим образом:

Text("GAME OVER") { $0.kern = CGFloat(2) }

С такого рода параметрами вы можете подробно дополнить эту статью.

10. Любой вид

Далее идет исправление для этого сообщения SwiftUI, жалующегося на несовпадающие представления. Хотя я обычно не рекомендую использовать AnyView, иногда кажется, что другого решения просто нет.

extension View {
    func eraseToAnyView() -> AnyView {
        AnyView(self)
    }
}

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

11. Подстрочный индекс

Это расширение позволяет вам индексировать строку; он использует стандарт, который существует уже давно

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

let word = "Start"
  for i in 0..<word.length {
    print(word[i])
}

12. Обнаружение сотрясения

Я постоянно ищу этот код Google. Кто помнит эту последовательность?

Вы можете создать расширение следующим образом:

.onShake {
  print("stop it shaking")
}

13. Сделайте снимок вида

Этот драгоценный камень взят с веб-сайта HWS; это отличный источник всего, что происходит на скорую руку.

Вы можете использовать его следующим образом:

let image = textView.snapshot().ignoresSafeArea

14. Сохранение/загрузка изображений

Если вы нашли это на портале разработчиков Apple; это пригодится.

В расширении вы можете использовать такой код:

@State private var image = UIImage(systemName: "xmark")!
private var url: URL {  let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)  return paths[0].appendingPathComponent("image.jpg")}
var body: some View { 
Image(uiImage: image)  
  .onAppear {   url.load(&image)  }  
  .onTapGesture {   url.save(image)  }
}

15. Список шрифтов

Почти в конце. Этот следующий полезен.

let fontFamilyNames = UIFont.familyNames
for familyName in fontFamilyNames {
  print("Font Family Name = [\(familyName)]")
  let names = UIFont.fontNames(forFamilyName: familyName)
  print("Font Names = [\(names)]")
}

С кодом SwiftUI вы можете найти такие шрифты:

struct Fonts {
  static func avenirNextCondensedBold (size: CGFloat) -> Font {
  return Font.custom("AvenirNextCondensed-Bold", size: size)
}

Вы вызовете эту конструкцию, чтобы использовать код:

.font(Fonts.avenirNextCondensedBold(size: 12))

16. Тернарный оператор

Это последнее расширение можно использовать во многих областях SwiftUI, но я никак не могу вспомнить синтаксис.

Здесь тернарный оператор оценивает condition и

  • если condition равно true, выполняется expression1.
  • если condition равно false, выполняется expression2.

Тернарный оператор принимает три операнда (condition, expression1 и expression2). Отсюда и название тернарный оператор.

flipColor = flipColor == .blue ? .green : .blue

Итак, если flipColor равно blue, я получу обратно green, а если flipColor равно green, я получу обратно blue.

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

Спасибо за прочтение!