Говоря о механизме событий фронтенда и мобильного терминала

внешний интерфейс iOS

предисловие

В последние годы на мобильном терминале появилось большое количество отличных интерфейсных сред из-за высокой стоимости и низкой эффективности нативной разработки, а также интерфейсных сред разработки (таких как RN/Weex) специально для мобильных устройств. , упомянул. В этом контексте интерфейсные технологии постепенно станут важным навыком для мобильных разработчиков. Как разработчик мобильных терминалов, связавшись с фронтенд-разработкой, я обнаружил, что, хотя интерфейс сильно отличается от мобильного терминала, есть много вещей, которым стоит научиться у мобильного терминала, и во многих аспектах они одинаковы. , Есть и сходство. В большом кругу тем, связанных с интерфейсом, есть много общих тем, таких как: архитектура MVC и MVVM, компонентизация, адаптивное программирование, разработка (инструменты для пакетов, инструменты для управления пакетами) и так далее. Автор намерен начать с механизма событий фронтенда и мобильного энда (на примере платформы iOS), сравнить сходства и различия между методами реализации двух эндшпилей, а также обобщить механизм событий фронтенда. конец и подвижный конец.

механизм события

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

В механизме событий есть 3 самые важные вещи:

  • продюсер событий
  • объект события
  • потребитель событий

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

Вышеуказанная фигура представляет собой одностороннюю модель доставки сообщений, а сообщения событий всегда передаются производителями событий для потребителей событий. Если вы хотите сделать события и потребители мероприятия образуют двустороннюю связь, очень просто, чтобы как производители событий и потребителей событий.И тогда событие может быть передано более приемлемым объектам, событие, сгенерированное производителем событий, может соответствовать более чем одному потребителю событий:И наоборот, потребитель событий также может получать сообщения о событиях от нескольких производителей событий:

Фронтенд статьи

1. Поток событий и привязка событий

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

<html>
    <body>
        <div>
            <button id="mybtn" onclick="buttonClickHandler(event)">点我试试</button>
        </div>
    </body>
</html>
<script>
    function buttonClickHandler(event) {
        console.log('button clicked')
    }
</script>

В приведенном выше коде, если кнопка нажата, стандартное срабатывание события проходит следующие три этапа:

Мы знаем, что файл HTML на самом деле является деревом DOM, и между узлами DOM существует иерархическая связь родитель-потомок (это очень похоже на дерево представления в iOS, которое будет обсуждаться позже). В модели W3C, когда происходит какое-либо событие, захват события начинается с верхнего уровня, пока триггер события не достигнет элемента источника события.Этот процесс называется захватом события (фактически это процесс доставки события), затем событие будет следовать DOM.Иерархический путь дерева передается от дочернего узла к родительскому узлу слой за слоем, пока не достигнет документа.Этот процесс называется всплытием событий (можно также сказать, что это процесс отклика на событие). В то время как большинство браузеров следуют стандарту, в Internet Explorer поток событий нестандартен. В IE поток событий имеет только две фазы: целевую фазу и фазу всплытия.Для стандартных событий срабатывание события проходит три этапа за раз, поэтому, если мы регистрируем событие для элемента, мы можем привязывать события на соответствующем этапе, и то же самое касается удаления событий.
target.addEventListener(type, listener, useCapture);  
    // 标准注册事件函数
    // target:文档节点、document、window 或 XMLHttpRequest。
    // 函数的参数:注册事件类型type,事件的回调函数,事件注册在捕获期间还是冒泡期间
    // 例如:给button注册onclick事件,要是在捕获阶段注册,则 button.addEventListener("click",function(){},true);
target.removeEventListener(type, listener, useCapture);  //在某一个元素上撤销已注册的事件。

Вот взгляд на браузер Chromeпример:

<html>
<head>
<style>
ul{
    background : gray;
    padding : 20px;
}
ul li{
    background : green;
}
</style>
</head>
<body>
<ul>
    <li>点我试试</li>
</ul>
<script>
var ul = document.getElementsByTagName('ul')[0];
var li = document.getElementsByTagName('li')[0];
document.addEventListener('click',function(e){console.log('document clicked')},true);//第三个参数为true使用捕获
ul.addEventListener('click',function(e){console.log('ul clicked')},true);
li.addEventListener('click',function(e){console.log('li clicked')},true);
</script>
</body>
</html>

В приведенном выше коде мы создаем элемент списка, нажимаем «щелкнуть меня, чтобы попробовать» и смотрим, что происходит:

document clicked
ul clicked
li clicked

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

В IE поддерживается только механизм всплытия, поэтому привязка событий и отмена событий могут выполняться только в фазе всплытия:

target.attachEvent(type, listener);  //target: 文档节点、document、window 或 XMLHttpRequest。
                                     //函数参数: type:注册事件类型;
                                     //         listener:事件触发时的回调函数。
target.detachEvent(type,listener);   //参数与注册参数相对应。 

Давайте посмотрим на пример в браузере IE:

<html>
<body>
<ul>
    <li>点我试试</li>
</ul>
<script>
var ul = document.getElementsByTagName('ul')[0];
var li = document.getElementsByTagName('li')[0];
document.attachEvent('onclick',function(event){console.log('document clicked')})
ul.attachEvent('onclick',function(event){console.log('ul clicked')});
li.attachEvent('onclick',function(event){console.log('li clicked')});
</script>
</body>
</html>

Точно так же мы нажимаем «щелкните меня, чтобы попробовать», и в консоли инструментов разработчика печатаются следующие результаты:

li clicked
ul clicked
document clicked

Однако иногда механизм захвата событий и механизм всплытия также имеют побочные эффекты.Например, механизм всплытия вызовет функцию слушателя на родительском узле, которая не должна была быть запущена, поэтому есть ли способ сделать всплывающее завершение преждевременным? Нам нужно только вызвать функцию stopPropagation объекта события (cancelBubble в браузере IE), чтобы остановить всплывающую подсказку события в той позиции, в которой мы хотим, чтобы событие прекратило всплывающую подсказку. Например, измените пример кода в приведенном выше браузере IE следующим образом:

li.attachEvent('onclick',function(event){
    console.log('li clicked');
    event.cancelBubble=true;
});

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

li clicked

2. Делегация мероприятия

Что такое делегирование событий??
Делегирование событий — это использование механизма всплытия событий для назначения обработчика событий для управления всеми событиями определенного типа. Определение этого делегирования события недостаточно простое и ясное, и некоторые люди могут до сих пор не понимать, что такое делегирование события. Я проверил, что многие Дэниелс в Интернете используют пример получения экспресса при объяснении делегирования событий для объяснения делегирования событий, но размышление об этом примере действительно вполне уместно и наглядно, поэтому давайте рассмотрим этот пример непосредственно, чтобы объяснить делегирование событий. означает:
Сотрудники компании часто получают экспресс-доставку. Чтобы облегчить получение экспресс-доставки, есть два способа: один заключается в том, что получатели отправляются забрать экспресс после прибытия экспресса; другой - поручить стойке регистрации ММ расписаться за экспресс, а стойке регистрации MM подпишется на экспресс по мере необходимости после получения экспресса. Очевидно, что второе решение удобнее и эффективнее, но в то же время у этого решения есть и преимущество, то есть даже в случае прихода нового сотрудника ММ на стойке регистрации может подменить нового сотрудника, чтобы расписаться в экспресс-доставке.
Причина, по которой этот пример очень уместен, заключается в том, что он содержит два значения делегирования:
Во-первых, теперь сотрудники в компании могут доверить расписку ММ на стойке регистрации, то есть существующие в программе узлы домохозяйства имеют события и могут доверить событие; во-вторых, вновь принятые на работу новые сотрудники также могут попросите ММ на стойке регистрации расписаться за экспресс-доставку, т.е. Недавно добавленный узел dom в программе также имеет события, а также может делегировать события обработки.

Зачем использовать делегирование событий??
Когда модели DOM необходимо обрабатывать события, мы можем добавить обработчики событий непосредственно в модель DOM, но что делать, если для обработки событий требуется множество моделей моделей DOM? Например, в ul есть 100 li, и каждый li должен обрабатывать событие click, тогда мы можем обойти все li и добавить к ним обработчики событий, но как это повлияет? Мы знаем, что количество обработчиков событий, добавленных на страницу, напрямую повлияет на общую производительность страницы, поскольку требует постоянного взаимодействия с узлом DOM. раз, тем больше, естественно, будет интерактивное время готовности страницы, поэтому операцию dom можно сократить для оптимизации производительности страницы; а если мы используем делегирование, мы можем поместить операцию события в js, чтобы соответствовать операции dom.Операцию можно сократить до одного раза, что значительно сократит количество взаимодействий с узлом dom и повысит производительность. В то же время унифицированное управление событийными операциями также позволяет экономить память, ведь каждая js-функция является объектом, который естественно будет занимать память, тем более, а с помощью делегатов мы можем лишь добавить обработчики событий к родительскому узлу dom, что, естественно, экономит много памяти и повышает производительность.
Как реализовать делегирование событий? Из-за механизма всплытия, поскольку событие щелчка родительского элемента также запускается при щелчке дочернего элемента. Затем мы можем передать событие щелчка по дочернему элементу самому внешнему родительскому элементу, чтобы сделать это, и позволить событию подняться до самого внешнего узла dom, чтобы вызвать обработчик события, который является делегированием события.
Прежде чем представить метод делегирования событий, давайте посмотрим, как обрабатывать события.общий метод:

<ul id="list">
    <li id="item1" >item1</li>
    <li id="item2" >item2</li>
    <li id="item3" >item3</li>
</ul>
  
<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
  
item1.onclick = function(event){
    alert(event.target.nodeName);
    console.log("hello item1");
}
item2.onclick = function(event){
    alert(event.target.nodeName);
    console.log("hello item2");
}
item3.onclick = function(event){
    alert(event.target.nodeName);
    console.log("hello item3");
}
</script>

Смысл приведенного выше кода очень прост, он заключается в том, чтобы привязать событие клика к каждому узлу li в списке.При нажатии на li вам нужно один раз найти позицию целевого li и выполнить обработчик события.
Итак, что мы делаем с делегированием событий (Посмотреть пример)?

<ul id="list">
    <li id="item1" >item1</li>
    <li id="item2" >item2</li>
    <li id="item3" >item3</li>
</ul>
  
<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
var list = document.getElementById("list");
list.addEventListener("click",function(event){
 var target = event.target;
 if(target == item1){
    alert(event.target.nodeName);
    console.log("hello item1");
 }else if(target == item2){
    alert(event.target.nodeName);
    console.log("hello item2");
 }else if(target == item3){
    alert(event.target.nodeName);
    console.log("hello item3");
 }
});
</script>

Мы добавляем событие щелчка к родительскому узлу.При щелчке дочернего узла событие щелчка всплывает из дочернего узла. После того, как родительский узел перехватывает событие, он определяет, является ли этот узел тем, который нам нужно обработать, оценивая event.target, чтобы можно было получить и обработать соответствующую информацию. Очевидно, что метод использования делегирования событий может значительно снизить сложность кода, при этом снизив вероятность ошибок.
Давайте посмотрим на преимущества использования делегирования событий, когда мы динамически добавляем dom? Сначала посмотримнормальное письмо:

<ul id="list">
    <li id="item1" >item1</li>
    <li id="item2" >item2</li>
    <li id="item3" >item3</li>
</ul>
  
<script>
var list = document.getElementById("list");
  
var item = list.getElementsByTagName("li");
for(var i=0;i<item.length;i++){
    (function(i){
        item[i].onclick = function(){
            alert(item[i].innerHTML);
        }
    })(i);
}
  
var node=document.createElement("li");
var textnode=document.createTextNode("item4");
node.appendChild(textnode);
list.appendChild(node);
  
</script>

Нажатие элемента 1 на элемент 3 вызывает реакцию на событие, но при нажатии элемента 4 реакция на событие отсутствует. Он показывает, что традиционная привязка событий не может динамически добавлять события к динамически добавляемым элементам.
А что если использовать метод делегирования событий (Посмотреть пример)?

<ul id="list">
    <li id="item1" >item1</li>
    <li id="item2" >item2</li>
    <li id="item3" >item3</li>
</ul>
  
<script>
var list = document.getElementById("list");
  
document.addEventListener("click",function(event){
    var target = event.target;
    if(target.nodeName == "LI"){
        alert(target.innerHTML);
    }
});
  
var node=document.createElement("li");
var textnode=document.createTextNode("item4");
node.appendChild(textnode);
list.appendChild(node);
  
</script>

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

Мобильный терминал (iOS)

Когда мы говорим о событиях в вебе, мы будем говорить о способах захвата и доставки событий (пузырьковая), тогда и на мобильной стороне эти проблемы также неразделимы.Далее мы представим iOS с этих аспектов.Механизм событий: 1 , Как найти наиболее подходящие элементы управления для обработки событий? 2. После нахождения первого ответившего на событие, как реагирует событие?

Генерация и передача событий

События в iOS можно разделить на 3 основных типа:

  • сенсорное событие
  • событие акселерометра
  • событие дистанционного управления

Здесь мы обсуждаем только самые распространенные сенсорные события в iOS.

объект ответчика

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

- (nullable UIResponder*)nextResponder;
- (BOOL)canBecomeFirstResponder;    // default is NO
- (BOOL)becomeFirstResponder;
- (BOOL)canResignFirstResponder;    // default is YES
- (BOOL)resignFirstResponder;
- (BOOL)isFirstResponder;
  
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

Когда происходит событие касания, система будет вызывать четыре вышеуказанных метода на разных этапах касания.

возникновение событий

  • После возникновения сенсорного события система добавляет это событие в очередь событий, управляемую UIApplication.
  • UIApplication возьмет фронтальное событие из очереди событий и распространит событие, сначала отправив событие в главное окно приложения (keyWindow).
  • Главное окно найдет наиболее подходящее представление в иерархии представлений для обработки сенсорных событий.
  • После нахождения подходящего элемента управления представлением будет вызван метод touchs элемента управления представлением для обработки определенного события.

доставка событий

В нашем приложении все представления организованы по определенной структуре, то есть древовидной иерархии, и у каждого представления есть свой superView, в том числе самое верхнее представление контроллера (self.view контроллера). Когда представление добавляется в superView, его свойство nextResponder будет указывать на его superView.При инициализации контроллера nextResponder из self.view (самое верхнее представление) будет указывать на контроллер, в котором он расположен, а nextResponder из будет указан контроллер.Будет указан superView для self.view.

Как приложение находит наиболее подходящий элемент управления для обработки события?

  • Сначала определите, может ли текущее управление принимать сенсорные события;
  • Определите, находится ли точка касания на себе;
  • Переместите вспомогательные элементы управления сзади на передний план в массиве вспомогательных элементов управления текущего элемента управления и повторите предыдущие два шага (так называемый обход вспомогательных элементов управления сзади на передний план заключается в том, чтобы сначала найти последний элемент в массиве. массив субэлементов управления, а затем выполнить шаги 1 и 2);
  • В вышеописанном процессе, если будет найдено подходящее представление, например, оно называется fitView, то событие будет передано в fitView, а затем будут проходиться дочерние элементы управления fitView до тех пор, пока не найдется более подходящее представление;
  • Если нет квалифицирующего детского контроля, то считаю себя наиболее подходящим для борьбы с этим инцидентом, то есть он является наиболее подходящим видом.

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

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

Конкретные принципы см.:Метод hitTest доставки событий iOS и метод PointInside.

2. Реагирование на инцидент

цепочка респондентов

Все элементы управления в IOS View организованы в соответствии с определенной иерархической структурой, то есть элементы управления помещаются в последовательность, а элементы управления, которые могут реагировать на события, образуют цепочку в соответствии с этой последовательностью, которая называется «цепь респорта ". Также можно сказать, что цепь респондента - это цепь, соединенная множественными объектами респондента. Как упоминалось ранее, Uiresponder является базовым классом для всех объектов респондента, а интерфейсы для обработки различных событий определены в классе UIRESPONDER. Uiagiclation, UiviewController, Uiwindow и все классы Uikit, которые наследуют от UIView прямо или косвенно наследуют от UIRESPONDER, поэтому их экземпляры являются объектами респондента, которые могут образовывать цепь респондента. Отношения цепочки ответчика в IOS могут быть использованы сСледующий рисунокВыражать:

Ниже мы объясняем процесс доставки событий на основе диаграммы цепочки ответчиков: - Если текущее представление является представлением контроллера, то контроллер (viewController) является последним ответившим, и событие передается контроллеру; если текущее представление не является представлением контроллера, то родительским является представление последний ответчик текущего представления. Событие передается родительскому представлению; - Если самое верхнее представление иерархии представлений также не может обработать полученное событие, оно передает событие объекту окна для обработки; - Если объект окна не может обработать событие, он передает событие объекту UIApplication; - Если UIApplication также не может обработать событие, отбросить его.

Когда представление реагирует на событие касания, оно автоматически вызывает собственный метод касания для обработки события:

#import "DYView.h"
@implementation DYView
    //只要点击控件,就会调用touchBegin,如果没有重写这个方法,就不能响应处理触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    ...
    // 默认会把事件传递给上一个响应者,上一个响应者是父控件,交给父控件处理
    [super touchesBegan:touches withEvent:event];
    // 注意不是调用父控件的touches方法,而是调用父类的touches方法,最终会把事件传递给nextResponder
}
@end

Независимо от того, может ли текущий дочерний элемент управления обработать событие, событие будет передано родительскому элементу управления (предыдущему респонденту).Если родительский элемент управления реализует метод касаний, событие касания будет обработано, что означает, что может выполняться только одним элементом управления. Обработка также может выполняться несколькими элементами управления в ответ. Таким образом, весь процесс доставки и ответа на сенсорное событие можно резюмировать следующим образом:

  • При возникновении события событие будет распространяться UIApplication по цепочке доставки, а именно UIApplication -> UIWindow -> UIView -> начальное представление, пока не будет найдено наиболее подходящее представление.
  • После наиболее подходящего представления начните реагировать на событие: сначала посмотрите, может ли начальное представление обработать событие, если нет, оно передаст событие вышестоящему представлению; если вышестоящее представление все еще не может его обработать, оно продолжать пропускать вверх; передавать его до контроллера представления контроллера представления; если нет, то судить, может ли контроллер представления обработать это событие, а если все еще не может, продолжать пропускать его вверх; (для второго представления сам контроллер все еще находится в другом контроллере представления, продолжайте передавать его родительскому корневому представлению контроллера представления, если корневое представление не может его обработать, оно будет передано родительскому контроллеру представления); до окна, если окно по-прежнему не может обработать это событие, оно будет по-прежнему передаваться приложению для обработки, и если приложение по-прежнему не может обработать это событие в конце, оно будет отброшено.
  • В ответе на событие, если элемент управления реализует метод touches, событие будет принято элементом управления.Если [super touchs....] вызывается, событие будет передано вверх по цепочке респондента и передано в верхний A ответчик; затем вызывается метод touches предыдущего ответчика.

3. Привязка событий и делегирование событий

привязка события

При разработке приложений для iOS часто используются различные элементы управления, такие как кнопки (UIButton), переключатели (UISwitch), ползунки (UISlider) и т. д., а также различные настраиваемые элементы управления. Эти элементы управления используются для взаимодействия с пользователем и реагирования на действия пользователя. У этих элементов управления есть одна общая черта: все они наследуются от класса UIControl. UIControl — это базовый класс класса управления. Это абстрактный базовый класс. Мы не можем напрямую использовать класс UIControl для создания экземпляров элементов управления. Он просто определяет некоторые общие интерфейсы для подклассов элементов управления и предоставляет некоторые базовые реализации. Когда происходит событие, Preprocess эти сообщения и отправить их указанному целевому объекту.
Привязка событий в iOS — это механизм Target-Action, и его работа в основном использует следующие два метода:

// 添加绑定
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
// 解除绑定
- (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

Когда нам нужно привязать событие клика к элементу управления (например, к кнопке), мы можем сделать следующее:

[button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];

Когда происходит событие щелчка кнопки, сообщение будет отправлено цели (здесь — объекту self), и метод clickButton: целевого объекта запускается для обработки события щелчка. Этот процесс можно описать следующей схемой:

Поэтому механизм Target-Action состоит из двух частей: целевого объекта и селектора поведения. Целевой объект указывает объект конечного события обработки, а селектор поведения — это метод обработки события. Что делать, если цель целевого объекта пуста? Если мы не укажем Target, событие будет распределено первому объекту, который захочет обработать сообщение в цепочке ответа, то есть если респондер в цепочке, если он найден, то вызов, иначе никак. Например следующий код:
[button addTarget:nil action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];

Целевой объект приведенного выше кода равен нулю, затем он сначала проверит, реализует ли сам класс кнопки clickButton: этот метод, если этот метод реализован, он будет вызван, иначе он найдет кнопку.nextResponder в соответствии с цепочкой респондентов , и еще раз проверьте, реализован ли метод clickButton:, пока UIApplication (собственно AppDelegate), если он еще не реализован, ничего не делайте.

агент событий

В IOS делегирование реализовано через метод @protocol, поэтому его также называют протоколом. Протокол — это список методов, совместно используемых несколькими классами. Методы, перечисленные в протоколе, не имеют соответствующих конкретных реализаций (эквивалентных интерфейсам). Методы в протоколе реализуются классом, который использует протокол.
Делегирование относится к предоставлению объекту возможности реагировать на изменения в другом объекте или влиять на поведение другого объекта. Основная идея такова: два объекта работают вместе для решения проблем. Объект очень общий и предназначен для повторного использования в широком диапазоне ситуаций. Он хранит ссылку на другой объект (то есть на своего делегата) и отправляет сообщения делегату в критические моменты. Сообщение может просто информировать делегата о том, что что-то произошло, предоставляя делегату возможность выполнить дополнительную обработку, или сообщение может просить делегата предоставить некоторую важную информацию для управления тем, что произошло.
В следующем примере используется пример, иллюстрирующий конкретное применение агента в разработке iOS:
Взяв в качестве примера экспресс-доставку, сотрудник может доверить MM на стойке регистрации подписать экспресс-доставку, поэтому между сотрудником и MM на стойке регистрации существует протокол:

@protocol signDelegate <NSObject>
- (void)signTheExpress;
@end

Этот протокол объявляет метод для подписи экспресса (signTheExpress).
Сотрудник может быть представлен классом, определенным ниже:

##employer.h
  
@protocol signDelegate <NSObject>
- (void)signTheExpress;
@end
 
@interface employer : NSObject
/**
 * delegate 是employer类的一个属性
 */
@property (nonatomic, weak) id<signDelegate> delegate;
- (void)theExpressDidArrive;
@end
employer.m
#import "employer.h"
 
@implementation employer
- (void)theExpressDidArrive{
    if ([self.delegate respondsToSelector:@selector(signTheExpress)]) {
        [self.delegate signTheExpress];
    }
}
@end

Давайте взглянем на реализацию внешнего класса MM:

#import "receptionMM.h"
#import "employer.h"
 
@interface receptionMM ()<signDelegate>  //<signDelegate>表示遵守signDelegate协议,并且实现协议里面的方法
 
@end
 
@implementation receptionMM
/**
 * 快递员到了
 */
- (void)theCourierCome{
    DaChu *employer1 = [[employer alloc] init];
    employer1.delegate = self; //说明前台MM充当代理的角色。
    [employer1 theExpressDidArrive]; //某个员工的快递到了
}
- (void)signTheExpress{
    NSLog(@"快递签收了");
}
@end

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

Суммировать

Хотя разработка внешнего интерфейса и мобильного терминала сильно различается, с точки зрения механизма событий между ними существует много схожих концепций: например, концепция количества DOM во внешнем интерфейсе. очень похоже на дерево представления на странице приложения, и захват событий внешнего интерфейса очень похож.Есть также сходство с механизмом всплытия и цепочкой доставки и механизмом цепочки ответов событий iOS, а также концепциями привязка событий и делегирование событий на обоих концах. Однако из-за в высокой степени объектно-ориентированных характеристик элементов мобильной страницы механизм обработки событий относительно сложнее, а цели применения некоторых шаблонов проектирования различны. Например, во фронтенд-разработке делегирование событий в основном предназначено для уменьшения сложности кода, а в iOS-разработке — для решения проблемы разделения модулей.
И есть много отличных фреймворков для фронтенда и мобильных платформ, так что еще многое предстоит рассказать о механизме событий фронтенда и мобильных устройств, таких как Event Bus Vue.js и унифицированный механизм обработки сообщений. в ReactiveCocoa Обсудить еще раз.

использованная литература

1,Механизм событий iOS