TGViewer
Мобильный трудоголик Мобильный трудоголик @hardworkerit · 1.65K subscribers
Post #152 1.13K
🔢 Погружение в диспетчеризацию методов Swift.

Если вы когда-то спорили с коллегами о том, стоит ли помечать классы final для оптимизации производительности, сохраните эту статью. Она разложит все по полочкам.


⚠️ Основные типы диспетчеризации в Swift.

Swift использует два принципиально разных подхода:
🔸 Статическая диспетчеризация: быстрая, но менее гибкая.
🔸 Динамическая диспетчеризация: медленнее, зато поддерживает полиморфизм.

Динамическая диспетчеризация может негативно влиять на производительность из-за:
🔸 Потери возможности оптимизации кода.
🔸 Увеличения вероятности кэш-промахов CPU.
🔸 Накладных расходов на поиск метода в таблицах.

Ключевой момент: если компилятор может определить адрес метода на этапе компиляции — используется статическая диспетчеризация. Иначе динамическая.


1️⃣ Статическая диспетчеризация.

Встраивание (Inlining):

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

♣️ Пример:


func square(_ x: Int) -> Int {
return x * x
}

let result = square(5)

// После оптимизации компилятор может превратить это в:
let result = 5 * 5 // 25 (вычислено на этапе компиляции!)


Прямая диспетчеризация (Direct Dispatch):

Используется для:
🔹 Структур.
🔹 Перечислений.
🔹 final классов.
🔹 static и private методов.

Почему это быстро?
Адрес метода известен заранее: CPU выполняет его за одну инструкцию.


2️⃣ Динамическая диспетчеризация.

Табличная (Virtual Table):

Каждый класс хранит таблицу методов. При вызове:
🔹 CPU ищет адрес метода в таблице.
🔹 Переходит по нему.

♣️ Пример:


class Animal {
func sound() {
}
}

class Dog: Animal {
override func sound() {
}
}

let pet: Animal = Dog()
pet.sound() // Динамически выбирается Dog.sound()



Протокольная (Witness Table):

Аналогично табличной, но для протоколов:


protocol Drawable {
func draw()
}

struct Circle: Drawable {
func draw() {
}
}

let shape: Drawable = Circle()
shape.draw() // Вызов через witness table



3️⃣ Message Dispatch (Obj-C Runtime).

Самая гибкая, но медленная диспетчеризация через Objective-C runtime:


class MyClass: NSObject {
@objc dynamic func message() {
}
}
// Вызов через objc_msgSend


Особенности:
🔹 Позволяет модифицировать поведение методов в runtime (swizzling).
🔹 Используется для KVO, Core Data и совместимости с Objective-C.


❌ Известные проблемы диспетчеризации.

🔸 Проблема 1:


protocol P {
}

extension P {
func foo() {
print("Protocol")
}
}

class A: P {
func foo() {
print("Class")
}
}

let instance = A()
instance.foo() // Выведет: Class, динамическая диспетчеризация

let instance2: P = A()
instance2.foo() // Выведет: Protocol, статическая диспетчеризация


Решение проблемы:

protocol P {
func foo() // Добавили метод в протокол
}

extension P {
func foo() {
print("Protocol")
}
}

class A: P {
func foo() {
print("Class")
}
}

let instance = A()
instance.foo() // Выведет: Class, динамическая диспетчеризация

let instance2: P = A()
instance2.foo() // Выведет: Class, динамическая диспетчеризация


🔸 Проблема 2:


protocol P {
func foo()
}

extension P {
func foo() {
print("Protocol")
}
}

class A: P {
}

class B: A {
func foo() {
print("Class")
}
}

let instance = B()
instance.foo() // Выведет: Class

let instance2: A = B()
instance2.foo() // Выведет: Protocol


Решение проблемы:

protocol P {
func foo()
}

extension P {
func foo() {
print("Protocol")
}
}

class A: P {
func foo() { // Нужно реализовать метод
}
}

class B: A {
override func foo() {
print("Class")
}
}

let instance = B()
instance.foo() // Выведет: Class

let instance2: A = B()
instance2.foo() // Выведет: Class



💡Вывод:

Используйте final и private там, где это возможно, чтобы компилятор мог оптимизировать код. Динамическая диспетчеризация — мощный инструмент, но не всегда нужен. Баланс между гибкостью и производительностью — ключ к эффективному коду.


➡️ Подписаться на канал
Мобильный трудоголик
  • ❤ 20
  • 🔥 16
  • 👍 2
  • 🙏 1
  • 🫡 1
More from @hardworkerit
  1. Oct 9, 2026👨‍💻 Умение адаптироваться - важный навык айтишника, который часто недооценивают. В ИТ не…
  2. Oct 8, 2026🈸 Apple обяжет разработчиков поддерживать iPhone Duo. Apple опубликовала требования к при…
  3. Oct 6, 2026🔢 Swift 6.4: новая диагностика ретейн циклов. В Swift 6.4 появилась новая диагностика, ко…
  4. Oct 4, 2026🔢 SwiftUI: определение угла раскрытия iPhone Duo. В iOS 27.1 появился модификатор .onHing…
  5. Oct 2, 2026👣 Архитекторы, тестировщики и кодеры. Создаем мультиагентную команду Разработка с ИИ-аген…
  6. Oct 1, 2026🔢 Работа с Picture-in-Picture в iOS. Picture-in-Picture - системная функция iOS, которая…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →