iOS разработка. Вопросы и ответы на собеседовании

iOS разработка. Вопросы и ответы на собеседовании

Оглавление

 

База по iOS разработке


Разница между Bounds и Frame

  • Frame – это прямоугольник описываемый положением location (x, y) и размерами size (width, height) view относительно её superview в которой она содержится;
  • Bounds – это прямоугольник описываемый положением location(x, y) и размерами size (width, height) view относительно ее собственной системы координат (0, 0);

Разница между Point (pt) и Pixel (px)

  • Pixels (px) — точки на экране;
  • Points (pt) — плотность точек на экране;

Работа механизма сообщений

Компилятор переводит каждую посылку сообщения, т.е. конструкцию вида [object msg] в вызов функции objc_msgSend.
Эта функция в качестве своего первого параметра принимает указатель на объект-получатель сообщения, в качестве второго параметра выступает т.н. селектор, служащий для идентификации посылаемого сообщения. Если в сообщении присутствуют аргументы, то они также передаются objc_msgSend как третий, четвертый и т.д. параметры.


Селектор

Селектор — это имя метода закодированное специальным образом, используемым Objective-c для быстрого поиска. Указание компилятору на селектор происходит при помощи директивы @selector(метод)


Чем отличается include от import?

import защищен от многократного включения кода. include — нет.

То есть при каждом вызове include будет происходить включение кода, даже если он уже был внедрён.


KVO

Key Value Observing

Одна из реализаций паттерна наблюдатель.

Наблюдатель следит за конкретным свойством объекта. Когда значение этого свойства меняется, наблюдателю приходит уведомление и он соответствующим образом реагируют.

В Objective-c / Swift, для назначения наблюдения, используется метод  addObserver.

Плюсы использования KVO:

  1. В Objective-c / Swift минимализм кода. Нет необходимости как-то изощряться, все элементы очевидны;
  2. Универсальный способ общения компонентов приложения между собой;

Минусы использования KVO:

  1. Заметное падение производительности при обильном использовании KVO. Следует очень продуманно подходить к использованию и использовать только там, где это действительно необходимо;
  2. Строковые идентификаторы не проверяются компилятором на валидность. Это может привести к ошибкам при переименовании переменных;
  3. Чувствительность к порядку добавления / удаления наблюдателей. Если наблюдатель пытается отписаться от наблюдаемого, на который наблюдатель в данный момент не подписан, то происходит «падение» приложения. Если же наблюдатель не отпишется до того, как наблюдаемый будет уничтожен, то произойдет утечка памяти;

Notification

Это механизм использования возможностей NotificationCenter самой операционной системы. Использование NSNotificationCenter позволяет объектам коммуницировать, даже не зная друг про друга.

Это очень удобно использовать когда у вас в параллельном потоке пришел push-notification, или же обновилась база, и вы хотите дать об этом знать активному на данный момент View.


Указатель isa

Каждый объект Objective-C содержит в себе атрибут isa — указатель на class object для данного объекта. class object автоматически создается компилятором и существует как один экземпляр, на который через isa ссылаются все экземпляры данного класса.

Под капотом Objective-C объекты по сути C-структуры. Каждая из которых содержит поле под названием isa, которое является указателем на класс, который является экземпляром объекта. Среда выполнения следует за этим указателем, чтобы определить, какой класс является объектом, поэтому он знает, на какие селекторы отвечает объект, каков его суперкласс, какие свойства имеет объект и т.д.


Что такое CoreData?

Это фреймворк для работы с хранимыми на устройстве данными. Не смотря на то, что Core Data может хранить данные в реляционной базе данных вроде SQLite, Core Data не является СУБД (системой управления БД).

По-правде, Core Data в качестве хранилища может вообще не использовать реляционные базы данных. Core Data скорее является оболочкой для работы с данными, которая позволяет работать с сущностями и их связями (отношениями к другим объектами), атрибутами, в том виде, который напоминает работы с объектным графом в обычном объектно-ориентированном программировании.


Типы хранилищ CoreData

  1. XML;
  2. SQLLite;
  3. In-Memory;
  4. Binary;

Что такое NSManagedObjectID

Является универсальным идентификатором для управляемого объекта, а также предоставляет основу для уникальности в структуре Core Data.

Универсальный потокобезопасный идентификатор. Бывает временным и постоянным. Используется в случае передачи объекта из одного контекста в другой.


Что такое NSPersistentStoreCoordinator?

NSPersistentStoreCoordinator отвечает за хранение объектов данных которые передаются из NSManagedObjectContext.


Особенности использования CoreData в разных потоках

NSManagedObjectContext не потокобезопасен.

Вариант решения проблемы: создавать для каждого потока свой NSManagedObjectContext и потом синхронизировать.


Разница между nil, Nil, NULL, NSNull

  • NULL = (void *)0 — нулевой указатель в языке Си;
  • nil = (id)0 — нулевой указатель на объект Objective-C;
  • Nil = (Class)0 — нулевой указатель типа Class в Objective-C;
  • NSNull = [NSNull null] — синглтон класса NSNull — обёртки над nil и Null;

Работа Push-Notification

Это короткое сообщение, состоящее из токена девайса, полезной нагрузки (payload) и ещё некоторой информации.

Полезная нагрузка — это актуальные данные, которые будут отправляться на девайс.

  1. APNS (Apple Push Notification Service) запрашивает у устройства token, своеобразный ключ, который можно считать «адресом»;
  2. Есть некий сервер;
  3. Приложение отправляет token на сервер, который занимается отправкой push-уведомлений;
  4. Когда произойдёт какое-либо событие для вашего приложения, сервер отправит push-уведомление в APNS;
  5. APNS отправит push-уведомление на девайс пользователя;

Тонкости Push-Notification

  1. Не работают в симуляторе, поэтому для тестирования нужен настоящий девайс;
  2. Регистрация в iOS Developer Program;
    Для каждого приложения, в котором будет интегрирован механизм push-уведомлений, необходимо создать новый App ID и provisioning profile, а также SSL-сертификат для сервера;
  3. Размер полезной нагрузки не может превышать 256 байт. Это примерно столько же, сколько позволяет вместить в себя СМС или твит;
  4. Нет гарантий, что push-уведомления будут доставлены, даже если APNS примет их;
  5. Как только ваш сервер сформировал push-уведомление, он безответно отправляет его в APNS. Нет способа узнать статус доставки уведомления конечному пользователю после отправки. Время доставки может варьироваться от нескольких секунд до получаса;
  6. APNS будет пытаться доставить последнее отправленное уведомление, когда девайс станет доступен для приёма. После тайм-аута push-уведомление будет потеряно навсегда;

Что такое контекст (NSManagedObjectContext)?

Это среда в которой находится объект и которая следит за состоянием объекта и зависимыми объектами.


Разница между dispatch_async и dispatch_sync

  • dispatch_async ставит копию блока на выполнение в очередь и немедленно возвращает управление;
  • dispatch_sync ставит ссылку блока на выполнение в очередь и ожидает завершения операции;

KVC

Key-Value Coding

Представляет собой механизм для доступа к свойству объекта косвенно, с помощью строк для идентификации свойств, а не через вызов аксессора или доступ к ним непосредственно через переменных экземпляра. Часто используется для фильтрации в массивах (NSPredicate).


Что такое быстрое перечисление (fast enumeration)?

Это итерация по объектам любого класса, который реализует протокол NSFastEnumeration, в том числе NSArray, NSSet и NSDictionary.


Категория

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

С помощью категорий также можно переопределять существующие методы.


Расширение

Расширение класса имеет некоторое сходство с категорией, но оно может быть добавлено только в класс, для которого есть исходный код во время компиляции (класс скомпилирован одновременно с расширением класса).

Методы, объявленные расширением класса, реализованы в блоке @implementation для исходного класса. В отличие от обычных категорий расширение класса может добавлять в класс собственные свойства и переменные экземпляра.


Протокол

Протокол (он же формальный протокол) в Objective-C описывает методы, которые должны реализовать классы реализующие этот протокол. Методы описанные в протоколе не имеют собственной реализации. Они реализуются в реализующем протокол классе.


Неформальный протокол

Категория с описанными, но не реализованными методами, называется неформальным протоколом.

Протокол может описывать методы, которые должны быть реализованы обязательно (@required) или опционально (@optional). По умолчанию, все методы, описанные в протоколе, являются обязательными.


runLoop

runLoop (цикл выполнения) — цикл обработки событий, который используется для планирования работы и координации получения входящих событий.

Объект NSRunLoop также обрабатывает события NSTimer.


Memory Warning

Приложение никогда не вызывает этот метод напрямую. Этот метод вызывается, когда система обнаружила недостаточное количество памяти. Можно переопределить.


Зачем нужны атрибуты свойств?

По сути, атрибуты, указываемые при объявлении свойств, определяют то, каким образом будут сгенерированы методы обращения к данным.


Атрибуты доступности свойства (readonly / readwrite)

  • readonly — свойство доступно только на чтение (getter);
  • readwrite — свойство доступно как на чтение (getter), так и на запись (setter);

Атрибут атомарности (atomic / nonatomic)

Cинхронизировать чтение / запись между потоками или нет. atomic потокобезопасен (синхронизирован).


Атрибуты владения (retain / strong / copy / assign / unsafe_unretained / weak)

  • retain / strong — показывает, что в сгенерированном сеттере счетчик ссылок на присваиваемый объект будет увеличен, а у объекта, на который свойство ссылалось до этого, — счетчик ссылок будет уменьшен. При включённом ARC используется strong, а при выключенном ARC используется retain;
  • copy — означает, что мы копируем значение объекта при его создании. Также показывает, что полученное значение свойства будет иммутабельным, попытка изменения приведёт к крэшу;
  • assign — просто присвоение адреса. С выключенным ARC является дефолтным значением. Стоит применять к свойствам типов, не попадающих под действие ARC (примитивные типы и так называемые необъектные типы (non-object types) вроде CFTypeRef);
  • unsafe_unretained — свойство с таким типом владения просто сохраняет адрес присвоенного ему объекта. Методы доступа к такому свойству никак не влияют на счетчик ссылок объекта. Он может удалиться, и тогда обращение к такому свойству приведет к крэшу (потому и unsafe). Сейчас используется исключительно редко;
  • weak — позволяет свойствам с таким значением атрибута менять свое значение на nil, когда объект, на который указывала переменная, уничтожается. Очень хорошо сказывается на устойчивости работы приложения;

Что такое @synthesize в Objective-C?

@synthesize генерирует методы getter и setter для вашего свойства.


Что такое @synchronized?

@synchronized гарантирует, что только один поток может выполнять код в блоке в любой момент времени.


Что такое Dynamic Dispatch?

Это процесс выбора реализации полиморфной операции, которая является методом или функцией для вызова во время выполнения.

Это происходит, когда мы хотим вызывать наши методы как метод объекта.


Что такое Grand Central Dispatch (GCD)?

GCD — это библиотека, которая предоставляет низкоуровневый и объектный API для одновременного запуска задач при управлении потоками за кулисами.

Терминология:

  • Очереди отправки: очередь отправки отвечает за выполнение задачи в порядке FIFO;
  • Серийная очередь отправки: последовательная очередь отправки запускает задачи по одной;
  • Параллельная очередь отправки: в параллельной очереди отправки выполняется столько задач, сколько возможно без ожидания завершения начатых задач;
  • Основная очередь отправки: глобально доступная последовательная очередь, которая выполняет задачи в основном потоке приложения;

Сильная / слабая ссылка

  • Сильная ссылка (strong) при присваивании количество ссылок на объект увеличивается;
  • Слабая ссылка (weak) при присваивании количество ссылок на объект не увеличивается, а когда объект удаляется, то этому свойству присваивается nil;


Как работает асинхронность в iOS?

Асинхронный код убирает блокирующую операцию из основного потока программы, так что она продолжает выполняться, но где-то в другом месте, а обработчик может идти дальше. Проще говоря, главный «процесс» ставит задачу и передает ее другому независимому «процессу».



ООП (Объектно-Ориентированное Программирование)


Инкапсуляция

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

  1. При необходимости максимальной локализации предстоящих изменений, когда изменяется только работа объекта, а не программы;
  2. При необходимости предсказания предстоящих изменений и их последствий;
  3. При необходимости очистки глобальной области видимости;

Наследование

Процесс, посредством которого один объект может приобретать свойства другого. Точнее, объект может наследовать основные свойства другого объекта и добавлять к ним черты, характерные только для него. Польза наследования в том, что оно дополняет идею абстракции. Абстракция позволяет представить объекты с разным уровнем детальности. Наследование упрощает программирование, позволяя создать универсальные методы для выполнения всего, что основано на общих свойствах, и затем написать специфические методы для выполнения специфических операций над конкретными типами данных.


Полиморфизм

Возможность объектов с одинаковой спецификацией иметь различную реализацию (использование одного имени для решения двух или более схожих, но технически разных задач).
Целью полиморфизма является использование одного имени для задания общих для класса действий. Выполнение каждого конкретного действия будет определяться типом данных. Концепцией полиморфизма является идея «один интерфейс, множество методов». Это означает, что можно создать общий интерфейс для группы близких по смыслу действий. Преимуществом полиморфизма является то, что он помогает понизить сложность разработки, разрешая использование того же интерфейса для задания единого класса действий. Выбор же конкретного действия, в зависимости от ситуации, возлагается на компилятор.


Конструктор

Специальный блок инструкций, вызываемый при создании объекта. Выполняется по умолчанию, не требует дополнительного вызова. Используется для инициализации членов класса, расчёта значений, необходимых для работы созданного объекта и тому подобное.


Назначенный инициализатор

Главный инициализатор (конструктор), все остальные методы создающие класс вызывают этот метод.


Деструктор

Вызывается при уничтожении объекта. Он обычно используется для освобождения памяти.


Виртуальный метод

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

Разработчику необязательно знать точный тип объекта для работы с ним через виртуальные методы: достаточно лишь знать, что объект принадлежит классу или наследнику класса, в котором метод объявлен.

Является одним из приёмов реализации полиморфизма. Виртуальные методы позволяют создавать общий код, который может работать как с объектами базового класса, так и с объектами любого его класса-наследника. При этом базовый класс определяет способ работы с объектами и любые его наследники могут предоставлять конкретную реализацию этого способа.



Общее


Lazy Initialization

Приём в программировании, когда некоторая ресурсоёмкая операция (создание объекта, вычисление значения) выполняется непосредственно перед тем, как будет использован её результат. Таким образом, инициализация выполняется «по требованию», а не заблаговременно.

Достоинства

  • Инициализация выполняется только в тех случаях, когда она действительно необходима;
  • Ускоряется начальная инициализации;

Недостатки

  • Невозможно явным образом задать порядок инициализации объектов;

Что такое семафор?

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

В основе семафора лежит счетчик, который и определяет, можно ли выполнять участок кода текущему потоку или нет. Если счетчик больше нуля — поток выполняет код, в противном случае — нет.


Что такое Deadlock?

Ситуация в многозадачной среде или СУБД, при которой несколько процессов находятся в состоянии бесконечного ожидания ресурсов, захваченных самими этими процессами.


Что такое Livelock?

Livelock частая проблема в асинхронных системах. Потоки почти не блокируются на критических ресурсах. Вместо этого они выполняют свою небольшую не блокируемую задачу и отправляют её в очередь на обработку другими потоками.

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


Что такое мьютекс?

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


Чем отличаются синхронная и асинхронная задача?

  • Синхронная ждёт, пока задача завершится;
  • Асинхронная завершает задачу в фоновом режиме и уведомляет о завершении;

Что такое Enum?

Это тип, который содержит группу связанных значений.


Проблема «читатели-писатели»

Это одновременное чтение нескольких потоков, когда должна происходить запись одного потока.

Решением проблемы является блокировка чтения-записи, которая позволяет одновременный доступ только для чтения и отдельный доступ для записи.

Терминология:

  • Состояние гонки возникает, когда два или более потока могут обращаться к общим данным, и они пытаются изменить его одновременно;
  • Тупик возникает, когда две или несколько задач ждут завершения других, но этого не происходит;
  • Блокировка чтения-записи: такая блокировка позволяет одновременный доступ к общему ресурсу только для чтения, в то время как операции записи должны запрашивать эксклюзивный доступ;
  • Блок барьера отправки создает узкое место по типу серии при работе с параллельными очередями;

KISS

  • Разбивайте задачи на подзадачи которые не должны по вашему мнению длиться более 4-12 часов написания кода;
  • Разбивайте задачу на множество более маленьких задач, каждая задача должна решаться одним или парой классов;
  • Сохраняйте ваши методы маленькими. Каждый метод должен состоять не более чем из 30-40 строк. Каждый метод должен решать одну маленькую задачу, а не множество случаев. Если в вашем методе множество условий, разбейте его на несколько. Это повысит читаемость, позволит легче поддерживать код и быстрее находить ошибки в нём. Вы полюбите улучшать код;
  • Сохраняйте ваши классы маленькими. Здесь применяется та же техника что и с методами.
  • Придумайте решение задачи сначала, потом напишите код. Никогда не поступайте иначе. Многие разработчики придумывают решение задачи во время написания кода и в этом нет ничего плохого. Вы можете делать так и при этом придерживаться выше обозначенного правила. Если вы можете в уме разбивать задачу на более мелкие части, когда вы пишете код, делайте это любыми способами. И не бойтесь переписывать код ещё и ещё и ещё… В счёт не идёт число строк, до тех пор пока вы считаете что можно ещё меньше/ещё лучше;
  • Не бойтесь избавляться от кода. Изменение старого кода и написание нового решения два очень важных момента. Если вы столкнулись с новыми требованиями, или не были оповещены о них ранее, тогда порой лучше придумать новое более изящное решение решающее и старые и новые задачи;

DRY

Don’t repeat yourself (не повторяй самого себя).

Каждая часть знания должна иметь единственное, непротиворечивое и авторитетное представление в рамках системы.



Паттерны проектирования (поведенческие)


Цепочка обязанностей (chain of responsibility)

Избегает связывания отправителя запроса и его получателя, давая возможность обработать запрос более чем одному объекту. Связывает объекты-получатели и передаёт запрос по цепочке пока объект не обработает его.


Команда (command)

Инкапсулирует запрос в виде объекта, позволяя передавать их клиентам в качестве параметров, ставить в очередь, логировать, а также поддерживает отмену операций.


Интерпретатор (interpreter)

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


Итератор (iterator)

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


Посредник (mediator)

Определяет объект, инкапсулирующий способ взаимодействия объектов. Обеспечивает слабую связь, избавляя объекты от необходимости прямо ссылать друг на друга и даёт возможность независимо изменять их взаимодействие.


Хранитель (memento)

Не нарушая инкапсуляцию, определяет и сохраняет внутреннее состояние объекта и позволяет позже восстановить объект в этом состоянии.


Наблюдатель (observer)

Определяет зависимость «один-ко-многим» между объектами так, что когда один объект меняет своё состояние, все зависимые объекты оповещаются.


Состояние (state)

Позволяет объекту изменять своё поведение в зависимости от внутреннего состояния.


Стратегия (strategy)

Определяет группу алгоритмов, инкапсулирует их и делает взаимозаменяемыми. Позволяет изменять алгоритм независимо от клиентов, его использующих.


Шаблонный метод (template method)

Определяет алгоритм, некоторые этапы которого делегируются подклассам. Позволяет подклассам переопределить эти этапы, не меняя структуру алгоритма.


Посетитель (visitor)

Представляет собой операцию, которая будет выполнена над объектами группы классов. Даёт возможность определить новую операцию без изменения кода классов, над которыми эта операция проводится.



Паттерны проектирования (структурные)


Адаптер (adapter)

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


Мост (bridge)

Разделяет абстракцию и реализацию так, чтобы они могли изменяться независимо.


Компоновщик (composite)

Компонует объекты в древовидную структуру, представляя их в виде иерархии. Позволяет клиенту обращаться как к отдельному объекту, так и к целому поддереву.


Декоратор (decorator)

Динамически предоставляет объекту дополнительные возможности. Представляет собой гибкую альтернативу наследованию для расширения функциональности.


Фасад (facade)

Предоставляет единый интерфейс к группе интерфейсов подсистемы. Определяет высокоуровневый интерфейс, делая подсистему проще для использования.


Приспособленец (flyweight)

Благодаря совместному использованию, поддерживает эффективную работу с большим количеством объектов.


Прокси (proxy)

Предоставляет замену другого объекта для контроля доступа к нему.



Паттерны проектирования (порождающие)


Абстрактная фабрика (abstract factory)

Предоставляет интерфейс для создания групп связанных или зависимых объектов, не указывая их конкретный класс.


Строитель (builder)

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


Фабричный метод (factory method)

Определяет интерфейс для создания объекта, но позволяет подклассам решать, какой класс инстанцировать. Позволяет делегировать создание объекта подклассам.


Прототип (prototype)

Определяет несколько видов объектов, чтобы при создании использовать объект-прототип и создаёт новые объекты, копируя прототип.


Одиночка (singleton)

Гарантирует, что класс имеет только один экземпляр и предоставляет глобальную точку доступа к нему.



SOLID


Что такое SOLID?

Сокращение от английского Single responsibility, Open-closed, Liskov substitution, Interface segregation и Dependency inversion) — акроним, введённый Майклом Фэзерсом для первых пяти принципов, названных Робертом Мартином в начале 2000-х, которые означали пять основных принципов ООП и проектирования.

  • single responsibility — принцип единственной ответственности;
  • open-closed — принцип открытости / закрытости;
  • liskov substitution — принцип подстановки Барбары Лисков;
  • Interface segregation — принцип разделения интерфейса;
  • Dependency inversion — принцип инверсии зависимостей;

Single responsibility

Принцип единственной ответственности.

Каждый класс должен иметь одну и только одну причину для изменений.


Open-closed

Принцип открытости / закрытости.

«Программные сущности … должны быть открыты для расширения, но закрыты для модификации.».


Liskov substitution

Принцип подстановки Барбары Лисков.

«Объекты в программе должны быть заменяемыми на экземпляры их подтипов без изменения правильности выполнения программы.» См. также контрактное программирование. Наследующий класс должен дополнять, а не изменять базовый.


Interface segregation

Принцип разделения интерфейса.

«Много интерфейсов, специально предназначенных для клиентов, лучше, чем один интерфейс общего назначения.»


Dependency inversion

Принцип инверсии зависимостей.

«Зависимость на Абстракциях. Нет зависимости на что-то конкретное.»



Архитектуры приложений


MVC

Model View Controller

  • Model. Представляет из себя модель конкретной предметной области. Содержит в себе данные и методы необходимые для работы с этими данными;
  • View. Отвечает за визуализацию данных, представление данных в UI;
  • Controller. Промежуточное звено между моделью и представлением. Занимается подготовкой данных для презентации их пользователю, реагирует на действия пользователя;

MVP

Model View Presenter

  • View. Прорисовка, анимации, переходы между экранами. Реализует отображение данных (из модели), обращается к Presenter за обновлениями;
  • Presenter. Форматирование, реакция на события, логика представления и управление View;
  • Model. Хранит в себе всю бизнес-логику, при необходимости получает данные из хранилища, по API;

MVVM

Model ViewModel View

  • Model. Представляет собой логику работы с данными и описание фундаментальных данных, необходимых для работы приложения;
  • ViewModel. Выступает подписчиком на событие изменения значений свойств или команд, предоставляемых ViewModel. В случае, если в ViewModel изменилось какое-либо свойство, то она оповещает всех подписчиков об этом, и View, в свою очередь, запрашивает обновлённое значение свойства из ViewModel. В случае, если пользователь воздействует на какой-либо элемент интерфейса, View вызывает соответствующую команду, предоставленную ViewModel.
  • View. С одной стороны, это абстракция View, а с другой — обёртка данных из Model, подлежащие связыванию. То есть, она содержит Model, преобразованную к View, а также команды, которыми может пользоваться View, чтобы влиять на Model;

 

Post Author: Nikulux

Добавить комментарий