ar
Feedback
Swift | Вопросы собесов

Swift | Вопросы собесов

الذهاب إلى القناة على Telegram
2 181
المشتركون
-324 ساعات
-27 أيام
-1430 أيام
جذب المشتركين
أغسطس '26
أغسطس '26
+24
في 0 قنوات
يوليو '26
+18
في 0 قنوات
Get PRO
يونيو '26
+32
في 1 قنوات
Get PRO
مايو '26
+21
في 0 قنوات
Get PRO
أبريل '26
+23
في 0 قنوات
Get PRO
مارس '26
+35
في 0 قنوات
Get PRO
فبراير '26
+45
في 1 قنوات
Get PRO
يناير '26
+58
في 0 قنوات
Get PRO
ديسمبر '25
+28
في 0 قنوات
Get PRO
نوفمبر '25
+156
في 1 قنوات
Get PRO
أكتوبر '25
+26
في 0 قنوات
Get PRO
سبتمبر '25
+41
في 0 قنوات
Get PRO
أغسطس '25
+38
في 0 قنوات
Get PRO
يوليو '25
+27
في 0 قنوات
Get PRO
يونيو '25
+34
في 0 قنوات
Get PRO
مايو '25
+50
في 0 قنوات
Get PRO
أبريل '25
+87
في 0 قنوات
Get PRO
مارس '25
+151
في 2 قنوات
Get PRO
فبراير '25
+123
في 1 قنوات
Get PRO
يناير '25
+127
في 53 قنوات
Get PRO
ديسمبر '24
+55
في 1 قنوات
Get PRO
نوفمبر '24
+75
في 0 قنوات
Get PRO
أكتوبر '24
+193
في 42 قنوات
Get PRO
سبتمبر '24
+348
في 251 قنوات
Get PRO
أغسطس '24
+98
في 0 قنوات
Get PRO
يوليو '24
+140
في 54 قنوات
Get PRO
يونيو '24
+411
في 244 قنوات
Get PRO
مايو '24
+646
في 191 قنوات
Get PRO
أبريل '24
+353
في 23 قنوات
التاريخ
نمو المشتركين
الإشارات
القنوات
30 أغسطس+1
29 أغسطس0
28 أغسطس0
27 أغسطس+4
26 أغسطس+1
25 أغسطس0
24 أغسطس+3
23 أغسطس0
22 أغسطس+2
21 أغسطس0
20 أغسطس0
19 أغسطس+1
18 أغسطس0
17 أغسطس+2
16 أغسطس0
15 أغسطس0
14 أغسطس+2
13 أغسطس+1
12 أغسطس+1
11 أغسطس0
10 أغسطس0
09 أغسطس0
08 أغسطس0
07 أغسطس+1
06 أغسطس0
05 أغسطس+2
04 أغسطس+2
03 أغسطس0
02 أغسطس+1
01 أغسطس0
منشورات القناة
🤔 Как решить проблему race condition? Race condition — это ошибка, возникающая при одновременном доступе нескольких потоков к одним и тем же данным без должной синхронизации. Для решения проблемы race condition в Swift используются механизмы синхронизации, такие как блокировки (locks), семафоры или серийные очереди GCD. Эти инструменты позволяют ограничить доступ к общим ресурсам, чтобы только один поток мог их изменять в любой момент времени. Это предотвращает непредсказуемое поведение программы и ошибки при многопоточном доступе к данным. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

2
🤔 Какой путь проделывает ивент , когда пользователь нажимает на приложение? Когда пользователь нажимает на иконку приложения на домашнем экране, iOS проходит несколько этапов перед тем, как приложение становится активным. 🚩Разберём путь события подробнее 🟠Пользователь нажимает на иконку (SpringBoard) iOS-устройства управляются системой SpringBoard – это оболочка, отвечающая за домашний экран, иконки, фоновые процессы. Когда пользователь тапает на иконку приложения, SpringBoard отправляет событие UIApplicationLaunchOptionsKey в систему. 🟠iOS загружает процесс приложения Если приложение не запущено: - iOS создаёт новый процесс и выделяет память. - Загружаются зависимости (библиотеки, фреймворки). - Создаётся объект UIApplication. 🟠Вызывается `application(_:didFinishLaunchingWithOptions:)` Здесь приложение инициализируется и загружается основной UI. Метод в AppDelegate: func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { print("Приложение запущено") return true } Ставь 👍 и забирай 📚 Базу знаний
137
3
🤔 Счётчик ссылок дошёл до нуля — в какой момент удалим объект? Как только счётчик ссылок объекта становится равным нулю, ARC немедленно освобождает память. Удаление происходит автоматически в этот момент, и вызывается деинициализатор (deinit), если он реализован. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
156
4
🤔 Что такое gitflow? В основе Git Flow – несколько веток с разными ролями, чтобы команда могла параллельно разрабатывать новые фичи, исправлять баги и выпускать релизы. 🚩Как работает Git Flow? 🟠Основные ветки (`main` и `develop`) - main – содержит только стабильные версии. - develop – основная ветка разработки, в неё вливаются все новые фичи. 🟠Разработка новых фич (feature branches) - Каждая новая фича создаётся в отдельной ветке feature/*. - После завершения сливается в develop. git checkout develop git checkout -b feature/new-cool-feature # Разработка... git checkout develop git merge feature/new-cool-feature git branch -d feature/new-cool-feature 🟠Подготовка к релизу (release branches) - Когда код стабилен, создаётся ветка release/* от develop. - Здесь можно тестировать и исправлять баги. - После финального теста сливается в main и develop. git checkout develop git checkout -b release/1.0 # Фиксим баги, тестируем... git checkout main git merge release/1.0 git tag -a v1.0 -m "Release 1.0" git checkout develop git merge release/1.0 git branch -d release/1.0 🟠Горячие фиксы (hotfix branches) - Если критический баг в main, создаём hotfix/*. - После исправления вливаем в main и в develop. git checkout main git checkout -b hotfix/urgent-bugfix # Фиксим баг... git checkout main git merge hotfix/urgent-bugfix git checkout develop git merge hotfix/urgent-bugfix git branch -d hotfix/urgent-bugfix Ставь 👍 и забирай 📚 Базу знаний
169
5
🤔 Какие есть варианты обезопасить работу с историей images? Обеспечение безопасности работы с историей изображений в iOS-приложениях может включать несколько уровней защиты: 🟠Контроль доступа к изображениям - Используйте Privacy Settings (NSPhotoLibraryUsageDescription, NSCameraUsageDescription) для контроля доступа к фотоальбому. - Для ограниченного доступа в iOS 14+ используйте PHPickerViewController. let status = PHPhotoLibrary.authorizationStatus(for: .readWrite) if status == .authorized { // Доступ есть } else { // Запросить разрешение PHPhotoLibrary.requestAuthorization { newStatus in if newStatus == .authorized { print("Доступ получен") } } } 🟠Шифрование изображений - Если изображения сохраняются локально, используйте AES-шифрование. - Можно хранить ключ в Keychain или использовать Secure Enclave. import CommonCrypto func encryptImage(data: Data, key: Data) -> Data? { var buffer = Data(count: data.count + kCCBlockSizeAES128) var numBytesEncrypted: size_t = 0 let status = CCCrypt( CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCOptionPKCS7Padding), key.bytes, key.count, nil, data.bytes, data.count, &buffer, buffer.count, &numBytesEncrypted ) return status == kCCSuccess ? buffer.prefix(numBytesEncrypted) : nil } 🟠Безопасное хранение изображений Core Data с Encrypted Store – можно использовать зашифрованные базы данных, такие как SQLCipher. FileManager + Data Protection – файлы можно хранить в Application Support с флагом .completeFileProtection. Keychain – если нужно хранить ссылки на изображения или ключи. let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("secure_image.jpg") try? imageData.write(to: fileURL, options: .completeFileProtection) 🟠Ограничение кеширования изображений - Если изображение чувствительное, отключите кеширование в URLSession: let config = URLSessionConfiguration.default config.urlCache = nil // Отключаем кеш let session = URLSession(configuration: config) 🟠Защита от утечек в памяти - Убедитесь, что ссылки на изображения не создают retain cycle. - Используйте weak ссылки в кэше изображений. class ImageCache { private let cache = NSCache<NSString, UIImage>() func store(image: UIImage, forKey key: String) { cache.setObject(image, forKey: key as NSString) } func retrieve(forKey key: String) -> UIImage? { return cache.object(forKey: key as NSString) } } 🟠Безопасная загрузка изображений (защита от MITM) - Используйте HTTPS вместо HTTP. - Включите App Transport Security (ATS) в Info.plist. - Верифицируйте SSL-сертификаты при загрузке. func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { if let serverTrust = challenge.protectionSpace.serverTrust { let credential = URLCredential(trust: serverTrust) completionHandler(.useCredential, credential) } else { completionHandler(.cancelAuthenticationChallenge, nil) } } Ставь 👍 и забирай 📚 Базу знаний
152
6
🤔 Что будет, если применить модификатор к View? SwiftUI создаст новую View с измененными параметрами, не изменяя оригинальный объект. Это позволяет оптимизировать ререндеринг, так как фреймворк пересоздает только измененные элементы. Благодаря иммутабельности View-дерева, SwiftUI автоматически сравнивает изменения (diffing), обновляя только те части интерфейса, которые изменились. Это делает рендеринг быстрым и эффективным. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
165
7
🤔 Перечислите все ленивые (lazy) контейнеры/вью? В iOS существует несколько ленивых (lazy) контейнеров и вью, которые откладывают создание или загрузку элементов до момента их фактического использования. 🚩`lazy var` (ленивые свойства) Обычное свойство инициализируется сразу, а lazy – только при первом вызове. class Example { lazy var expensiveObject: Data = { print("Объект создан!") return Data() }() } let obj = Example() print("Объект ещё не создан") _ = obj.expensiveObject // Только теперь создастся 🚩`LazySequence` и `LazyCollection` Если вы хотите избежать лишних вычислений, можно использовать ленивую последовательность: let numbers = (1...1000).lazy.map { $0 * 2 } // Не вычисляется сразу! print(numbers.first!) // Только теперь вычисляется первый элемент 🚩`LazyVStack`, `LazyHStack`, `LazyGrid` (SwiftUI) В отличие от обычных VStack и HStack, ленивые версии создают элементы только при прокрутке. ScrollView { LazyVStack { ForEach(0..<1000) { index in Text("Элемент \(index)") } } } 🚩`UITableView` и `UICollectionView` (UIKit) Они работают по принципу переиспользования ячеек, загружая их только когда нужно. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = "Строка \(indexPath.row)" return cell } Ставь 👍 и забирай 📚 Базу знаний
187
8
🤔 Что такое static в Swift? static — ключевое слово, обозначающее, что свойство или метод относится к типу, а не к экземпляру. В классах также используется class для переопределяемых методов. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
203
9
🤔 Какие объекты участвуют в зависимостях? В зависимости от контекста, под "объектами, участвующими в зависимостях" можно понимать различные концепции. В программировании под зависимостями чаще всего подразумеваются связи между объектами или модулями, где один объект зависит от другого для выполнения своих функций. 🚩Объект-зависимый и объект-зависимость Когда один объект (например, ViewController) зависит от другого (NetworkManager), первый становится клиентом, а второй – зависимостью. class NetworkManager { func fetchData() { print("Данные загружены") } } class ViewController { let networkManager: NetworkManager init(networkManager: NetworkManager) { self.networkManager = networkManager } func loadData() { networkManager.fetchData() } } 🚩Протоколы как способ ослабления зависимостей Жесткие зависимости можно ослабить, используя протоколы. protocol NetworkService { func fetchData() } class NetworkManager: NetworkService { func fetchData() { print("Данные загружены") } } class ViewController { let networkService: NetworkService init(networkService: NetworkService) { self.networkService = networkService } func loadData() { networkService.fetchData() } } 🚩Зависимости в архитектурах (MVVM, VIPER, DI) В MVVM зависимость между ViewController и ViewModel. В VIPER модули зависят друг от друга, но слабо связаны через протоколы. В DI (Dependency Injection) зависимости передаются снаружи, что повышает тестируемость и гибкость. 🚩Менеджеры зависимостей Чтобы управлять внешними зависимостями (библиотеками), используются Swift Package Manager (SPM) CocoaPods Carthage Ставь 👍 и забирай 📚 Базу знаний
218
10
Пожизненный PRO доступ на easyoffer — по цене одного года! До 2 сентября вы можете купить PRO навсегда. Покупаешь один раз — пользуешься всю жизнь. – База вопросов и задач из собеседований – Примеры видео-ответов на вопросы – Записи реальных собеседований – Тренажеры "Проработка вопросов" и "Реальное собеседование" – Аналитика требований из вакансий – Автоотклики на вакансии – Агрегатор вакансий (скоро) 👉 Купить PRO со скидкой 70%: https://easyoffer.ru/pro
180
11
🤔 Что такое верстка на AutoLayout, а что такое верстка на frame? - AutoLayout — это система ограничений (constraints), определяющих расположение элементов вне зависимости от размера экрана. Используется при адаптивной, универсальной верстке. - Frame-верстка — это явное указание координат и размеров каждого элемента. Быстро, но не гибко — плохо масштабируется под разные устройства и ориентации. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
199
12
🤔 В каком методе жизненного цикла можно поставить отступы к vue? Если вы хотите задать отступы (margins, padding) для UIView в жизненном цикле UIViewController, то важно выбрать правильный момент, когда размеры view уже определены. 🚩Пример установки отступов в `viewDidLayoutSubviews()` class MyViewController: UIViewController { let myView = UIView() override func viewDidLoad() { super.viewDidLoad() myView.backgroundColor = .red view.addSubview(myView) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // Установка отступов (margins) myView.frame = view.bounds.insetBy(dx: 20, dy: 50) } } Ставь 👍 и забирай 📚 Базу знаний
209
13
🤔 Что происходит с классом при компиляции? При компиляции в Swift класс проходит несколько стадий обработки: Анализ синтаксиса и семантики – компилятор проверяет код на ошибки. Генерация промежуточного представления (IR) – создаётся код на уровне LLVM IR. Оптимизация – Swift применяет различные оптимизации, например, inlining, dead code elimination и другие. Генерация машинного кода – итоговый код превращается в исполняемый машинный код, специфичный для платформы. 🚩Что конкретно происходит с классом? В отличие от структур, классы в Swift являются ссылочными типами и хранятся в куче (heap). Это означает, что: - При создании объекта выделяется память в куче. - Swift автоматически использует ARC (Automatic Reference Counting) для управления памятью. - Методы класса могут вызываться через виртуальную таблицу (vtable), если класс использует динамическую диспетчеризацию. 🚩Важные моменты - Если класс final, компилятор может оптимизировать вызовы методов, убрав динамическую диспетчеризацию. - Наследование делает вызовы методов менее предсказуемыми (они идут через vtable). - В отличие от структур, классы не копируются при передаче в функцию, а передаётся ссылка. class Animal { var name: String init(name: String) { self.name = name } func speak() { print("Some sound") } } final class Dog: Animal { override func speak() { print("Woof!") } } let myDog = Dog(name: "Buddy") myDog.speak() Ставь 👍 и забирай 📚 Базу знаний
220
14
🤔 Расскажи про букву D в solid Принцип инверсии зависимостей (Dependency Inversion Principle, DIP) гласит: Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. 🚩Плохой пример (Нарушение DIP) class MySQLDatabase { func fetchData() -> String { return "Данные из MySQL" } } class DataManager { let database = MySQLDatabase() // Прямая зависимость от MySQL func getData() -> String { return database.fetchData() } } 🚩Хороший пример (Используем DIP) Вводим абстракцию (Протокол) protocol Database { func fetchData() -> String } Реализуем конкретные базы данных class MySQLDatabase: Database { func fetchData() -> String { return "Данные из MySQL" } } class PostgreSQLDatabase: Database { func fetchData() -> String { return "Данные из PostgreSQL" } } Используем абстракцию в DataManager class DataManager { private let database: Database // Зависимость от абстракции init(database: Database) { self.database = database } func getData() -> String { return database.fetchData() } } Использование let mySQLDataManager = DataManager(database: MySQLDatabase()) print(mySQLDataManager.getData()) // "Данные из MySQL" let postgreSQLDataManager = DataManager(database: PostgreSQLDatabase()) print(postgreSQLDataManager.getData()) // "Данные из PostgreSQL" Ставь 👍 и забирай 📚 Базу знаний
216
15
🤔 Почему по дефолту дабл, а не фолт? В Swift (и во многих других языках программирования) по умолчанию числовой литерал с плавающей запятой интерпретируется как `Double`, а не Float. 🚩Основные причины: 🟠Бóльшая точность Double имеет 64 бита, а Float – 32 бита. Это значит, что Double может хранить более точные значения, что особенно важно при математических вычислениях. 🟠Совместимость со стандартными API Большинство API и стандартных библиотек Swift (например, sin(), cos(), pow()) работают именно с Double. Например: let x = 3.14 // По умолчанию это Double let y = sin(x) // sin() принимает Double 🟠Производительность на современных процессорах На современных 64-битных процессорах операции с Double выполняются так же быстро или даже быстрее, чем с Float, из-за оптимизаций в аппаратном обеспечении. 🟠Меньше неожиданных ошибок округления Float может округлять числа с потерей точности, что может привести к неожиданным результатам. Пример ошибки округления в Float: let a: Float = 0.1 + 0.2 print(a == 0.3) // false 😱 🚩Как сделать `Float` вручную? Если всё же нужен Float, надо указать это явно: let number: Float = 3.14 или let number = 3.14 as Float Ставь 👍 и забирай 📚 Базу знаний
206
16
🤔 Чем отличается garbage collector и подсчет ссылок? Garbage Collector (GC) и Automatic Reference Counting (ARC) – это два разных подхода к управлению памятью в программировании. Они решают одну задачу: автоматическое освобождение неиспользуемой памяти, но делают это по-разному. 🚩Garbage Collector (GC) Java, Kotlin, C#, Python, JavaScript - GC периодически просматривает всю память приложения и ищет объекты, на которые больше нет ссылок. - Когда такие объекты находятся, они удаляются, а память освобождается. - Это автоматический процесс, который запускается по мере необходимости. 🚩Подсчет ссылок (ARC - Automatic Reference Counting) Где используется: Swift, Objective-C - Каждый объект имеет счетчик ссылок (reference count). - Когда переменная создает ссылку на объект, счетчик увеличивается. - Когда переменная перестает ссылаться на объект, счетчик уменьшается. - Когда счетчик достигает нуля, объект удаляется из памяти сразу же. class Person { var pet: Pet? } class Pet { var owner: Person? } let person = Person() let pet = Pet() person.pet = pet pet.owner = person // Теперь оба объекта держат друг друга, и ARC их не удалит Решение – использовать weak: class Pet { weak var owner: Person? // Теперь утечки памяти не будет } Ставь 👍 и забирай 📚 Базу знаний
221
17
🤔 Класс open — финальный или нефинальный? open — всегда нефинальный, то есть разрешает наследование и переопределение. Противоположностью является final, который запрещает всё это. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
225
18
🤔 Если обозначить внутри метода Synchronized , что будет монитору? Это высокоуровневый механизм синхронизации, который объединяет взаимное исключение (mutex) и условные переменные (condition variables) для управления доступом к объектам в многопоточной среде. 🚩Как работает 🟠Взаимное исключение (Mutual Exclusion) Только один поток может выполнить защищенный блок кода в любой момент времени. 🟠Условные переменные (Condition Variables) Позволяют потокам ожидать определенных условий, а другим потокам уведомлять их о наступлении этих условий. 🚩Примеры class ThreadSafeClass { private var internalState = 0 private let queue = DispatchQueue(label: "com.example.threadSafeQueue") func increment() { queue.sync { internalState += 1 } } func getState() -> Int { return queue.sync { internalState } } } С NSLock class ThreadSafeClass { private var internalState = 0 private let lock = NSLock() func increment() { lock.lock() internalState += 1 lock.unlock() } func getState() -> Int { lock.lock() let state = internalState lock.unlock() return state } } С objc_sync_enter и objc_sync_exit class ThreadSafeClass: NSObject { private var internalState = 0 func increment() { objc_sync_enter(self) internalState += 1 objc_sync_exit(self) } func getState() -> Int { objc_sync_enter(self) let state = internalState objc_sync_exit(self) return state } } Ставь 👍 и забирай 📚 Базу знаний
239
19
🤔 Кто будет управлять нажатием: вложенная коллекция или родительская? По умолчанию вложенная коллекция перехватывает события. Однако управление можно перенастроить: отключить isUserInteractionEnabled у ячеек, передать события вверх, изменить приоритеты gesture recognizers. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
222
20
🤔 Расскажи про механизм отмены в operatsion В Operation (ранее NSOperation) в Foundation есть встроенный механизм отмены, который позволяет корректно завершить операцию, если она больше не нужна. Однако отмена не прерывает выполнение автоматически – код внутри операции должен сам проверять флаг отмены и корректно завершаться. 🚩Как работает отмена `Operation`? Вызывается cancel() – операция помечается как отмененная. Флаг isCancelled становится true, но операция продолжает выполняться, если не проверяет этот флаг. Операция должна самостоятельно проверять isCancelled и прерываться. class MyOperation: Operation { override func main() { for i in 1...10 { if isCancelled { return } // Проверяем, отменена ли операция print("Выполняется шаг \(i)") sleep(1) // Симуляция работы } } } let queue = OperationQueue() let operation = MyOperation() queue.addOperation(operation) DispatchQueue.main.asyncAfter(deadline: .now() + 3) { operation.cancel() // Отменяем через 3 секунды } 🚩Отмена асинхронных операций Если операция асинхронная (isAsynchronous = true), просто проверять isCancelled недостаточно. Надо корректно управлять состояниями (isExecuting, isFinished). class AsyncOperation: Operation { private var _executing = false private var _finished = false override var isAsynchronous: Bool { true } override var isExecuting: Bool { get { return _executing } set { willChangeValue(for: \.isExecuting) _executing = newValue didChangeValue(for: \.isExecuting) } } override var isFinished: Bool { get { return _finished } set { willChangeValue(for: \.isFinished) _finished = newValue didChangeValue(for: \.isFinished) } } override func start() { if isCancelled { isFinished = true return } isExecuting = true executeTask() } private func executeTask() { DispatchQueue.global().asyncAfter(deadline: .now() + 3) { if self.isCancelled { self.complete() return } print("Асинхронная операция завершена") self.complete() } } private func complete() { isExecuting = false isFinished = true } } let queue = OperationQueue() let asyncOp = AsyncOperation() queue.addOperation(asyncOp) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { asyncOp.cancel() // Отменяем через 1 секунду } 🚩Отмена зависимых операций Если у вас есть зависимости между операциями, отмена одной может автоматически отменить все последующие: let op1 = MyOperation() let op2 = MyOperation() op2.addDependency(op1) let queue = OperationQueue() queue.addOperations([op1, op2], waitUntilFinished: false) // Отменяем первую операцию, вторая тоже не выполнится op1.cancel() Ставь 👍 и забирай 📚 Базу знаний
237