Swift | Вопросы собесов
2.13K subscribers
28 photos
956 links
Download Telegram
🤔 Где фреймы наиболее яркий пример использования?

Фреймы (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)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 В чем отличие классов и структур?

Это объектные типы данных, но с разными принципами работы.
- Классы передаются по ссылке, поддерживают наследование.
- Структуры передаются по значению, копируются при изменении.
- Классы хранятся в куче (Heap), а структуры – в стеке (Stack).
- Классы используют deinit, а структуры – нет.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
🤔 Что такое 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()


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Что под капотом стэка?

Под капотом стек организован как непрерывный блок памяти, управляемый указателем вершины. Операции добавления и удаления происходят за константное время O(1), а память автоматически освобождается при удалении элементов. Стек обычно используется для хранения вызовов функций, локальных переменных и управления потоком выполнения.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
3
🤔 Чем отличается 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? // Теперь утечки памяти не будет
}

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
🤔 Какие есть два типа инициализаторов?

Есть обычные инициализаторы, задающие начальные значения свойств, и факультативные (init?), возвращающие nil, если объект не может быть создан.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3😁3
🤔 Функция принимала дабл, а указываем функцию, то что было бы?

Если функция ожидает параметр типа Double, но вместо этого передаем саму функцию, произойдет ошибка компиляции, так как тип функции и Double — это разные вещи

func printDouble(value: Double) {
print("Значение: \(value)")
}

printDouble(value: printDouble) // Ошибка: Несовместимые типы


🚩Как исправить?

Если вы хотите передавать функцию в качестве аргумента, ее нужно объявить в параметрах как (Double) -> Void:
func processDouble(_ value: Double, action: (Double) -> Void) {
action(value)
}

processDouble(42.0, action: printDouble) // Выведет: "Значение: 42.0"


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉1
🤔 Что будет, если применить модификатор к View?

SwiftUI создаст новую View с измененными параметрами, не изменяя оригинальный объект. Это позволяет оптимизировать ререндеринг, так как фреймворк пересоздает только измененные элементы.
Благодаря иммутабельности View-дерева, SwiftUI автоматически сравнивает изменения (diffing), обновляя только те части интерфейса, которые изменились. Это делает рендеринг быстрым и эффективным.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое dSYM?

Это файл, содержащий отладочную информацию, используемую для сопоставления адресов в машинном коде с исходным кодом. В iOS и macOS разработке dSYM-файлы играют важную роль в процессе отладки и анализа сбоев (crash reports).

🚩Основные аспекты

🟠Содержание
dSYM-файл содержит символы отладки, такие как имена методов и классов, которые соответствуют машинному коду скомпилированного приложения. Эта информация позволяет разработчикам интерпретировать сбои и ошибки, связывая их с исходным кодом.

🟠Создание
dSYM-файлы автоматически создаются Xcode при сборке приложения. Они хранятся в специальной директории и могут быть включены в архив сборки (archive) для последующей загрузки в инструменты анализа сбоев.

🟠Использование
Декодирование отчетов о сбоях: При сбое приложения, отчет о сбое содержит машинные адреса, которые трудно интерпретировать без символов отладки. dSYM-файл помогает преобразовать эти адреса в понятные строки исходного кода.
Инструменты анализа: Инструменты, такие как Xcode, Crashlytics, или другие платформы сбора и анализа сбоев, используют dSYM-файлы для декодирования и анализа отчетов о сбоях.

🚩Пример использования

🟠Получение отчета о сбое (crash report)
Отчеты о сбоях можно получить из Xcode, TestFlight, App Store Connect, или от пользователей.
🟠Загрузка dSYM в сервис анализа
Сервис анализа сбоев, такой как Crashlytics, запрашивает загрузку соответствующего dSYM-файла для декодирования отчетов. Обычно это можно сделать через интерфейс разработчика или автоматически при настройке сборочного процесса.
🟠Декодирование отчета
С помощью dSYM-файла отчет о сбое преобразуется в читаемый формат, содержащий строки исходного кода, где произошел сбой.

🚩Важные моменты

🟠Сохранение dSYM-файлов
Всегда сохраняйте dSYM-файлы для каждой версии вашего приложения, так как они уникальны для каждой сборки.
🟠Управление версиями
Храните dSYM-файлы в безопасном месте (например, в системе управления версиями), чтобы всегда иметь доступ к нужной информации для анализа сбоев.
🟠Сопоставление версий
Убедитесь, что используемый dSYM-файл соответствует версии приложения, из которой получен отчет о сбое.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Чем отличается UIView-based animation от Core Animation?

UIView-based animation — это высокоуровневый API, удобный для анимаций интерфейса. Работает с UIView.animate, абстрагирует детали.
Core Animation — это низкоуровневая система, напрямую работающая с CALayer, позволяющая более тонко управлять производительностью, таймингами, переходами и 3D-эффектами.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Как можно оптимизировать выполнение кода в Swift?

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

🟠Использование правильных структур данных
Array vs. Set vs. Dictionary: Выбирайте структуру данных в зависимости от задачи. Например, для уникальных элементов и быстрого поиска используйте Set, для пар ключ-значение — Dictionary.
   var array = [1, 2, 3, 4, 5]
var set: Set = [1, 2, 3, 4, 5]
var dictionary = ["one": 1, "two": 2, "three": 3]


🟠Минимизация использования опционалов
Избегайте чрезмерного использования опционалов и принудительного разворачивания, так как это может снижать производительность и приводить к ошибкам.
   var name: String? = "John"
if let unwrappedName = name {
print("Name is \(unwrappedName)")
}


🟠Избегание ненужного копирования
Используйте inout параметры для избежания копирования при передаче значений в функции.
   func increment(value: inout Int) {
value += 1
}
var number = 1
increment(value: &number)


🟠Профилирование и отладка
Используйте инструменты профилирования, такие как Instruments, для анализа производительности и выявления узких мест.

🟠Асинхронность и параллелизм
Используйте GCD (Grand Central Dispatch) и OperationQueue для выполнения задач в фоновом режиме.
   DispatchQueue.global(qos: .background).async {
// Фоновая задача
DispatchQueue.main.async {
// Обновление UI на главном потоке
}
}


🟠Lazy Loading
Используйте ленивую загрузку для отложенной инициализации свойств до момента их первого использования.
   class MyClass {
lazy var expensiveObject: ExpensiveObject = {
return ExpensiveObject()
}()
}


🟠Избегание ненужных вычислений
Кэшируйте результаты дорогостоящих вычислений.
   var cache = [Int: Int]()
func fibonacci(_ n: Int) -> Int {
if let result = cache[n] {
return result
}
if n <= 1 { return n }
let result = fibonacci(n - 1) + fibonacci(n - 2)
cache[n] = result
return result
}


🟠Оптимизация циклов
Используйте эффективные конструкции циклов и избегайте лишних операций внутри них.
   for i in 0..<1000 {
// Оптимизированный код
}


🟠Использование Value Types
Структуры (value types) могут быть более эффективными, чем классы (reference types), особенно для небольших объектов.
   struct Point {
var x: Int
var y: Int
}


🟠Избегание глобальных переменных
Глобальные переменные могут приводить к снижению производительности и трудностям с отладкой.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Forwarded from easyoffer
Я боялся, что провалю собеседование. Так появился easyoffer

Когда я только начинал искать первую работу программистом, меня пугала мысль, что я просто не смогу ответить на вопросы на собеседовании.

Типа… ты потратил месяцы на то, чтобы учиться, писал pet-проекты, собирал резюме, рассылаешь отклики — и всё может закончиться на одном-единственном вопросе, на который ты не знаешь ответ.

Я реально боялся.
Я смотрел видео mock-собеседований на YouTube, останавливал каждое, выписывал вопросы в Notion. Потом вручную писал к ним ответы. И потом ещё по нескольку раз перечитывал. Такой вот "тренажёр" на коленке.

📎 (там на картинке — один из моих реальных списков в Notion, ставь 🔥 если тоже так делал)

В какой-то момент я посчитал — у меня уже было выписано больше 500 вопросов. Я почувствовал ужас.
Потому что невозможно всё это зазубрить. А что, если спросят как раз тот, к которому я не успел подготовиться?..

Тогда и пришла идея

А что если понять, какие из вопросов встречаются чаще всего? Чтобы не учить всё подряд, а сфокусироваться на главном.

Так родился easyoffer.

Сначала — просто как пет-проект, чтобы показать в резюме и подготовиться к собесам. А потом оказалось, что он реально помогает людям. За первые месяцы его посетили сотни тысяч человек. И я понял: это больше, чем просто пет-проект.

Сейчас я делаю EasyOffer 2.0
И уже не один, а вместе с вами.

В новой версии будут:
– вопросы из реальных собесов, с фильтрацией по грейду, компании, типу интервью
– тренажёр с карточками (по принципу интервальных повторений — как в Anki)
– база задач с интервью
– тренажёр «реальное собеседование», чтобы отрепетировать как в жизни

Каждая фича упрощает и сокращает время на подготовку. Все эти штуки я бы мечтал иметь, когда сам готовился к собеседованиям.

Я делаю всё на свои деньги. Никаких инвесторов. Только вы и я.

Если вы хотите помочь — сейчас самое важное время.
Краудфандинг уже стартовал. Благодаря нему я смогу привлечь больше людей для разработки, сбору и обработки собеседований.

Все, кто поддержат проект до релиза, получат:

🚀 1 год PRO-доступа по цене месячной подписки. Его можно активировать в любое время, например когда начнете готовится к собесам.
Доступ к закрытому бета-тесту

Поддержать 👉 https://planeta.ru/campaigns/easyoffer

Спасибо, что верите в этот проект 🙌
🤔 Что такое property wrapper?

Это механизм Swift, позволяющий добавить логику при доступе к свойству (при чтении, записи, обновлении).
Они позволяют:
- Автоматически управлять значением.
- Реализовывать реактивность, кэширование, валидацию и т.п.
- Быть читаемыми и декларативными.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что из себя представляет структура данных stack?

Stack (стек) – это структура данных, работающая по принципу LIFO (Last In, First Out – "последним пришел, первым ушел").

🚩Пример реализации стека в Swift

В Swift нет встроенного стека (кроме Array), но можно создать свой:
struct Stack<T> {
private var elements: [T] = []

mutating func push(_ item: T) {
elements.append(item)
}

mutating func pop() -> T? {
return elements.popLast() // Удаляет и возвращает верхний элемент
}

func peek() -> T? {
return elements.last // Возвращает верхний элемент без удаления
}

func isEmpty() -> Bool {
return elements.isEmpty
}
}

// Пример использования:
var stack = Stack<Int>()
stack.push(10)
stack.push(20)
stack.push(30)

print(stack.pop()!) // 30
print(stack.peek()!) // 20
print(stack.isEmpty()) // false


🚩Где используется стек?

Обратный порядок выполнения (рекурсия) – стек вызовов функций.
Алгоритмы (обратная польская нотация, DFS – поиск в глубину)
История действий (назад-вперед в браузере, отмена в редакторе).

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Какие есть фреймворки для выполнения бэкраунд задач?

1. GCD (Grand Central Dispatch): для управления потоками и выполнения задач.
2. OperationQueue: более высокоуровневая абстракция над GCD.
3. URLSession: для выполнения сетевых запросов в фоне.
4. BackgroundTasks: для выполнения долгосрочных задач в фоне.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 В чем проблема, если все переменные будут делаться в вик?

Если все переменные в коде сделать weak, объекты могут мгновенно удаляться из памяти, потому что никто не будет владеть ими (strong reference).

🚩Как работает `weak`?

- weak создает слабую ссылку – объект не увеличивает счетчик ссылок (retain count).
- Если нет других (strong) ссылок на объект, он удаляется (ARC освобождает память).
- weak переменные всегда являются Optional, потому что объект может стать nil в любой момент.
class Person {
weak var name: String? // Ошибка! Строки – это value type, weak нельзя
}


Проблема, если weak используется везде
class Car {
weak var model: String? // Ошибка (value type)
weak var owner: Person? // ⚠️ Будет nil, если нет других strong ссылок
}

class Person {
var car: Car?
}

var person: Person? = Person()
person?.car = Car()
person?.car?.owner = person // `owner` - weak, объект сразу удалится

print(person?.car?.owner) // nil, объект Person уничтожен


🚩Когда `weak` полезен?

🟠Избегание циклов ссылок (retain cycle)
Например, между delegate и ViewController
   protocol SomeDelegate: AnyObject {
func doSomething()
}

class ViewController {
weak var delegate: SomeDelegate? // Prevent retain cycle
}


🟠Когда объект не должен владеть другим объектом
Например, ячейки в UITableView не должны владеть ViewController.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯1
🤔 Какие можешь выделить главные принципы ООП?

Основные принципы объектно-ориентированного программирования (ООП) включают:
1. Инкапсуляция: сокрытие внутренних деталей реализации объекта и объединение данных и методов, работающих с этими данными, в один объект.
2. Наследование: создание нового класса на основе существующего.
3. Полиморфизм: возможность обращаться с объектами, производными от одного базового класса, для выполнения методов, определенных в базовом классе, но переопределенных в производных.
4. Абстракция: определение интерфейса взаимодействия с объектом, отделяющего его функциональное поведение от конкретной реализации.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Расскажи про структуры

Структуры (struct) – это один из основных типов данных в Swift. Они значимые (value type), то есть при передаче копируются, а не передаются по ссылке.

🚩Главные особенности `struct`

Value type – при передаче копируется (в отличие от классов)
Нет ARC (автоматического подсчета ссылок) – производительность выше
Могут иметь методы, свойства, инициализаторы
Работают с протоколами (protocol-oriented programming)
Не поддерживают наследование

🚩Пример структуры

struct Car {
var model: String
var year: Int

func description() -> String {
return "\(model) – \(year)"
}
}

let car1 = Car(model: "Tesla", year: 2023)
var car2 = car1 // Создается копия

print(car1.description()) // Tesla – 2023
print(car2.description()) // Tesla – 2023

car2.year = 2024 // Изменяем car2, но car1 остается прежним
print(car1.year) // 2023
print(car2.year) // 2024


🚩Мутируемые структуры (`mutating`)

По умолчанию методы не могут изменять свойства структуры. Чтобы изменить их внутри метода, нужно использовать mutating
struct Counter {
var count = 0

mutating func increment() {
count += 1
}
}

var counter = Counter()
counter.increment()
print(counter.count) // 1


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
🤔 Зачем нужно делать двусторонние связи в таблицах?

Двусторонние (взаимные) связи позволяют объектам знать друг о друге, что удобно при навигации в обе стороны. Например, если у вас есть User и Post, вы можете получить все посты пользователя (user.posts), а из поста — автора (post.user). Это упрощает работу с данными, повышает связность и облегчает доступ к связанным объектам. Также это удобно для поддержки целостности и каскадных операций (например, удаления).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1