Отладка SwiftUI с пользовательским модификатором вью

09 марта 2023

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

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

В этой статье мы рассмотрим регистрацию того, сколько раз пересоздается SwiftUI-вью. Это выручает в случае, когда вы пытаетесь отследить неожиданные изменения, вызывающие повторное создание ваших вью в SwiftUI.

 

Счетчик модификатора вью SwiftUI

Мы создадим модификатор вью, который будет подсчитывать, сколько раз он был вызван. Мы выгрузим саму регистрацию в пользовательскую очередь отправки под названием debugRenderQueue:

private let debugRenderQueue = DispatchQueue(label: "debugRenderQueue")
private var debugRenderCounts = [String: Int]()


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

extension View {
  func debugRender(
    named: String? = nil, 
    file: StaticString = #file, 
    line: UInt = #line) -> some View {

    // implementation below

  }
}


Разработчик может задать имя счетчику через параметр named или не передавать параметры вообще, и счетчик будет использовать имя файла и номер строки для уникальной идентификации места вызова модификатора.

Наконец, мы будем асинхронно увеличивать текущий счетчик и регистрировать его значение, а затем вернем вью без изменений:

debugRenderQueue.async {
  let id = named ?? "\(file):\(line)"
  debugRenderCounts[id, default: 0] += 1
  os_log("\(id): \(debugRenderCounts[id]!)")
}
return self

 

Теперь давайте попробуем этот новый модификатор.

 

Проверка количества отображений вью с помощью debugRender()


Давайте возьмем простое вью SwiftUI, которое отображает часы, управляемые Timer:

struct ContentView: View {
  @State var timer = Timer.publish(every: 0.1, on: .main, in: .default)
    .autoconnect()

  @State var time = ""

  var body: some View {
    VStack {
      Text("Current time:")
      Text(time).bold()
    }
    .onReceive(timer) { d in
      time = d.formatted(date: .omitted, time: .standard)
    }
  }
}


Таймер обновляет свойство состояния "time" текущим временем 10 раз в секунду, а вью подбирает новое состояние и отображает время:

width=226 align=center rounded=0 Clock ticking
Когда дело доходит до улучшения производительности вашего приложения, вам может понадобиться проверить, перерисовывается ли вью 10 раз в секунду (так часто вы обновляете свойство time) или только один раз, когда свойство time действительно меняет значение.

Вот где нам пригодится использование нового модификатора, указанного выше. Если вы добавите модификатор debugRender(), вы сразу же увидите обновления в dataTile:

Text(time).bold()
  .debugRender(named: “Timer")


width=537 align=center rounded=0 Clock ticking


И чтобы сделать данные еще более удобными для чтения, нажмите на меню плитки и выберите "Просмотреть как диаграмму", далее нажмите на подзаголовок плитки, чтобы увидеть, сколько логов он отображает в секунду:

width=537 align=center rounded=0 Clock tickingТеперь у вас есть ответ - сам элемент плитки обновляется один раз в секунду, поэтому SwiftUI заново создает вью только тогда, когда состояние действительно изменяется.

Какие еще модификаторы вью SwiftUI, взаимодействующие с dataTile, вы бы хотели использовать? 

Оригинал статьи
 

Содержание