Ответ 1
Позвольте мне начать с некоторой теории. MVVM является специализацией Модель представления (или Модель приложения) для Microsoft Silverlight и WPF. Основные идеи, лежащие в основе этого архитектурного шаблона пользовательского интерфейса:
- Часть просмотра является единственной, которая зависит от структуры GUI. Это означает, что для iOS контроллер представления является частью представления.
- В представлении может отображаться только модель представления. Никогда.
- Модель просмотра содержит состояние представления. Это состояние предлагается для представления через свойства модели представления. Эти свойства содержат не только значение меток, но и другую информацию, связанную с просмотром, например, если включена кнопка сохранения или цвет для рейтинга. Но информация государства должна быть независимой от пользовательского интерфейса. Таким образом, в случае iOS свойство для цвета должно быть перечислением, например, вместо UIColor.
- Модель просмотра также предоставляет методы, которые будут учитывать действия пользовательского интерфейса. Эти действия будут обсуждаться с моделью, но они никогда не изменят состояние представления, напрямую связанного с данными. Вместо этого он разговаривает с моделью и просит внести необходимые изменения.
- Модель должна быть автономной, т.е. вы должны иметь возможность использовать тот же код для модели для приложения командной строки и интерфейса интерфейса. Он позаботится обо всей бизнес-логике.
- Модель не знает о модели представления. Таким образом, изменения в модели представления распространяются через механизм наблюдения. Для iOS и модели с обычными подклассами NSObject или даже Core Data для этого может использоваться KVO (также для Swift).
- Когда модель представления узнает об изменениях в модели, она должна обновить состояние, которое оно хранит (если вы используете типы значений, тогда она должна создать обновленную версию и заменить ее).
- Модель представления не знает о представлении. В своей первоначальной концепции он использует привязку данных, недоступную для iOS. Таким образом, изменения в модели представления распространяются через механизм наблюдения. Вы также можете использовать KVO здесь, или, как вы упомянули в вопросе, будет делать простой шаблон делегирования, даже лучше, если он будет объединен с наблюдателями свойств Swift. Некоторые люди предпочитают реактивные рамки, такие как RxSwift, ReactiveCocoa или даже Swift Bond.
Преимущества, как вы упомянули:
- Лучшее разделение проблем.
- Независимость от пользовательского интерфейса: упрощение миграции на другие пользовательские интерфейсы.
- Лучшая тестируемость из-за разделения проблем и развязанного характера кода.
Итак, вернувшись к вашему вопросу, реализация протокола UITableViewDataSource
принадлежит к части представления архитектуры из-за ее зависимостей от структуры пользовательского интерфейса. Обратите внимание, что для использования этого протокола в коде этот файл должен импортировать UIKit. Также методы, подобные tableView(:cellForRowAt:)
, которые возвращают представление, сильно зависят от UIKit.
Затем ваш массив Contacts
, который действительно является вашей моделью, не может быть обработан или запрошен через представление (источник данных или иначе). Вместо этого вы передаете модель представления в контроллер табличного представления, который в простейшем случае имеет два свойства (я рекомендую их хранить, а не вычисленные свойства). Одним из них является количество разделов, а другое - количество строк в секции:
var numberOfSections: Int = 0
var rowsPerSection: [Int] = []