MVVM SwiftUI вопрос про классы


#21

И да, я не знаток ))) Тут есть более опытные коллеги, но я опишу своё мнение.

Да, по сути, ЮАй - это та же реактивщина и почти всё то же. У ЮАйя особенность, что внутри боди (тело вьюшки) вью вы ничего не можете инициализировать. Можете до боди, где как раз обычно инициализируют некоторые переменные данные и вьюмодели. Поэтому вы или делаете приватные функции, или логику уносите во вьюмодель. Тут главное за что любят ЮАй - это как раз раективщина, наследство от Комбайн: паблишеры (источники уведомлений об изменении данных) и сабскрайберы (подписчики на эти уведомления), при помощи которых моментально перерисовывается интерфейс. Это всё происходит нативно и просто - и это огромная сила ЮАйя. Но есть много подводных камней, от части съедающих этот мега плюс, но их должны точно решить в ближайшее время.
Вторая особенность вытекает из первой: чтобы создать паблишер и подписаться на него, надо соответствовать протоколу ObservableObject. Соответсвенно, если у вас, например, массив каких-либо данных, то просто вы его не можете подписать под протокол. Для этого его необходимо обернуть в класс, чтобы этот класс подписать под протокол. Отсюда необходимость в ЮАй использовать архитектуры реактивщины и самая простая - MVVM.
Странно, что вы не используете логику внутри вью модели, ведь в этом и плюс, что вьюмодель парсит модель и передаёт данные вью. А если, например нам надо добавить или убрать элемент из массива, так как раз эта логика (функция) будет у нас лежать как раз внутри вьюмодели, так как там же и данные лежат. Да и удобнее всё в одном месте, и не разбрасывать логику по вью.

По количеству вьюмоделей получается, что всё зависит от вашей модели данных и от вью, с которыми она взаимодействует.

Пример: у нас задача сделать простой функционал списка для записывания простых задач-напоминаний как в штатном приложении “напоминания”.

Модель

  1. У нас будет модель одного напоминая/записи (строки)
  2. У нас будет модель списка строк
    Модели списка списков скорее не будет, так как это просто массив моделей списков, который мы завернём в класс и получим вьюмодель списка списков.

Вью:

  1. вью списка списков
  2. вью одного списка
    И тут дальше если список одноуровневый, то можно на этом и закончить и всё в одно вью запихнуть. Но если задача сделать вложенность любого уровня или бесконечную, то уже точно без рекурсии (вызова функции из тела самой этой функции) не обойтись.
  3. нам нужна вью одной строки, чтобы мы могли её закольцевать (вызвать саму из себя) для вложенности.

Вью модели получается почти соответствуют нашей модели и полностью соответствует количеству вью.

  1. Вьюмодель списка списков.
  2. Вьюмодель списка.
  3. Вьюмодель строки.

Во-первых: в каждой вьюмодели у нас есть данные к которым нужна логика их обработки (например во вьюмодели одного списка лежит массив вьюмоделей строк. Во вьюмодели строки лежит модель строки).
Второй пункт - это особенность ЮАй. На данный момент ЮАй не видит уведомления от вложенных данных в другой класс! Что это значит?

Небольшое отступление.
На данный момент есть два пути подписать данные под протокол ObservableObject:

  1. Подписать непосредственно модель.
  2. Создать вьюмодель и подписать её.
    По архитектуре и “бэст практис” мы понимаем, что лезть в модель с логикой и протоколами так себе идея. Да и определённая архитектура нам всё равно необходима просто по условиям.

Продолжение.
Берём за основу самое простое, MVVM, и создаём вьюмодель, подписанную под нужный протокол. Если у нас это вьюмодель одной строки, то логично туда положить объект модели строки. Но тут как раз собака зарыта :slight_smile: Положив туда объект, мы перестаём видеть уведомления об изменении свойств объекта (модели строки), даже если они были обозначены как паблишед в самой модели, что уже не гуд, как мы выяснили выше (просто из-за одной из тонны особенностей ЮАй на данный момент. Эта особенность не обоснована ни чем и больше похожа на баг, который ломает логику ООП). И проблема идёт наверх по иерархии вьюмоделей. Поэтому мы обязаны перезаписать все свойства модели во вью модель по отдельности (либо это свойства дочерней вьюмодели в родительской вьюмодели), обозначив их @Published, что ломает немного ООП. Вот такие пироги. И, соответственно, логично всю логику по работе с данными видеть во вьюмодели при архитектуре MVVM (по крайней мере не только для ЮАй, но и для все остального по моему мнению тоже).

Тут в соседней теме от меня есть код как раз с этой иерархией и проблемой невидения уведомлений от свойств объектов внутри вьюмодели - поищите.

Надеюсь понятно описал, и вы пройдёте эти затыки быстрее меня.

Следущая серия - это передача наверх по иерархии вьюмоделей уведомлений от паблишера при использовании навигейшена (NavigationLink). Например, при изменении количества строк в списке, при переходе из списка наверх в список списков (а из списка списков в конкретный список мы попали через NavigationLink), мы должны видеть число, равное актуальному количеству строк в каждом списке. Там тоже нефига неочевидное решение, которое я искал неделю на стэке и не нашёл, а сложил из десятка разных ответов. Так как чисто случайно нашёл и понял, что проблема, похоже, в особенностях навигейшена ЮАйя была очередная блин :rofl:
И ещё: чем хуже в некоторые случаях (в большинстве) @EnvironmentObject, чем вложенная вью модель и @ObservedObject на каждом вью. :wink:

Вместо ПыСы:
Для понимания проблемы для новичков в ЮАй. Этому фреймворку всего один год! И он активно развивается - это значит, что решения, которые работают сегодня, могут не работать завтра! На Кит вы на английском найдёте тонны информации по любому вопросу. По ЮАй вы можете не найти решения даже на английском! А каких-то решений просто пока не существует: например, создать кастомный экшен для списков.

Пример про навигейшн линк опишу завтра, при этом даже на английском напрямую эту проблему ни кто не описывает! А на русском так вообще, этот пост - это единственное на данный момент развёрнутое объяснение про проблему паблишеров во вложенных классах (буду рад ошибаться, но я не нашёл), а это - всего пару моментов ЮАй… понимаете масштаб недостаточности информации по этой теме? При этом, эта информация ещё будет года 3 стремительно меняться…

Благо Пол Хадсон со своим hackingwithswift.com разбирает почти все базовые вопросы по верстке интерфейса в ЮАй, но при этом все подводные камни так и лежат на дне и ждут вас :slight_smile: