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

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

前往频道在 Telegram

Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv

显示更多
2 204
订阅者
-224 小时
-47
-1030
吸引订阅者
七月 '26
七月 '26
+3
在0个频道中
六月 '26
+32
在0个频道中
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个频道中
日期
订阅者增长
提及
频道
04 七月0
03 七月0
02 七月+3
01 七月0
频道帖子
🤔 Как ловил утечки памяти? Для выявления утечек памяти используют инструмент Instruments, а именно его компонент Leaks, который помогает обнаружить утечки во время выполнения приложения. Важно избегать циклических ссылок, особенно при работе с замыканиями и объектами — для этого применяются слабые (weak) и несобственные (unowned) ссылки, что позволяет сборщику мусора корректно освобождать память. Анализ профилей памяти и использование метода deinit для проверки освобождения объектов также помогает обнаруживать утечки на ранних стадиях. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

2
🤔 Что такое 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 Ставь 👍 и забирай 📚 Базу знаний
151
3
🤔 Какие есть структуры данных? 1. Линейные: массивы, списки, стеки, очереди. 2. Нелинейные: деревья, графы. 3. Ассоциативные: хэш-таблицы, словари. 4. Специализированные: кучи, множества. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
149
4
🤔 Какие плюсы и минусы layout'а? Каждый способ создания макетов (layout'а) в iOS-разработке имеет свои преимущества и недостатки. 🚩Interface Builder (IB) ➕Визуальное редактирование Удобный графический интерфейс для быстрой настройки и визуального просмотра изменений. ➕Интеграция с Auto Layout Простая настройка ограничений (constraints) для адаптивного интерфейса. ➕Быстрое прототипирование Возможность быстрого создания и изменения макетов без написания кода. ➖Меньшая гибкость Ограниченные возможности для создания сложных и динамических макетов. ➖Конфликты при совместной работе Трудности при слиянии изменений в storyboard или xib файлах в больших командах. ➖Производительность Более медленное время загрузки по сравнению с программными подходами. 🚩Auto Layout ➕Адаптивность Поддержка различных устройств и ориентаций экрана. ➕Мощные инструменты Возможность создания сложных и адаптивных макетов с помощью ограничений. ➕Интеграция с Interface Builder Упрощенная настройка ограничений через визуальный интерфейс. ➖Крутая кривая обучения Может быть сложно освоить, особенно для новичков. ➖Управление сложными макетами Требует тщательного планирования и может стать сложным при работе с большим количеством ограничений. 🚩Programmatic Layout ➕Полный контроль Возможность точной настройки макета с помощью кода. ➕Гибкость Легкость создания динамических и условных макетов. ➕Управление версиями Легче управлять изменениями в коде по сравнению с визуальными файлами. ➖Большая трудоемкость Требует больше времени и усилий для настройки, особенно для сложных макетов. ➖Меньшая наглядность Отсутствие визуального редактора может затруднить представление конечного результата. 🚩Stack Views ➕Упрощение макетов Легкость создания и управления сложными макетами с минимальными усилиями. ➕Интеграция с Auto Layout Автоматическое управление ограничениями для вложенных элементов. ➕Адаптивность Поддержка различных ориентаций и размеров экранов. ➖Ограниченная гибкость Менее гибкие по сравнению с чистым Auto Layout или программными подходами. ➖Поддержка Не всегда подходят для всех типов макетов, особенно для более сложных компоновок. 🚩SwiftUI ➕Декларативный синтаксис Простота и понятность кода благодаря декларативному подходу. ➕Превью в реальном времени Мгновенное обновление интерфейса при изменении кода. ➕Интеграция с Swift Современные возможности языка и тесная интеграция с экосистемой Apple. ➕Кроссплатформенность Поддержка различных платформ (iOS, macOS, watchOS, tvOS). ➖Требования к версии iOS Поддержка только iOS 13 и выше, что может ограничить использование на старых устройствах. ➖Зрелость фреймворка Некоторые функции еще находятся в стадии разработки, и могут быть ограничены возможности по сравнению с UIKit. Ставь 👍 и забирай 📚 Базу знаний
180
5
АЙТИШНИКИ, ХВАТИТ сливать время на прилизанные новости и бесполезные курсы Проект «ИИнтеллигенция» стал главным каналом для т
АЙТИШНИКИ, ХВАТИТ сливать время на прилизанные новости и бесполезные курсы Проект «ИИнтеллигенция» стал главным каналом для тех, кто использует нейросети на уровне разработки, автоматизации и опенсорса, а не просто балуется в чатах. Здесь собирают только то, что реально экономит человеко-часы и работает в проде. 🎓 Готовые ИИ-сервисы, промпты и ИИ-агенты для автоматизации рутины 📚 Разборы полезных ИИ-инструментов, локальных LLM и опенсорс-репозиториев 🛠 Практические кейсы, гайды по деплою моделей и интеграции ИИ в пайплайны ⚡️ Технические ИТ-новости без маркетинговой воды и душных отчетов Обучение и прокачка в реальном времени: работа с API (Claude, GPT), локалки (Ollama, vLLM), автоматизация кода, опенсорс-утилиты, AI-агенты и др. Ценишь время и работаешь с ИИ, подпишись: @clucai
182
6
🤔 Когда создаётся экземпляр view? Когда происходит первый доступ к view, или когда вызывается метод loadView(). Тогда UIViewController инициализирует дерево вью Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
179
7
🤔 Какие проблемы можно получить , если оставить контекст? Если оставить контекст в замыкании, не принимая во внимание возможные проблемы, это может привести к нескольким серьезным проблемам, особенно в многопоточном и асинхронном программировании. 🚩Проблемы 🟠Утечки памяти (Retain Cycles) Одной из самых распространенных проблем является утечка памяти из-за циклов удержания (retain cycles). Это происходит, когда два или более объекта удерживают ссылки друг на друга, препятствуя освобождению памяти. В этом примере closure захватывает self, что создает цикл удержания: MyClass держит сильную ссылку на closure, а closure держит сильную ссылку на self. class MyClass { var value: Int = 0 var closure: (() -> Void)? func setupClosure() { closure = { self.value += 1 } } } let instance = MyClass() instance.setupClosure() 🟠Непредсказуемое поведение и условия гонки (Race Conditions) Когда замыкания захватывают изменяемый контекст, это может привести к условиям гонки и непредсказуемому поведению, особенно при работе в многопоточном окружении. Если метод increment вызывается из разных потоков, это может привести к условиям гонки и некорректному изменению значения count. class Counter { var count = 0 func increment() { DispatchQueue.global().async { self.count += 1 } } } let counter = Counter() counter.increment() 🟠Задержки в освобождении ресурсов Если замыкания захватывают тяжелые ресурсы (например, файлы, сети), это может привести к задержкам в их освобождении, что может негативно сказаться на производительности приложения. Если FileHandler освобождается, но замыкание все еще захватывает file, это может привести к задержке в освобождении файлового дескриптора. class FileHandler { var file: File? func processFile() { DispatchQueue.global().async { self.file?.read() } } } 🟠Потеря захваченных данных Когда используется слабая ссылка (weak), замыкание может обнаружить, что захваченный объект освобожден, что приводит к тому, что слабая ссылка становится nil. Это требует дополнительных проверок и обработки. class MyClass { var value: Int = 0 var closure: (() -> Void)? func setupClosure() { closure = { [weak self] in guard let strongSelf = self else { return } strongSelf.value += 1 } } } Ставь 👍 и забирай 📚 Базу знаний
208
8
🤔 Какие есть способы внедрения зависимостей? Через инициализацию (constructor injection), сеттеры, property injection, либо через DI-контейнер (например, Swinject, Resolver или Hilt в Android). В iOS чаще используют первый и третий способ. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
206
9
🤔 Что такое runLoop? RunLoop — это фундаментальный механизм в iOS и macOS, который управляет циклом обработки событий в приложении. Он отслеживает и обрабатывает входящие события, такие как нажатия клавиш, касания экрана, таймеры и сетевые запросы, и поддерживает приложение в активном состоянии, пока оно не завершится. 🚩Основные аспекты `RunLoop` 🟠Цикл обработки событий RunLoop постоянно выполняет цикл, ожидая входящие события и обрабатывая их по мере поступления. Этот цикл состоит из нескольких этапов: ожидание события, обработка события и повтор цикла. 🟠Режимы (Modes) RunLoop может работать в разных режимах, которые определяют, какие источники событий будут отслеживаться и обрабатываться. Основные режимы включают default и tracking (для событий отслеживания, таких как прокрутка). В каждой итерации RunLoop обрабатывает события только для текущего режима. RunLoop.current.run(mode: .default, before: Date.distantFuture) 🟠Источники событий (Event Sources) RunLoop может отслеживать различные источники событий, такие как таймеры (Timer), порты (Port), ввод пользователей (такие как касания экрана и клики мыши), а также пользовательские источники (Input Source). 🟠Таймеры RunLoop может управлять таймерами, которые выполняют задачи через определенные интервалы времени. let timer = Timer(timeInterval: 1.0, repeats: true) { _ in print("Timer fired!") } RunLoop.current.add(timer, forMode: .default) 🟠Обработка событий RunLoop используется для обработки событий в основном потоке (main thread) приложения. Это особенно важно для поддержания отзывчивости пользовательского интерфейса, поскольку все взаимодействия с UI происходят в основном потоке. 🚩Пример использования `RunLoop` import Foundation class Example { var timer: Timer? func startRunLoop() { timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true) RunLoop.current.run() } @objc func timerFired() { print("Timer fired!") } } let example = Example() example.startRunLoop() Ставь 👍 и забирай 📚 Базу знаний
234
10
🤔 В чем разница между синхронными и асинхронными запросами? Синхронные запросы блокируют выполнение программы до получения ответа, что может замедлить работу приложения, особенно если запрос занимает длительное время. Асинхронные запросы, напротив, не блокируют основной поток и позволяют программе продолжать выполнение других задач, пока ожидается ответ от сервера или другой операции. Асинхронные запросы часто используются для работы с сетью или файловой системой, чтобы улучшить отзывчивость и производительность программ. В Swift асинхронные операции реализуются через GCD или `async/await`. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
224
11
🤔 Как заставить оператор поддерживать функцию типа t? В Swift можно заставить оператор поддерживать функцию типа T с помощью перегрузки операторов. Это особенно полезно, когда мы хотим, чтобы оператор мог работать с пользовательскими типами или функциями. 🟠Что значит "функция типа T"? Функция в Swift — это тоже тип данных. func add(_ a: Int, _ b: Int) -> Int { return a + b } Тип этой функции (Int, Int) -> Int 🟠Пример: оператор `+` для функций Допустим, у нас есть две функции, и мы хотим, чтобы оператор + создавал новую функцию, объединяя их поведение. import Foundation // Функция типа (Int) -> Int func double(_ x: Int) -> Int { return x * 2 } func increment(_ x: Int) -> Int { return x + 1 } // Перегружаем оператор + для функций (Int) -> Int func + (lhs: @escaping (Int) -> Int, rhs: @escaping (Int) -> Int) -> (Int) -> Int { return { x in rhs(lhs(x)) } // Сначала вызываем первую, затем вторую } // Используем оператор let combinedFunction = double + increment print(combinedFunction(3)) // (3 * 2) + 1 = 7 🟠Пример: оператор `*` для функций Можно сделать оператор *, который применяет функцию несколько раз. // Перегружаем оператор * для дублирования применения функции func * (lhs: @escaping (Int) -> Int, rhs: Int) -> (Int) -> Int { return { x in var result = x for _ in 0..<rhs { result = lhs(result) } return result } } // Используем оператор let tripleDouble = double * 3 print(tripleDouble(2)) // (2 * 2) * 2 * 2 = 16 Ставь 👍 и забирай 📚 Базу знаний
239
12
🤔 А если сделать свою структуру, то она будет поддерживать Copy-On-Write? Нет, по умолчанию пользовательские структуры не поддерживают COW. Чтобы реализовать это, нужно использовать обёртку с reference type и isKnownUniquelyReferenced для контроля над копированием. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
244
13
🤔 Как бы реализовал словарь в Swift при помощи массива? В Swift словарь (Dictionary) представляет собой структуру данных, которая хранит пары ключ-значение и обеспечивает быстрый доступ к значениям по ключу (O(1) в среднем). Но если бы мы хотели реализовать словарь на основе массива, то пришлось бы использовать линейный поиск, что делает операции менее эффективными (O(n)). 🚩Реализация словаря через массив кортежей Один из простых способов создать словарь на базе массива — использовать массив кортежей (ключ, значение). struct ArrayDictionary<Key: Equatable, Value> { private var items: [(Key, Value)] = [] // Храним пары ключ-значение // Получение значения по ключу func value(for key: Key) -> Value? { for (k, v) in items { if k == key { return v } } return nil } // Добавление или обновление значения mutating func insert(value: Value, for key: Key) { for i in 0..<items.count { if items[i].0 == key { items[i].1 = value // Обновляем значение, если ключ уже есть return } } items.append((key, value)) // Добавляем новую пару } // Удаление элемента по ключу mutating func remove(for key: Key) { items.removeAll { $0.0 == key } } } // Пример использования var myDict = ArrayDictionary<String, Int>() myDict.insert(value: 42, for: "age") myDict.insert(value: 30, for: "height") print(myDict.value(for: "age")!) // 42 myDict.remove(for: "age") print(myDict.value(for: "age")) // nil 🚩Оптимизация: Использование бинарного поиска Если мы отсортируем массив по ключам, можно использовать бинарный поиск (O(log n)) для ускорения поиска ключа. struct SortedArrayDictionary<Key: Comparable, Value> { private var items: [(Key, Value)] = [] // Бинарный поиск индекса ключа private func index(of key: Key) -> Int? { var left = 0 var right = items.count - 1 while left <= right { let mid = (left + right) / 2 if items[mid].0 == key { return mid } else if items[mid].0 < key { left = mid + 1 } else { right = mid - 1 } } return nil } // Получение значения по ключу func value(for key: Key) -> Value? { if let index = index(of: key) { return items[index].1 } return nil } // Вставка с сохранением сортировки mutating func insert(value: Value, for key: Key) { if let index = index(of: key) { items[index].1 = value } else { items.append((key, value)) items.sort { $0.0 < $1.0 } // Сортируем после вставки } } } // Использование var sortedDict = SortedArrayDictionary<String, Int>() sortedDict.insert(value: 50, for: "b") sortedDict.insert(value: 20, for: "a") sortedDict.insert(value: 70, for: "c") print(sortedDict.value(for: "b")!) // 50 Ставь 👍 и забирай 📚 Базу знаний
280
14
🤔 В чём проблема, если все переменные будут делаться в weak? Если все переменные будут weak, объекты будут сразу уничтожаться, как только ни одна сильная ссылка на них не останется. Это приведёт к непредсказуемому поведению, потере данных и крашам, потому что объекты будут nil при обращении. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
277
15
🤔 Структуры (value-типы) хранятся? на стеке, если используются как локальные переменные. в куче, если они: — вложены в класс, — захвачены замыканием, — передаются как inout, — возвращаются из функции и живут дольше текущего контекста. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
302
16
🤔 Как можно итерироваться по коллекции? По коллекции можно итерироваться: - С помощью цикла for. - Через итераторы. - Используя методы коллекций (например, map, filter, forEach). - Через генераторы или ленивые последовательности (в функциональных языках). Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
307
17
🤔 Какие есть инструменты для работы с потоками? В 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) } Ставь 👍 и забирай 📚 Базу знаний
318
18
🤔 Где фреймы — наиболее яркий пример использования? Фреймы логично использовать в анимациях, при рисовании на Canvas, и в простых элементах интерфейса, где точное позиционирование важнее гибкости. Также актуальны при создании кастомных вью или в играх. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
275
19
🤔 Почему Apple предпочитает использовать value type по умолчанию? Apple предпочитает value types (структуры struct) по умолчанию в Swift по нескольким причинам 🟠Безопасность многопоточного кода struct копируется при передаче, а не передается по ссылке, как class. Это снижает вероятность гонки данных (data race), когда один поток изменяет объект, а другой читает его одновременно. В многопоточной среде это делает код более безопасным. struct Point { var x: Int var y: Int } var p1 = Point(x: 1, y: 2) var p2 = p1 // p2 - это копия, изменения в p2 не затронут p1 p2.x = 10 print(p1.x) // 1 print(p2.x) // 10 🟠Производительность struct хранятся в стеке, а не в куче, что делает их создание и удаление быстрее. Куча (heap) требует управления памятью (ARC – Automatic Reference Counting), а struct — нет. class MyClass { var value = 0 } // В куче (heap), управляется ARC struct MyStruct { var value = 0 } // В стеке (stack), копируется при передаче 🟠Предсказуемость и неизменяемость struct ведут себя как примитивные типы (Int, Double), что делает код предсказуемым. Их изменение происходит локально, без неожиданных эффектов в других частях программы. class Car { var speed: Int init(speed: Int) { self.speed = speed } } var car1 = Car(speed: 60) var car2 = car1 // car2 - это ссылка на тот же объект car2.speed = 100 // Изменение затрагивает car1! print(car1.speed) // 100 (хотя мы меняли car2!) 🟠Использование в стандартной библиотеке Swift изначально построен на struct: Int, Double, Bool, Array, Dictionary, String — это структуры. Это делает язык более безопасным и производительным. var arr1 = [1, 2, 3] var arr2 = arr1 // Копия массива, а не ссылка! arr2.append(4) print(arr1) // [1, 2, 3] (не изменился!) print(arr2) // [1, 2, 3, 4] (новый массив) 🚩Когда использовать `class`? Хотя struct — предпочтительный выбор, class нужен, когда: Нужна ссылочная семантика (например, объект должен изменяться в разных местах кода). Есть сложные иерархии наследования. Требуется работа с Objective-C (NSObject). Ставь 👍 и забирай 📚 Базу знаний
324
20
🤔 Какие есть ключевые различия между Objective-C и Swift? Swift — это современный, безопасный, типизированный язык с лаконичным синтаксисом. Objective-C основан на динамической диспетчеризации и C-подобной нотации. В Swift управление памятью автоматизировано и безопаснее. Swift также поддерживает опциональные типы, value semantics, протокол-ориентированное программирование, тогда как Objective-C ближе к классической ООП-модели. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
302