Где хранятся статические (`static`) переменные в Swift и каков их жизненный цикл?

Ответ

Статические переменные (объявленные с ключевым словом static) хранятся в области памяти, называемой сегментом данных (Data Segment/BSS). Это память, выделяемая при запуске приложения и существующая до его завершения.

Ключевые характеристики:

  • Время жизни: Существуют на протяжении всей работы программы. Инициализируются один раз (лениво, при первом обращении, если не указано иное).
  • Область видимости: Ограничена областью видимости типа (класса, структуры, перечисления), в котором они объявлены.
  • Потокобезопасность: Инициализация по умолчанию потокобезопасна в Swift.

Примеры и использование:

  1. Статическое свойство типа:

    class AppSettings {
        static let version = "1.0.0" // Хранится в data segment
        static var launchCount = 0   // Хранится в data segment, значение сохраняется между запусками (если его записать в UserDefaults)
    }
    print(AppSettings.version) // Обращение через имя типа
  2. Локальная статическая переменная в функции:

    func generateUniqueID() -> Int {
        static var counter = 0 // Хранится в data segment, но видима только внутри этой функции
        counter += 1
        return counter
    }
    print(generateUniqueID()) // 1
    print(generateUniqueID()) // 2 // Значение сохраняется между вызовами!
  3. class для вычисляемых свойств в классах (только для классов):

    class AbstractShape {
        class var defaultColor: String { return "black" } // Может быть переопределен в подклассе
        static let immutableID = "SHAPE" // Не может быть переопределен
    }

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

Ответ 18+ 🔞

А, ну это же про статик, блядь! Ну, слушай, сейчас разжуем, как сука, на пальцах.

Вот представь, есть у тебя память программы, да? И там такая специальная полочка, сегмент данных называется. Так вот, когда ты пишешь static, ты по сути говоришь: "Эй, система, положи эту переменную на ту самую полочку, и пусть она там лежит, пока я приложение не закрою, нахуй". Всё, приехали. Она не в стеке, которая там всплывает и исчезает, как последняя надежда, а именно на постоянке.

Что это за зверь такой:

  • Живёт как Мафусаил: Создалась один раз — и пиздуй до самого завершения программы. Инициализируется лениво, то есть когда ты к ней первый раз полез, а не раньше.
  • Видна только своим: Сидит внутри своего класса или структуры, как в бункере. Снаружи не торчит, глобальное пространство имён не засирает — красота, блядь.
  • Потоки не порвут: В Свифте за тебя сделали, инициализация по умолчанию потокобезопасная, можешь не бздеть.

Ну и где это, сука, применять?

  1. Статик свойство прямо в типе:

    class AppSettings {
        static let version = "1.0.0" // Сидит на той самой полочке в data segment
        static var launchCount = 0   // Тоже там. Хочешь между запусками сохранить — пихни в UserDefaults, гений.
    }
    print(AppSettings.version) // Достучался через имя типа — и всё, красава.
  2. Локальный статик внутри функции (вообще пиздецкая штука):

    func generateUniqueID() -> Int {
        static var counter = 0 // Живет на вечной полке, но видна ТОЛЬКО тут, внутри!
        counter += 1
        return counter
    }
    print(generateUniqueID()) // 1
    print(generateUniqueID()) // 2, блядь! Значение-то сохранилось! Вот это магия, ёпта!
  3. class для вычисляемых свойств (только в классах, ебать их в сраку):

    class AbstractShape {
        class var defaultColor: String { return "black" } // Это можно в наследниках переписать
        static let immutableID = "SHAPE" // А это уже нет, хрен вам, статично и неизменно.
    }

И главное, чувак, не путай это с глобальными переменными, которые валяются где попало. Статик — он прибранный, инкапсулированный в свой тип. Порядок, блядь, а не бардак.