Что такое синглтон и как его правильно реализовать
Что проверяют
Знаете ли вы, как в Swift правильно получить единственный экземпляр, и понимаете ли, чем глобальная точка доступа мешает тестам и многопоточности. Следом почти всегда спрашивают, как протестировать код, который зовёт .shared, и чем синглтон заменить.
Как отвечать
Синглтон гарантирует один экземпляр типа и даёт к нему глобальный доступ. В Swift каноническая реализация занимает три строки:
static let shared = Service(): статические свойства инициализируются лениво, при первом обращении, и потокобезопасно, рантайм сам делает это ровно один раз. Ручнойdispatch_onceили блокировки вокруг создания не нужны;private init(): запрещает создать второй экземпляр снаружи;final class: синглтон должен быть ссылочным типом,structпри каждом присваивании копируется, и «единственности» не будет.
Важно разделить две вещи: создание экземпляра безопасно, а изменяемое состояние внутри нет. Если сервис хранит кеш или токен, доступ к нему нужно защищать: actor, серийная очередь, OSAllocatedUnfairLock или Mutex из фреймворка Synchronization. В режиме Swift 6 компилятор сам этого потребует: static let с не-Sendable типом даёт ошибку, и решением будет Sendable-тип, actor или изоляция через @MainActor.
Примеры из системы: URLSession.shared, UserDefaults.standard, FileManager.default. Чтобы код с синглтоном тестировался, прячьте его за протоколом и передавайте через инициализатор с дефолтом: init(api: APIClient = NetworkService.shared). В тесте подставляется заглушка, в продакшене работает общий экземпляр.
Где спотыкаются
Добавляют DispatchQueue.sync или замок вокруг создания shared, не зная, что static let уже потокобезопасен, и при этом оставляют без защиты сами изменяемые поля.
Зовут Singleton.shared прямо из глубины бизнес-логики. Зависимость становится скрытой, в тестах состояние перетекает из одного теста в другой, а подменить сервис нечем.
Превращают синглтон в свалку: AppManager с сетью, базой и настройками. Хороший ответ называет, где синглтон уместен (действительно единственный ресурс вроде логгера), а где лучше внедрение зависимостей.