Какова иерархия наследования класса UIView в UIKit?

Ответ

UIView наследуется от UIResponder. UIResponder, в свою очередь, является подклассом NSObject — корневого класса большинства иерархий в Objective-C и Cocoa Touch.

Полная цепочка наследования:

NSObject → UIResponder → UIView

Роль каждого класса в иерархии:

  1. NSObject:

    • Предоставляет базовую функциональность Objective-C runtime.
    • Реализует протокол NSObjectProtocol (например, методы isEqual(_:), hash, description).
    • Поддерживает Key-Value Observing (KVO) и Key-Value Coding (KVC).
  2. UIResponder:

    • Базовый класс для всех объектов, обрабатывающих события.
    • Определяет интерфейс для работы с цепочкой ответчиков (Responder Chain).
    • Обрабатывает события касания (touchesBegan(_:with:)), движения, нажатия кнопок, встряхивания устройства, а также события удаленного управления (например, наушников).
    • От UIResponder также наследуются UIViewController, UIApplication и UIWindow.
  3. UIView:

    • Наследуя от UIResponder, получает способность обрабатывать события.
    • Добавляет функциональность для отображения и компоновки на экране: геометрия (frame, bounds), иерархия вью (addSubview), отрисовка (draw(_:)), анимация, Auto Layout.

Пример создания кастомной вью:

class CustomView: UIView {
    // Наследует все возможности UIView и UIResponder
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }

    // Можно переопределить методы UIResponder для кастомной обработки событий
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        print("CustomView получил касание")
        // Кастомная логика
    }
}

Практический вывод: Поскольку UIView — это UIResponder, любая вью по умолчанию может стать первым обработчиком событий касания в своей области экрана, если не перехватывается другими объектами (например, кнопками).

Ответ 18+ 🔞

А, ну вот, смотри, классика жанра, блядь! Это как в том анекдоте про деда, который всем внукам рассказывал, откуда ноги растут. Так и тут — чтобы понять, что за зверь такой UIView, надо копнуть поглубже, в его родословную, ёпта.

Вот представь себе такую цепочку, прям как матрёшка, только из классов:

NSObject → UIResponder → UIView

И что же это за твари такие, блядь?

  1. NSObject — это, сука, дедушка-основатель, прародитель всей этой Objective-C банды. Он как тот алкаш во дворе, который всем даёт базовые советы по жизни: «Сынок, чтобы выжить, надо уметь isEqual и hash считать, а то тебя в словарь не положат!». Он же за KVO/KVC отвечает — это как подслушивать соседей за стенкой, не выходя из квартиры.

  2. UIResponder — это уже папаня поинтереснее. Его главная фишка — цепочка ответчиков (Responder Chain). Представь, что кто-то нахулиганил в приложении (тапнул, тряханул, кнопку нажал). Система как участковый: «Кто здесь за всё отвечает?». И начинает спрашивать по цепочке, от мелкого пацана (UIView) до самого главного (UIApplication). UIResponder — это и есть тот самый навык «умей ответить за базар». От него же и UIViewController с UIWindow пошли — вся элита, блядь.

  3. UIView — это уже наш красавчик, который унаследовал от папаши (UIResponder) умение вмазывать по ебалу событиям, а от себя добавил крутости: умеет показываться на экране (frame, bounds), плодить детишек (addSubview) и красиво шевелиться (анимации). По сути, это тот самый мужик, который и драться умеет, и хату построить может.

Вот тебе живой пример, как своего бандита замутить:

class CustomView: UIView {
    // Уже по умолчанию он и вьюха, и ответчик — два в одном, блядь!
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }

    // А тут мы можем перехватить управление, как настоящие гангста!
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        print("CustomView получил касание, ёба!")
        // Тут можно свою дичь творить, например, цвет поменять или анимацию запустить.
    }
}

А вывод-то какой, спросишь? Да хуй с горы, всё просто! Раз UIView — это UIResponder, то любая твоя вьюха из коробки уже умеет ловить тапы и прочую хуйню. Она стоит на низовом уровне в этой бандитской цепочке ответчиков. Если сверху на неё не наехала какая-нибудь кнопка (UIButton) и не перехватила событие со словами «Это моё, сука!» — то вьюха сама всё обработает. Чистая мафия, только в коде.