Swift | Вопросы собесов
前往频道在 Telegram
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @sendme_ads
显示更多2 156
订阅者
无数据24 小时
-47 天
-730 天
数据加载中...
相似频道
标签云
进出提及
---
---
---
---
---
---
吸引订阅者
十月 '2610月 '26
十月 '26
+11
在0个频道中
九月 '26
+22
在0个频道中
Get PRO
八月 '26
+25
在0个频道中
Get PRO
七月 '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个频道中
| 日期 | 订阅者增长 | 提及 | 频道 | |
| 11 十月 | +2 | |||
| 10 十月 | 0 | |||
| 09 十月 | 0 | |||
| 08 十月 | +1 | |||
| 07 十月 | 0 | |||
| 06 十月 | 0 | |||
| 05 十月 | +3 | |||
| 04 十月 | 0 | |||
| 03 十月 | +2 | |||
| 02 十月 | +1 | |||
| 01 十月 | +2 |
频道帖子
🤔 Что известно о типовых приёмах рефакторинга?
Часто используются приёмы: выделение метода, перемещение логики в отдельный класс или слой, замена условных операторов полиморфизмом, переименование для ясности, инверсия зависимости. Главная цель — улучшить читаемость, переиспользуемость и снизить связанность компонентов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
| 2 | 🤔 Какие виды диспетчеризации существуют в свифт?
В Swift существует несколько видов диспетчеризации, которые определяют, как и когда вызываются методы или функции. Основные виды диспетчеризации включают статическую диспетчеризацию (static dispatch), диспетчеризацию по таблице виртуальных функций (vtable dispatch), диспетчеризацию по свидетелю (witness table dispatch) и динамическую диспетчеризацию (dynamic dispatch). Рассмотрим их подробнее:
🟠Статическая диспетчеризация (Static Dispatch)
Вызов функции или метода определяется на этапе компиляции. Используется для функций и методов, которые не переопределяются в подклассах или не являются динамическими. Для структур, перечислений и final классов.
struct MyStruct {
func printMessage() {
print("Hello from MyStruct")
}
}
let instance = MyStruct()
instance.printMessage() // Вызов определяется на этапе компиляции
🟠Диспетчеризация по таблице виртуальных функций (Vtable Dispatch)
Используется для вызова методов класса, которые могут быть переопределены в подклассах. Виртуальная таблица (vtable) используется для определения, какой метод вызывать. Для классов и их подклассов.
class BaseClass {
func printMessage() {
print("Hello from BaseClass")
}
}
class SubClass: BaseClass {
override func printMessage() {
print("Hello from SubClass")
}
}
let instance: BaseClass = SubClass()
instance.printMessage() // Вызов определяется в runtime с использованием vtable
🟠Диспетчеризация по свидетелю (Witness Table Dispatch)
Используется для вызова методов протоколов, реализованных типами. Таблица свидетелей (witness table) используется для определения, какой метод вызывать. Для типов, соответствующих протоколам.
protocol MyProtocol {
func printMessage()
}
struct MyStruct: MyProtocol {
func printMessage() {
print("Hello from MyStruct")
}
}
let instance: MyProtocol = MyStruct()
instance.printMessage() // Вызов определяется в runtime с использованием witness table
🟠Динамическая диспетчеризация (Dynamic Dispatch)
Используется для вызова методов, отмеченных как dynamic или методов Objective-C. Метод определяется в runtime с использованием Objective-C runtime. Для методов, которые должны быть динамически разрешены в runtime, обычно для взаимодействия с Objective-C.
import Foundation
class MyClass: NSObject {
@objc dynamic func printMessage() {
print("Hello from MyClass")
}
}
let instance = MyClass()
instance.printMessage() // Вызов определяется в runtime с использованием Objective-C runtime
Ставь 👍 и забирай 📚 Базу знаний | 136 |
| 3 | 🤔 Кто обрабатывает тач и как и куда он проходит?
1. Система получает событие тача через сенсорный экран и передаёт его в UIKit.
2. UIKit определяет целевой объект (UIView) на основе его координат.
3. Событие передаётся в методы touchesBegan, touchesMoved, touchesEnded или touchesCancelled.
4. Если объект не обрабатывает событие, оно передаётся следующему объекту в цепочке обработки событий (responder chain).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 148 |
| 4 | 🤔 Где фреймы наиболее яркий пример использования?
Фреймы (frames) в iOS-разработке используются для задания размеров и расположения элементов интерфейса (UIView) вручную.
🟠Кастомные анимации
Когда нужно анимировать движение элемента, проще всего работать с его frame, так как он напрямую управляет origin (координаты) и size (размеры).
UIView.animate(withDuration: 0.5) {
self.button.frame.origin.x += 100
}
🟠Ручная верстка (без Auto Layout)
Если вы не используете Auto Layout или хотите задать положение элементов программно, frame позволяет точно указать размеры и координаты.
let button = UIButton(type: .system)
button.frame = CGRect(x: 50, y: 100, width: 200, height: 50)
button.setTitle("Нажми меня", for: .normal)
view.addSubview(button)
🟠Оптимизация производительности
При динамической подгрузке ячеек в UITableView или UICollectionView можно вручную вычислять frame для ускорения работы, вместо использования Auto Layout, который может замедлить скроллинг.
🟠Работа с Core Graphics и CALayer
При рисовании или настройке слоев CALayer используется frame, чтобы точно определить размеры слоя.
let borderLayer = CALayer()
borderLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
borderLayer.borderWidth = 2
borderLayer.borderColor = UIColor.red.cgColor
view.layer.addSublayer(borderLayer)
Ставь 👍 и забирай 📚 Базу знаний | 183 |
| 5 | 🤔 Что будет, если на serial очереди запустить асинхронную Task?
Асинхронная задача начнёт выполнение независимо от очереди, так как Task использует Swift Concurrency runtime, который сам решает, где и как исполнять задачу. Она не заблокирует очередь, но может быть приостановлена и возобновлена.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 186 |
| 6 | 🤔 Что известно о Swift Intermediate Language (SIL)?
SIL (Swift Intermediate Language) — это промежуточное представление кода, которое Swift-компилятор использует между стадиями компиляции и генерации байткода.
SIL:
- Позволяет проводить оптимизации на уровне Swift-кода.
- Более абстрактен, чем машинный код, но ближе к нему, чем сам Swift.
- Существует в двух формах: raw SIL (до оптимизаций) и canonical SIL (после).
- Используется для анализа производительности, валидации ARC, оптимизации кода, проверки правильности lifetime объектов.
SIL — ключевая часть того, почему Swift работает быстро и надёжно, несмотря на высокоуровневую природу языка.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 204 |
| 7 | 🤔 Что под капотом стэка?
Это абстрактная структура данных, работающая по принципу LIFO (Last In, First Out), что означает "последний пришёл — первый вышел". Это значит, что последний добавленный элемент будет первым при извлечении из стека. Под капотом реализации стека могут быть разные, и они зависят от конкретного языка программирования и задач, которые необходимо решить.
🟠Массивы
Один из самых распространённых способов реализации стека — это использование массива. В такой реализации элементы стека хранятся в массиве, и индекс последнего элемента (вершина стека) отслеживается отдельной переменной.
struct Stack<Element> {
private var storage: [Element] = []
mutating func push(_ element: Element) {
storage.append(element)
}
mutating func pop() -> Element? {
return storage.popLast()
}
func peek() -> Element? {
return storage.last
}
var isEmpty: Bool {
return storage.isEmpty
}
}
🟠Связные списки
Стек можно реализовать с использованием связных списков, где каждый элемент списка содержит данные и ссылку на следующий элемент в стеке. Вершина стека в такой реализации — это начало связного списка.
class Node<Element> {
var value: Element
var next: Node?
init(value: Element) {
self.value = value
}
}
struct Stack<Element> {
private var head: Node<Element>?
mutating func push(_ element: Element) {
let node = Node(value: element)
node.next = head
head = node
}
mutating func pop() -> Element? {
let node = head
head = head?.next
return node?.value
}
func peek() -> Element? {
return head?.value
}
var isEmpty: Bool {
return head == nil
}
}
🟠Стек вызовов
Это системный стек, который используется во время выполнения программы для хранения информации о вызовах функций/методов. Он хранит адреса возврата, параметры функций, локальные переменные и другие данные, необходимые для управления вызовами функций и их возврата.
🚩Зачем он нужен?
Обратную польскую нотацию для вычисления арифметических выражений. Управление вызовами функций в программном стеке. Поддержка операций undo в приложениях.
Ставь 👍 и забирай 📚 Базу знаний | 214 |
| 8 | 🤔 Как хранить объекты классов в массиве по weak-ссылке?
Обычно для этого используют обёртку, например WeakBox<T>, где T: AnyObject, и поле weak var value: T
Swift не поддерживает массив weak напрямую.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 190 |
| 9 | 🤔 Как можно итерироваться по строке?
Строка — это коллекция символов. Итерироваться можно так же, как и по массиву: посимвольно через for, используя индекс, итератор или методы работы со строками (например, enumerate или split в зависимости от языка).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 210 |
| 10 | 🤔 Какие есть инструменты для работы с потоками?
В Swift есть несколько инструментов для работы с многопоточностью и параллельным выполнением кода. Вот основные из них:
🟠GCD (Grand Central Dispatch) – главный инструмент для потоков
GCD – это низкоуровневая технология, позволяющая управлять задачами (тасками) в очередях (DispatchQueue).
DispatchQueue.global(qos: .background).async {
print("Фоновый поток")
DispatchQueue.main.async {
print("Вернулись в главный поток")
}
}
🟠OperationQueue – более удобный API для задач
OperationQueue – это более гибкая и объектно-ориентированная альтернатива GCD.
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 2 // Ограничение на 2 задачи одновременно
queue.addOperation {
print("Операция 1")
}
queue.addOperation {
print("Операция 2")
}
🟠Actors – безопасная работа с потоками в Swift 5.5+
С actor можно работать с потоками без гонок данных, потому что все его свойства защищены от одновременного доступа.
actor Counter {
private var value = 0
func increment() {
value += 1
}
func getValue() -> Int {
return value
}
}
let counter = Counter()
Task {
await counter.increment()
print(await counter.getValue()) // Потокобезопасный доступ
}
🟠Task & Async/Await (Swift 5.5+) – современный подход к асинхронности
С async/await код становится читаемым и удобным.
func fetchData() async -> String {
try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 секунда задержки
return "Данные загружены"
}
Task {
let result = await fetchData()
print(result)
}
Ставь 👍 и забирай 📚 Базу знаний | 217 |
| 11 | 🔥 Скрытые вакансии с удаленной работой для iOS разработчика, которые нигде больше не публикуются. Напрямую от компаний, с контактами рекрутеров.
🔹 iOS Jobs | Вакансии
🔹 Flutter Dart Jobs | Вакансии
🔹 Android Jobs | Вакансии
🔸 Все каналы с вакансиями | 209 |
| 12 | 🤔 Что такое замыкание?
Замыкание (closure) — это блок кода, который можно передать и выполнить позже. Оно может захватывать значения из окружающего контекста. Аналог лямбда-функций и функциональных выражений.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 216 |
| 13 | 🤔 Что нужно сделать, чтобы кастомная структура стала ключом в dictionary?
В Swift ключи в словаре (Dictionary) должны быть уникальными и сравниваться между собой. Поэтому, если вы хотите использовать*свою структуру в качестве ключа, она должна соответствовать протоколу Hashable.
🚩Что нужно?
Структура должна соответствовать Hashable
Должен быть реализован hash(into:) или использовать Equatable + Hashable автоматически
Свойства структуры должны быть Hashable (если String, Int, Double – все ок)
🚩Пример кастомной структуры в `Dictionary`
struct Person: Hashable {
let id: Int
let name: String
}
// Теперь можно использовать `Person` как ключ
var peopleAges: [Person: Int] = [
Person(id: 1, name: "Alice"): 25,
Person(id: 2, name: "Bob"): 30
]
// Доступ по ключу
let alice = Person(id: 1, name: "Alice")
print(peopleAges[alice] ?? "Не найдено") // 25
🚩Ручная реализация `hash(into:)`
Если нужно кастомное хеширование, можно реализовать hash(into:):
struct Person: Hashable {
let id: Int
let name: String
func hash(into hasher: inout Hasher) {
hasher.combine(id) // Используем только id для хеша
}
}
Ставь 👍 и забирай 📚 Базу знаний | 239 |
| 14 | 🤔 Какой есть механизм для показа экрана?
Обычно используются:
- pushViewController (в UINavigationController);
- present(_:animated:) — для модального показа;
- В SwiftUI — NavigationStack, .sheet, .fullScreenCover.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 210 |
| 15 | 🤔 Что такое notification центр?
Это механизм в iOS и macOS для обмена сообщениями между различными частями приложения. Он позволяет объектам отправлять и получать уведомления без необходимости напрямую ссылаться друг на друга, что способствует более гибкому и модульному дизайну.
🚩Основные аспекты
🟠Отправка уведомлений
Любой объект может отправить уведомление с помощью Notification Center. Уведомления идентифицируются по имени (Notification.Name). Можно передать дополнительную информацию в виде словаря (userInfo).
NotificationCenter.default.post(name: .myNotification, object: nil)
🟠Получение уведомлений
Объекты могут регистрироваться для получения уведомлений с определенным именем. Для обработки уведомлений используется метод, который будет вызван при получении уведомления.
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: .myNotification, object: nil)
@objc func handleNotification(notification: Notification) {
print("Received notification")
}
🟠Удаление наблюдателей
Важно удалять наблюдателей, когда они больше не нужны, чтобы избежать утечек памяти. Обычно это делается в методе deinit или перед уничтожением объекта.
NotificationCenter.default.removeObserver(self, name: .myNotification, object: nil)
🚩Плюсы
➕Слабая связанность
Объекты не нужно напрямую ссылаться друг на друга, что улучшает модульность кода.
➕Гибкость
Позволяет легко организовать обмен сообщениями между различными частями приложения.
➕Повторное использование
Уведомления могут использоваться многими объектами, что облегчает реализацию функций, таких как обновление интерфейса или реагирование на события.
🚩Примеры использования
1⃣Обновление интерфейса
Когда данные изменяются, можно отправить уведомление для обновления пользовательского интерфейса.
NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
2⃣Реакция на системные события
Например, можно подписаться на уведомление о смене состояния сети.
NotificationCenter.default.addObserver(self, selector: #selector(handleNetworkChange), name: .reachabilityChanged, object: nil)
3⃣Межмодульное взаимодействие
Различные модули приложения могут общаться друг с другом через Notification Center, не создавая сильных зависимостей.
NotificationCenter.default.post(name: .userDidLogin, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: .userDidLogin, object: nil)
Ставь 👍 и забирай 📚 Базу знаний | 226 |
| 16 | 🤔 Как устроено наследование в Swift?
Наследование в Swift позволяет классу (подклассу) унаследовать свойства, методы и инициализаторы от другого класса (суперкласса). Подклассы могут переопределять (override) поведение суперкласса, добавлять новые свойства и методы, но не могут наследовать структуры, перечисления или протоколы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 196 |
| 17 | 🤔 Расскажи про кодирование и декодирование в user defaults
UserDefaults — это хранилище для сохранения простых данных (строки, числа, массивы). Но если нужно сохранить сложные объекты, их сначала кодируют в `Data` (Codable), а затем сохраняют.
🟠Сохранение и загрузка простых данных
Для примитивных типов (строки, числа, массивы, словари) UserDefaults работает без кодирования:
let defaults = UserDefaults.standard
// Сохранение
defaults.set("Иван", forKey: "username")
defaults.set(25, forKey: "age")
// Чтение
let name = defaults.string(forKey: "username") ?? "Нет имени"
let age = defaults.integer(forKey: "age")
print(name, age) // Иван 25
🟠Сохранение сложных объектов (Codable)
Если нужно сохранить свой объект, сначала его нужно закодировать в Data.
struct User: Codable {
let name: String
let age: Int
}
Сохранение в UserDefaults
let user = User(name: "Иван", age: 25)
let defaults = UserDefaults.standard
if let encoded = try? JSONEncoder().encode(user) {
defaults.set(encoded, forKey: "user")
}
Загрузка из UserDefaults
if let savedData = defaults.data(forKey: "user"),
let savedUser = try? JSONDecoder().decode(User.self, from: savedData) {
print(savedUser.name, savedUser.age) // Иван 25
}
🟠Удаление данных из `UserDefaults`
Чтобы удалить ключ:
defaults.removeObject(forKey: "user")
🟠Сохранение массива объектов
Можно сохранить массив объектов, просто закодировав его:
let users = [
User(name: "Иван", age: 25),
User(name: "Анна", age: 30)
]
if let encoded = try? JSONEncoder().encode(users) {
defaults.set(encoded, forKey: "users")
}
// Читаем массив обратно
if let savedData = defaults.data(forKey: "users"),
let savedUsers = try? JSONDecoder().decode([User].self, from: savedData) {
print(savedUsers) // [{name: Иван, age: 25}, {name: Анна, age: 30}]
}
Ставь 👍 и забирай 📚 Базу знаний | 207 |
| 18 | 🤔 Что знаешь про capture list?
Capture list используется в замыканиях Swift, чтобы управлять тем, как значения захватываются: как weak, unowned или strong. Это предотвращает retain cycle и утечки.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 198 |
| 19 | 🤔 Как устроено наследование?
Это ключевой механизм ООП, позволяющий классам наследовать свойства, методы и другие характеристики от других классов. Это позволяет создавать новые классы на основе существующих, расширяя их функциональность или изменяя её.
🚩Основы наследования
🟠Определение базового класса
Базовый класс определяет общие свойства и методы, которые могут быть унаследованы подклассами.
🟠Создание подкласса
Подкласс наследует (или "расширяет") базовый класс. Он может переопределять унаследованные методы и свойства, добавлять новые методы и свойства, а также добавлять инициализаторы или изменять существующие.
🟠Переопределение методов и свойств
Подклассы могут переопределять методы, свойства и индексаторы базового класса для изменения или расширения их поведения.
🟠Предотвращение переопределения
Можно предотвратить переопределение методов, свойств или индексаторов с помощью ключевого слова final. Если метод, свойство или индексатор объявлен как final, то он не может быть переопределён в подклассе.
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "traveling at \(currentSpeed) miles per hour"
}
func makeNoise() {
// Этот метод будет переопределен в подклассах, если необходимо
}
}
class Bicycle: Vehicle {
var hasBasket = false
}
class Car: Vehicle {
var gear = 1
final func drive() {
print("Car is moving")
}
override func makeNoise() {
print("Vroom!")
}
}
🚩Использование super
Подклассы могут вызывать методы своего суперкласса с помощью ключевого слова super. Это позволяет подклассам расширять, а не заменять поведение суперкласса.
Ставь 👍 и забирай 📚 Базу знаний | 217 |
| 20 | 🤔 На какой механизм Swift похож associatedtype?
associatedtype — это аналог дженериков, но на уровне протоколов. Он позволяет абстрагировать конкретный тип и использовать его позже в реализации, сохраняя гибкость и строгость типизации.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний | 213 |
