9. Что такое Message Dispatch и какие у него есть достоинства и недостатки?Теория

Темы

Компании

Ответ

Message Dispatch. Метод ищут в runtime Objective-C по селектору. У класса для этого есть свой список, в каждой записи селектор и адрес нужного метода. Runtime идет по списку класса, потом по списку родителя, пока не найдет селектор. Нашли селектор, из этой же записи берут адрес метода и вызывают его.

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

Достоинства:

  • Реализацию можно менять во время выполнения. Например, method swizzling: у селектора в списке класса подменяют адрес тела метода.
  • На этом стоят KVO, Target-Action и вызов по #selector.
  • После первого поиска селектор кэшируют. Следующий вызов с тем же именем уже не обходит весь список методов.

Недостатки:

  • Самый медленный вид диспетчеризации. Даже с кэшем это тяжелее прямого вызова и virtual table.
  • Нужен runtime Objective-C. Для метода Swift это @objc dynamic у наследника NSObject.

Так работают:

  • Методы с @objc dynamic у наследников NSObject. Даже вызов из Swift идет по селектору.
  • Target-Action. Например, кнопка вызывает метод по #selector.
  • KVO у свойств @objc dynamic. Можно подписаться на изменение свойства, runtime сам вызовет код, когда значение поменяется.

Message dispatch ищет метод во время выполнения через objc_msgSend. Так работают @objc, наследники NSObject и dynamic. Поиск идёт по классу и его родителям, поэтому метод можно переопределить и даже подменить, как в swizzling. Это самый гибкий и самый дорогой из трёх способов. Компилятор почти не встраивает такой вызов: адрес заранее неизвестен.

  • плюс: переопределение, KVO и подмена метода
  • минус: поиск при каждом вызове и почти нет inlining