ЗАМЕТКИ
Model-view-controller (MVC)

Шаблон model-view-controller (MVC) состоит из трех связанных между собой объектов различного типа:
- Model структура данных приложения (подклассы UIView)
- View представление приложения, визуальные элементы управления (подклассы UIView)
- View Controller контроллер для координации работы между моделью и представлением (подкласс UIViewController)
Шаблон MVC используется в UIKit.
Модель взаимодействует с контроллером посредством наблюдения за его свойствами, представление взаимодействует с контроллером через IBActions. У контроллера может быть множество связанных с ним моделей и представлений. Модели и представления могут быть переиспользованны другими контроллерами, переиспользование контроллера допустимо, но крайне нежелательно из его индивидуальной специфики и назначения.
Когда использовать?
Используйте этот шаблон в качестве отправной точки при создании приложений. MVC — это структурный шаблон, поскольку он предназначен для создания объектов в виде моделей, представлений или контроллеров.
Создание простой структуры Address:
import UIKit
public struct Address {
public var street: String
public var city: String
public var state: String
public var zipCode: String
}
import UIKit требуется для создания подкласса AddressView класса UIView:
public final class AddressView: UIView {
@IBOutlet public var streetTextFeld: UITextField!
@IBOutlet public var cityTextField: UITextField!
@IBOutlet public var stateTextField: UITextField!
@IBOutlet public var zipCodeTextField: UITextField!
}
Создание контроллера AddressViewController:
public final class AddressViewController: UIViewController {
public var address: Address?
public var addressView: AddressView! {
guard isViewLoaded else {
return nil
}
return (view as! AddressView)
}
}
Контроллер содержит строгую ссылку на представление и модель. Переменная addressView проверяет условие isViewLoaded (загрузка представления) и, если оно оценивается как ложное, выполняет оператор else, обычно завершающий работу метода. Если значение true представление преобразуется в AddressView. Преимущество оператора guard заключается в более быстром исполнении: блок guard выполняется только в том случае, если условие ложно, и выход из блока осуществляется через оператор передачи управления, такой как return, break, continue или thrown. Это обеспечивает ранний выход и меньшее количество скобок.
Контроллер должен обновить addressView используя значение из переменной address.
Предотвратить переопределение метода, свойства или индекса, можно обозначив его как конечный написав ключевое слово final перед ключевым словом метода, свойства или индекса (final var, final func, final class func, и final subscript). Любая попытка переписать конечный метод, свойство или индекс в подклассе приведет к ошибке компиляции. Методы, свойства и индексы внутри класса, так же могут быть отмечены как конечные. Можно отметить целый класс как конечный или финальный, написав слово final перед ключевым словом class (final class). Любая попытка унаследовать класс также приведет к ошибке компиляции.
Добавляем перегрузку функции viewDidLoad() и функцию для обновления адресных данных updateViewFromAddress() в контроллер. Также заменим свойство переменной address чтобы модель могла сообщать контроллеру об изменениях, который в свою очередь обновит представление.
public final class AddressViewController: UIViewController {
public var address: Address? {
didSet {
updateViewFromAddress()
}
}
public var addressView: AddressView! {
guard isViewLoaded else {
return nil
}
return (view as! AddressView)
}
public override func viewDidLoad() {
super.viewDidLoad()
updateViewFromAddress()
}
private func updateViewFromAddress() {
guard let addressView = addressView,
let address = address else { return }
addressView.stateTextField.text = address.street
addressView.cityTextField.text = address.city
addressView.stateTextField.text = address.state
addressView.zipCodeTextField.text = address.zipCode
}
}
Для обновления адреса из представления в контроллере используется метод IBAction:
@IBAction public func updateAddressFromView(_sender: AnyObject) {
guard let street = addressView.streetTextFeld.text,
street.count > 0,
let city = addressView.cityTextField.text,
city.count > 0,
let state = addressView.stateTextField.text,
state.count > 0,
let zipCode = addressView.zipCodeTextField.text,
zipCode.count > 0 else {
return
}
address = Address(street: street, city: city, state: state, zipCode: zipCode)
}
MVC — хорошая отправная точка, но у нее есть ограничения. Не каждый объект точно впишется в категорию модели, представления или контроллера. Следовательно, приложения, использующие только MVC, как правило, содержат много логики в контроллерах.
В новой технологии SwiftUI используется модель MVVM (Model-View-ViewModel), вместе с этим использование классических MVC также допустимо.