MVC означает Model-View-Controller , и это широко распространенный архитектурный шаблон для разработки программного обеспечения. Это фактический шаблон проектирования для разработки Какао, и это было в течение многих, многих лет. Большинство из нас не могут представить себе создание приложений без него. И UIKit (iOS), и AppKit (macOS) часто используют MVC. Кажется, что у нас нет другого варианта для создания приложений для iOS, tvOS, macOS и watchOS.
Даже если вы не знакомы с шаблоном Model-View-Controller, если у вас есть амбиции по разработке приложений для одной из платформ Apple, вам необходимо узнать, как представления (iOS) и windows (macOS) связаны с контроллерами и какую роль играют модель играет в типичном приложении какао. К счастью, MVC легко изучить.
В этой короткой серии статей я объясню, что такое MVC, как он выглядит в типичном приложении Cocoa и почему он может быть не лучшим решением для разработчиков Cocoa.
1. Пример
Позвольте мне показать вам, как выглядит шаблон MVC в типичном приложении Cocoa. Пример, который я покажу вам, фокусируется на iOS, но все, что мы обсуждаем, относится и к tvOS, macOS и watchOS. Откройте Xcode и создайте новый проект iOS на основе шаблона приложения Single View .
Назовите проект MVC и установите « Язык» на « Swift» и « Устройства» на iPhone . Я использую Xcode 8 для этого урока. Параметры конфигурации проекта могут выглядеть немного иначе, если вы используете Xcode 9.
Как следует из названия, шаблон Model-View-Controller определяет три компонента, модель , представление и контроллер . Позвольте мне показать вам, где вы можете найти эти компоненты в типичном проекте iOS.
Контроллеры
Контроллеры приложения iOS являются контроллерами представления, экземплярами класса UIViewController
или его подклассом. Класс UIViewController
определен в платформе UIKit . Поскольку мы выбрали шаблон приложения Single View Application при настройке проекта, Xcode создал для нас контроллер для начала, класс ViewController
, определенный в ViewController.Swift . Он наследуется от класса UIViewController
.
Как следует из названия, экземпляр UIViewController
отвечает за управление представлением, экземпляром класса UIView
. Каждый контроллер представления в проекте iOS сохраняет сильную ссылку на представление, еще один компонент шаблона Model-View-Controller. Класс UIView
также определен в структуре UIKit .
Взгляды
Мы можем найти компонент вида в основной раскадровке проекта. Откройте Main.storyboard в Навигаторе проектов слева и осмотрите Сцена Контроллера Представления . Сцена содержит контроллер представления, экземпляр класса ViewController
и управляет экземпляром UIView
.
Выберите View в раскадровке слева и откройте Identity Inspector справа. Поле класса представления установлено в UIView
. В приложении iOS представления, как правило, являются экземплярами класса UIView UIView
или его подкласса.
модели
До сих пор мы исследовали слой контроллера и слой представления. Но где мы можем найти модельный слой проекта? Модель почти всегда специфична для проекта, над которым вы работаете, и вы должны определить, реализовать и использовать модель проекта. Я пишу модель , но у вас обычно есть несколько моделей, в зависимости от сложности вашего проекта.
Давайте добавим последний кусок головоломки MVC, создав модель. Создайте новый файл Swift и назовите его Person.swift .
Выберите Person.swift в Навигаторе проектов слева и определите структуру с именем Person
. Мы определяем три свойства:
-
firstName
типаString
-
lastName
типаString
-
age
типаInt
1
2
3
4
5
6
7
|
struct Person {
let firstName: String
let lastName: String
let age: Int
}
|
Теперь у вас есть модель, которую вы можете использовать в своем проекте. Давайте будем проще и определим свойство person
типа Person?
в классе ViewController
. Мы создаем экземпляр Person
в viewDidLoad()
контроллера представления и присваиваем его свойству person
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
import UIKit
class ViewController: UIViewController {
// MARK: — Properties
var person: Person?
// MARK: — View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Create Person
person = Person(firstName: «John», lastName: «Doe», age: 40)
}
}
|
То, что мы видим в этом примере, очень распространено в приложениях Cocoa, работающих на основе шаблона Model-View-Controller. Контроллер представления владеет моделью и управляет ею, а также использует модель для заполнения своего представления. В более сложном приложении вы загружаете данные модели из постоянного хранилища или извлекаете их из удаленного бэкэнда.
Давайте определим выход для экземпляра UILabel
в контроллере представления и в основной раскадровке добавим метку к сцене View Controller .
01
02
03
04
05
06
07
08
09
10
11
|
import UIKit
class ViewController: UIViewController {
// MARK: — Properties
@IBOutlet var label: UILabel!
…
}
|
В viewDidLoad()
контроллера представления мы безопасно разворачиваем значение, сохраненное в свойстве person
и используем его данные для установки свойства UILabel
экземпляра UILabel
.
01
02
03
04
05
06
07
08
09
10
11
|
override func viewDidLoad() {
super.viewDidLoad()
// Create Person
person = Person(firstName: «John», lastName: «Doe», age: 40)
// Populate Label
if let person = person {
label.text = «\(person.lastName), \(person.firstName) (\(person.age))»
}
}
|
Результат не очень удивителен, если вы знакомы с разработкой Какао. Это то, что мы в конечном итоге.
2. Что такое модель-представление-контроллер?
Шаблон Model-View-Controller легко понять и подобрать. Несмотря на его простоту, вы можете найти широкий спектр вкусов MVC. MVC предлагает только базовый проект, который можно изменить на платформе, на которой он используется.
Шаблон Model-View-Controller, с которым вы знакомы в iOS, tvOS, macOS и watchOS, несколько отличается от исходного определения. Хотя различия по сравнению с исходным определением незначительны, они оказывают значительное влияние на код, который вы пишете, а также на удобство сопровождения проекта.
Болтовня
Шаблон Model-View-Controller — это старый шаблон проектирования. Он впервые появился в 1970-х годах в Smalltalk . Шаблон был задуман Тригве Реенскауг . За прошедшие годы модель Model-View-Controller вошла во многие языки и фреймворки, включая Java , Rails и Django .
Ранее я упоминал, что шаблон MVC разбивает приложения на три отдельных компонента: модель , представление и контроллер . Исходная реализация шаблона определяет, что представление отвечает за отображение данных модели для пользователя. Пользователь взаимодействует с приложением через слой представления. Контроллер отвечает за взаимодействие с пользователем и в результате манипулирует данными модели. Представление визуализирует эти изменения для пользователя. Как показано на диаграмме ниже, модель играет ключевую роль в модели MVC, как она была разработана Реенскаугом.
MVC и какао
Реализация, которую мы используем в разработке Какао, отличается от оригинального дизайна Reenskaug. Посмотрите на диаграмму ниже, чтобы лучше понять, что влечет за собой эти различия.
Как я упоминал ранее, представление и контроллер имеют близкие отношения. В типичном приложении для iOS контроллер содержит строгую ссылку на представление, которым он управляет. Представление — это тупой объект, который знает, как отображать данные и реагировать на взаимодействие с пользователем. Результат — компонент многократного использования.
Контроллер играет жизненно важную роль в приложениях Cocoa, работающих на основе шаблона Model-View-Controller. Он берет на себя некоторые задачи модели в оригинальной реализации MVC Реенскага. Представление и модель не взаимодействуют напрямую друг с другом. Вместо этого модель обычно принадлежит контроллеру, который он использует для настройки и заполнения представления, которым он управляет.
Я надеюсь, что вы можете увидеть тонкие различия между оригинальной реализацией Reenskaug в Smalltalk и реализацией Cocoa, к которой мы привыкли. Различия незначительны, но, как я сейчас расскажу, их влияние важно.
3. Добро: разделение проблем и возможность повторного использования
Прежде чем мы рассмотрим проблемы, которые создает MVC, я хотел бы показать вам, почему шаблон Model-View-Controller стал таким популярным и широко распространенным шаблоном в разработке программного обеспечения. Шаблон Model-View-Controller, который мы используем в разработке Какао, имеет ряд явных преимуществ, которые он унаследовал от первоначальной реализации Reenskaug.
Наиболее очевидным преимуществом модели Model-View-Controller является разделение задач . Например, слой представления отвечает за представление данных пользователю. Уровни модели и контроллера не связаны с представлением данных. Но если вы использовали MVC в проекте Какао, то вы знаете, что это не всегда так. Я расскажу об этом чуть позже.
Непосредственным преимуществом такого разделения интересов является возможность повторного использования . Каждый из компонентов шаблона Model-View-Controller ориентирован на определенную задачу, что означает, что строительные блоки приложения MVC часто легко использовать повторно. Это также позволяет этим компонентам быть слабосвязанными, увеличивая их возможность повторного использования. Это не правда для каждого компонента, хотя. Например, в проекте Какао контроллеры часто являются специфическими для приложения и не являются подходящими кандидатами для повторного использования.
Тем не менее, представления и модели проекта можно использовать многократно, если они спроектированы правильно. Например, представления таблиц и коллекций являются подклассами UIView
, которые используются в миллионах приложений. Поскольку табличное представление делегирует взаимодействие пользователя с другим объектом и запрашивает источник данных о данных, которые необходимо отобразить, оно может сосредоточиться исключительно на представлении данных и взаимодействии с пользователем.
4. Плохо: массивные контроллеры представления
Большинство разработчиков быстро понимают, что шаблон Model-View-Controller привносит в таблицу и как он должен быть реализован. К сожалению, модель Model-View-Controller также имеет некрасивую сторону. Я уже писал о возможности повторного использования и разделения проблем. Я уверен, что мне не нужно убеждать вас в этих преимуществах. Табличное представление очень многократно и невероятно эффективно. Разработчики могут использовать стандартные компоненты UIKit в своих приложениях без необходимости создавать подклассы или настраивать их.
Достигая пределов MVC
Но это только часть истории. Вы знаете, когда начинаете выходить за пределы MVC, когда в ваш проект проникли массивные контроллеры представления. Настало время перемен, когда вы просматриваете сотни или тысячи строк кода, чтобы найти тот метод, который вы ищете.
Сбросить это в контроллере
Большинство разработчиков знают, что входит в уровни представления и модели типичного приложения Cocoa, работающего на основе модели Model-View-Controller. Но какой компонент отвечает за форматирование данных, отображаемых пользователю? Помните, что представления должны быть тупыми и многоразовыми. Представление не должно форматировать данные. Правильно? Следует только знать, как представлять данные и реагировать на взаимодействие с пользователем. Должна ли модель быть связана с форматированием данных?
А как насчет сети? Это, конечно, не задача зрения. Должно ли оно быть делегировано модели? Это не звучит правильно. Почему бы нам не вставить этот кусок кода в контроллер? Это не правильно, но пока подойдет.
После многих строк кода вы получите контроллер, готовый к взрыву, и кошмар для тестирования. Тестирование? Я слышу тебя. Я также не хотел бы тестировать контроллер представления, страдающий синдромом массивного контроллера представления .
5. Лучшее решение
Вы начали с благими намерениями, но в итоге вы получили проект с набором избыточных контроллеров, которыми сложно управлять и обслуживать. Вы не ожидаете добавления новых функций в проект, над которым работаете, потому что открытие этих контроллеров представления вызывает у вас тошноту. Это звучит знакомо?
Важно понимать, что это общий сценарий. Многие разработчики выходят за пределы шаблона Model-View-Controller и понимают, что им нужно что-то лучшее. Скорее всего, вы уже рассматривали несколько альтернатив, таких как MVP (Model-View-Presenter) или MVVM (Model-View-ViewModel).
В следующей части этой серии я увеличу шаблон Pattern -View-ViewModel . Будет странно знакомо, если вы уже работали с шаблоном Model-View-Controller. Но шаблон Model-View-ViewModel вносит в таблицу несколько улучшений, которые очень хорошо подходят для разработки Какао.
И пока вы ждете, посмотрите другие наши посты о разработке приложений Какао!