Констренты
Если скопировать велью тайп его внутренние поля с ссылочными типами как будут вести ?
массив что внути как маштабируется (три вида массива) экзестентиал контейнер (rjynbyejc fhhft b ytn)
сatransaction cacommit
Excplisit animation
Pointers inout for struct Stone/Owner
Расчёт констрейнтов сразу синхронно в этом же потоке проиходит решение линейных уровнений
Вызов setNeedsLayout у Супервью (в следубщем апдейт цикле - нужно обновить фреймы всех сабВью)

Апдейт цикл - до 120 раз в секунду

1. Обновление констрейнтов
2. Обновление лайаута (Установка фрейма)
3. Отрисовка на экране

Можем поставить флаг setNeedUpdate - что бы в следующем цикле обновились фреймы.
Если хотим прямо сразу - updateConstraint и layoutIfNeeded (запустится сразу, если флаг в тру)

Если не вызовем layoutIfNeeded - данные будут не актуальны

Казуар - способ решения линейных уравнений
Создать систему ограничений
Преобразовать задачу в систему линейного программирования
Решить задачу SIMPLEX Method


Не менять констрейнты (лучше больше ячеек с identifier)

Когда мы добавляем, изменяем или удаляем constraint'ы, то они не обновляются сразу. Пересчет layout'a и обновление отрисовки при каждом изменении было бы неэффективным. Вместо этого ваши изменения планируют, что механизм layout'a, принадлежащий window, запускает обновления layout'a при следующей возможности в runloop'e.

Активация, изменение или деактивация constraints не обновляет напрямую фреймы вьюх. Вместо этого он обновляет модель the layout engine и планирует передачу макета, которая выполняется позже в цикле выполнения приложения.

  • В иерархии представлений есть два прохода макета.Первый проход позволяет вам обновить constraints. Второй проход обновляет view layout, изменяя размер и положение представлений, чтобы они соответствовали значениям из модели the layout engine.
  • Вызовите setNeedsLayout, чтобы вручную запланировать этап обновления layout'a. Вызов layoutIfNeeded для принудительного немедленного обновления view frames из модели.
В любой Момент времени Лайоут посчитан

На самом деле существует три этапа, связанные с компоновкой и рисованием видов.
Первый - это обновление ограничений (constraint pass), которое происходит снизу вверх.
Второй - это компоновка представлений и подвидов (layout pass), которая происходит сверху вниз и зависит от настроек ограничений.
Третий этап - это проход отображения, где виды перерисовываются на основе прохода макета.
Управление памятью в Swift
UIKit
Начнем с главного. Что такое ваш UIKit? Если посмотреть в официальную доку, то мы увидим такую инфу:

The UIKit framework provides the required infrastructure for your iOS or tvOS apps. It provides the window and view architecture for implementing your interface, the event handling infrastructure for delivering Multi-Touch and other types of input to your app, and the main run loop needed to manage interactions among the user, the system, and your app.

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

UIApplication, UIWindow, UIView - кто, зачем и почему?
Наше приложение стартует с имплементации экземпляра класса для UIApplication. Каждое iOS приложение имеет ровно один экземпляр UIApplication. Он маршрутизирует события пользователя, а также с помощью UIApplicationDelegate информирует о важных событиях (запуске приложения, не хватки памяти, завершении работы приложения).

  • UIApplicationMain создает экземпляр UIApplication и сохраняет этот экземпляр. К которому позже можно обращаться через UIApplication.shared
  • Затем он создает экземпляр класса делегата приложения. Система знает что это за класс, потому что мы пометили его @main (в ранних версиях @UIApplicationMain)
  • UIApplicationMain вызывает у делегата приложения метод application(_:didFinish- LaunchingWithOptions:).
  • Но интерфейс приложения не отображается, пока содержащее его window не станет ключевым окном приложения. Функция makeKeyAndVisible поможет нам
Не ожидайте, что window может быть только одно. Есть такие окна UITextEffectsWindow и UIRemoteKeyboardWindow.
Steve Jobs
Apple CEO
Главный объект, который содержит много нужной инфы для обработки событий. Когда обнаруживается системное событие, такое как прикосновение к экрану, UIKit внутри создает экземпляры UIEvent и отправляет их в очередь системных событий (main event loop), вызывая UIApplication.shared.sendEvent().
UITouch
Каждый экземпляр UIEvent содержит одно или несколько объектов UITouch. Для данного объекта UITouch могут произойти только четыре вещи. Они называются фазами касания и описываются свойством var phase: UITouch.Phase:

  • .began — Палец впервые коснулся экрана; этот экземпляр UITouch только что был создан. Это всегда первая фаза, которая наступает только один раз.
  • .moved — Палец двигается по экрану.
  • .stationary — Палец оставался на экране неподвижно. Для чего это нужно? Как только экземпляр UITouch был создан, он должен присутствовать каждый раз, когда прибывает UIEvent для этой последовательности мультитач. Таким образом, если UIEvent прибывает из-за того, что произошло что-то еще (например, новый палец коснулся экрана), UIEvent должен сообщить, что этот палец делал, даже если он ничего не делал
  • .ended — Палец покинул экран. Как и .began, эта фаза наступает только один раз. Экземпляр UITouch теперь будет уничтожен и больше не будет отображаться в UIEvents для этой последовательности мультитача.

По сути этих 4х фаз достаточно, чтобы описать все действия пальца. Но возможна еще одна фаза:

  • .cancelled — Система прервала последовательность мультитача, потому что что-то прервало ее. Возможно, пользователь нажал кнопку «Домой» или кнопку блокировки экрана в середине последовательности. Возможно, появилось локальное уведомление.

UITouch также имеет такие свойства:

  • location(in:), previousLocation(in:) — Текущее и предыдущее местоположение этого касания относительно системы координат view.
  • timestamp — Когда тач последний раз менялся. Прикосновение получает отметку времени, когда оно создается (.began) и каждый раз, когда оно перемещается (.moved)
  • tapCount — Если два касания происходят примерно в одном и том же месте в быстрой последовательности, а первое короткое, второе можно охарактеризовать как повторение первого. Это разные сенсорные объекты, но второму будет назначено значение tapCount на единицу больше, чем у предыдущего
  • view — вьюшка, c которой связано это прикосновение

Когда UITouch впервые появляется (.began), ваше приложение определяет, с каким UIView оно связано. (Позже мы узнаем как это происходит). Затем это же UIView устанавливается как свойство var view сенсорного экрана и остается им. C этого момента этот UITouch всегда связан с этим view (до тех пор, пока этот палец не покинет экран).
Main Event Loop
Когда объект приложения получает событие из очереди событий, он отправляет его в window, в котором произошло пользовательское событие. Window отправляет событие в view, которое является для него наиболее подходящим обработчиком

Сразу после запуска приложение настраивает инфраструктуру для основного цикла событий
Когда приложение запускается, оно также устанавливает основную группу объектов, которые отвечают за отрисовку UI и обработку событий. Эти основные объекты включают window и различные виды вьюшек.

Окей. Вроде все понятно. Мы узнали про главный маршрутизатор событий, узнали о самих событиях. Но как события доходят до точки исполнения?
Responder Chain
Экземпляры UIResponder — основные обработчики событий в приложении. Почти все ключевые объекты являются респондерами (UIApplication, UIWindow, UIViewController, UIView).

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

Респондеры получают необработанные данные о событии и должны либо обработать событие, либо переслать его другому объекту-респонденту. По связанному списку от реcпондера к респондеру.
Если первый респондер не может обработать сообщение о событии или действии, он пересылает его «следующему респондеру». Если объект в цепочке респондента не может обработать событие или действие, он передает сообщение следующему респондеру в цепочке. Сообщение движется вверх по цепочке к объектам более высокого уровня, пока не будет обработано. Если он не обрабатывается, то приложение отбрасывает его.
У респондера есть несколько методов обработки событий:

  • touchesBegan(_:with:) — во view или window произошло одно или несколько новых касаний.
  • touchesMoved(_:with:)Сообщает респонденту, когда одно или несколько касаний, связанных с событием, изменились.
  • touchesEnded(_:with:) — Сообщает респонденту, когда один или несколько пальцев поднимаются из вида или окна.
  • touchesCancelled(_:with:) — Сообщает респонденту, когда системное событие (например, системное предупреждение) отменяет последовательность касаний.

Аргументы этих методов:

  • touches: Set<UITouch> — множество прикосновений. Если во множестве только одно касание, то мы получаем его. Если же во множестве много то выполнится first метод (набор неупорядочен, поэтому какой элемент будет первым система выберет произвольно).
  • event: UIEvent? — сущность объекта UIEvent