Swift | Вопросы собесов
2.13K subscribers
28 photos
935 links
Download Telegram
Что такое жизненный цикл объекта ?
Спросят с вероятностью 45%

Жизненный цикл объекта — это период с момента его создания до момента уничтожения. Управление жизненным циклом объекта важно для эффективного использования памяти и предотвращения утечек памяти, особенно в языках программирования, где управление памятью выполняется автоматически через механизм подсчёта ссылок (reference counting).

Создание объекта

1️⃣Инициализация (Initialization): Объект создаётся в памяти. Это происходит при вызове инициализатора, который устанавливает начальное состояние всех свойств объекта. Инициализаторы могут быть определены с различными параметрами, позволяя создавать объекты с разными начальными значениями.

Использование объекта

2️⃣Доступ и изменение состояния: После создания объекта его методы могут быть вызваны, а свойства — читаться или изменяться. Это активный период в жизненном цикле объекта, когда он выполняет полезную работу.

Уничтожение объекта

3️⃣Деинициализация (Deinitialization): Непосредственно перед тем, как объект будет уничтожен, вызывается деинициализатор (если он определён). Это дает возможность освободить ресурсы или выполнить другие операции по очистке. Деинициализаторы не принимают никаких параметров и указываются с помощью ключевого слова deinit.

4️⃣Освобождение памяти (Deallocation): Когда на объект больше нет активных ссылок (когда счётчик ссылок достигает нуля), память, занимаемая объектом, освобождается. Это означает, что объект удаляется из памяти, и ресурсы, которые он использовал, становятся доступными для других объектов или программ.

Управление памятью объектов осуществляется через подсчёт ссылок (ARC — Automatic Reference Counting). ARC автоматически отслеживает, сколько активных ссылок указывает на каждый объект. Когда количество ссылок на объект уменьшается до нуля, Swift понимает, что объект больше не нужен, и автоматически уничтожает его, освобождая занимаемую память.

Понимание жизненного цикла объекта помогает избегать утечек памяти, неправильного управления ресурсами и других ошибок, связанных с управлением памятью. Например, утечки памяти могут произойти, если два объекта ссылаются друг на друга сильными ссылками, и их счётчики ссылок никогда не достигнут нуля, что препятствует ARC корректно уничтожить объекты.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍21
Как решить проблему race condition ?
Спросят с вероятностью 36%

Проблема "race condition" возникает в многопоточных или распределённых системах, когда несколько потоков или процессов пытаются одновременно изменить общие данные, и конечный результат зависит от порядка, в котором выполняются эти операции. Это может привести к непредсказуемому поведению программы, ошибкам и сложностям с отладкой.

Решение проблемы "rc" включает в себя различные стратегии синхронизации доступа к общим ресурсам, чтобы обеспечить, что в любой момент времени только один поток может выполнять критические операции. Вот несколько общих подходов:

1️⃣Использование блокировок (Locks)

Блокировки позволяют "заблокировать" данные, чтобы только один поток мог их изменять в данный момент времени. В Swift для этого можно использовать NSLock, pthread_mutex_t в более низкоуровневом коде или даже DispatchSemaphore с семафором, установленным в 1, для управления доступом к ресурсу.
let lock = NSLock()

func threadSafeMethod() {
lock.lock()
// безопасный доступ к данным
lock.unlock()
}


2️⃣Сериализация операций с помощью очередей

Система Grand Central Dispatch (GCD) в Swift позволяет создавать сериализованные (последовательные) очереди, гарантируя, что операции в очереди выполняются одна за другой, что исключает возможность "race condition".
let queue = DispatchQueue(label: "com.example.myQueue")

func threadSafeMethod() {
queue.async {
// безопасный доступ к данным
}
}


3️⃣Использование атомарных операций

Атомарные операции — это такие операции с данными, выполнение которых гарантированно не будет прервано другими потоками. Они полезны для операций инкремента, декремента или сравнения и замены. В некоторых языках и системах предоставляются встроенные атомарные функции для работы с общими ресурсами.

4️⃣Использование транзакций

В некоторых системах, например, в базах данных, можно использовать транзакции для управления доступом к данным. Транзакции гарантируют, что серия операций либо выполняется полностью, либо не выполняется вовсе, что может помочь предотвратить "race condition" при одновременном доступе к данным.

5️⃣Избегание общего состояния

Ещё одним подходом является стараться избегать общего состояния между потоками там, где это возможно, и использовать локальное состояние, передаваемое между потоками, или неизменяемые (immutable) данные, которые безопасно читать из нескольких потоков одновременно.

Выбор стратегии зависит от конкретного случая и требований к производительности и безопасности. Важно тщательно тестировать многопоточный код, чтобы убедиться в отсутствии "race condition" и других проблем синхронизации.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍3
Что такое dispatch группа ?
Спросят с вероятностью 18%

Используя библиотеку Grand Central Dispatch (GCD), dispatch группы представляют собой мощный инструмент для организации и синхронизации асинхронных задач. Эти группы позволяют объединять несколько асинхронных задач в одну группу, выполнение которой можно отслеживать коллективно.

Как они работают

Позволяют вам асинхронно отправлять несколько задач на выполнение и получать уведомление, когда все эти задачи завершены. Это особенно полезно, когда вам нужно выполнить несколько асинхронных операций параллельно и затем обработать все результаты, когда они будут готовы. Например, это может быть загрузка данных с нескольких серверов, выполнение нескольких сложных вычислений или чтение из нескольких источников данных.

Вот пример того, как можно использовать dispatch группы с помощью GCD:
let dispatchGroup = DispatchGroup()

dispatchGroup.enter()
DispatchQueue.global().async {
// Задача 1
print("Задача 1 началась")
// Представим, что тут какая-то асинхронная операция
sleep(2) // Имитация длительной операции
print("Задача 1 завершена")
dispatchGroup.leave()
}

dispatchGroup.enter()
DispatchQueue.global().async {
// Задача 2
print("Задача 2 началась")
sleep(1) // Имитация длительной операции
print("Задача 2 завершена")
dispatchGroup.leave()
}

dispatchGroup.notify(queue: DispatchQueue.main) {
// Этот блок кода будет выполнен, когда все задачи в группе завершены
print("Все задачи в группе выполнены")
}


Основные Моменты

`dispatchGroup.enter()`: Этот метод увеличивает счётчик задач в группе и сообщает системе, что началась новая задача, которая должна быть учтена.
`dispatchGroup.leave()`: Этот метод уменьшает счётчик задач в группе и сообщает системе, что задача завершена.
`dispatchGroup.notify(queue:completion:)`: Этот метод позволяет задать блок кода, который будет выполнен после завершения всех задач в группе. Вы указываете очередь, в которой должен выполняться этот блок, что позволяет гарантировать, что все последующие действия будут выполнены в нужном контексте (например, в основной очереди для обновления пользовательского интерфейса).

Dispatch группы в GCD предоставляют эффективный способ управления параллельным выполнением нескольких задач, упрощая синхронизацию и обработку зависимостей между асинхронными операциями.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍41
Что такое RC ?
Спросят с вероятностью 36%

RC, или подсчёт ссылок (Reference Counting) — это метод управления памятью, используемый в программировании для автоматического освобождения неиспользуемой памяти. Суть метода заключается в отслеживании количества ссылок на объект в памяти; когда число этих ссылок достигает нуля, объект считается больше не нужным, и его память может быть освобождена.

Это механизм Automatic Reference Counting (ARC), который автоматически управляет памятью, отслеживая и очищая объекты, на которые больше нет активных ссылок. ARC помогает предотвратить утечки памяти, автоматически освобождая ресурсы, которые больше не используются в программе.

Как работает ARC:

Увеличение счётчика ссылок: Когда вы создаёте ссылку на объект, ARC автоматически увеличивает количество ссылок на этот объект. Это происходит, например, когда вы присваиваете объект переменной или добавляете его в коллекцию.
Уменьшение счётчика ссылок: Когда ссылка на объект удаляется или заменяется, ARC уменьшает счётчик ссылок. Если счётчик достигает нуля, ARC автоматически освобождает память, занимаемую объектом.

ARC умно управляет всеми ссылками в рамках приложения, включая сильные, слабые (weak) и несильные (unowned) ссылки, чтобы минимизировать риск утечек памяти. Однако разработчикам всё ещё нужно быть осторожными с циклическими ссылками, когда два объекта ссылаются друг на друга сильными ссылками, что может помешать ARC корректно освободить память. В таких случаях рекомендуется использовать слабые или несильные ссылки для разрыва цикла.

RC или подсчёт ссылок — это ключевой механизм управления памятью, который позволяет языкам программирования, автоматически освобождать неиспользуемые объекты, тем самым предотвращая утечку памяти и оптимизируя ресурсы системы.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍2
Что такое Stack и куча ?
Спросят с вероятностью 36%

Stack (стек) и куча (heap) — это две области памяти, используемые в компьютерных программах для хранения переменных и объектов, но они управляются по-разному и служат разным целям.

Стек

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

Пример использования стека — вызов функций: когда функция вызывается, запись о ней (включая параметры и локальные переменные) помещается в стек. Когда функция завершает работу, её запись удаляется из стека.

Куча

Куча — это область памяти, предназначенная для динамического выделения памяти. В отличие от стека, память в куче может быть выделена и освобождена в любом порядке, и размер выделяемой памяти не ограничен размером кучи. Это делает кучу идеальным местом для хранения данных, размер или время существования которых неизвестны во время компиляции программы.

Работа с кучей медленнее, чем со стеком, поскольку требует явного управления памятью: программист должен явно запрашивать выделение памяти при создании нового объекта и освобождать её, когда объект больше не нужен. Это увеличивает риск утечек памяти и фрагментации.

Ключевые отличия

Управление памятью: В стеке управление памятью осуществляется автоматически, а в куче — вручную или с помощью сборщика мусора в языках программирования, которые его поддерживают.
Производительность: Доступ к стеку быстрее из-за его LIFO-структуры и автоматического управления памятью, в то время как куча предоставляет большую гибкость за счёт производительности.
Размер: Стек обычно имеет ограниченный размер, заданный при запуске программы, в то время как куча может расширяться в зависимости от доступной системной памяти.
Хранение данных: Стек используется для хранения локальных переменных и управления вызовами функций, куча — для динамически выделяемых объектов.

Понимание различий между стеком и кучей важно для эффективной разработки программ и управления памятью.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
3
В чем разница между синхронными и асинхронными запросами ?
Спросят с вероятностью 36%

Синхронные и асинхронные запросы — это два разных подхода к выполнению операций, которые могут занимать некоторое время, таких как обращение к сетевым ресурсам, чтение файлов или выполнение тяжёлых вычислений. Основное отличие между ними заключается в том, как программа реагирует на выполнение таких операций.

Синхронные запросы

При синхронном выполнении задача (запрос) выполняется последовательно. Программа инициирует запрос и затем приостанавливает дальнейшее выполнение, пока этот запрос не будет завершён. То есть, следующая строка кода (или операция) будет выполнена только после того, как завершится синхронный запрос. Это означает, что пользовательский интерфейс программы может "заморозиться" на время выполнения такой операции, если она происходит в основном потоке.

Пример:
let data = try? Data(contentsOf: url)
// Следующая строка кода не выполнится, пока данные не будут загружены

Асинхронные запросы

При асинхронном выполнении программа инициирует запрос и сразу же продолжает выполнение следующих операций, не дожидаясь его завершения. Завершение асинхронного запроса обрабатывается с помощью колбэков, промисов, фьючерсов, async/await или других механизмов, позволяющих уведомить программу о завершении операции. Таким образом, асинхронное выполнение позволяет избежать блокировки пользовательского интерфейса и делает приложение более отзывчивым.

Пример:
func fetchData() async {
let data = try? await Data(contentsOf: url)
// Этот код выполнится сразу после завершения загрузки данных, но не заблокирует остальную программу
}


Ключевые отличия

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

Выбор между синхронными и асинхронными запросами зависит от специфики задачи, требований к отзывчивости приложения и предпочтений.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍41
Что такое Dependency Injection ?
Спросят с вероятностью 36%

Dependency Injection (DI) — это техника в программировании, используемая для управления зависимостями между объектами. Это один из методов инверсии управления (Inversion of Control, IoC), который помогает сделать программный код более модульным и упрощает тестирование. Его суть заключается в том, что вместо того чтобы объект сам создавал или искал необходимые ему зависимости (другие объекты, от которых он зависит для выполнения своих функций), эти зависимости предоставляются ему извне.

Преимущества:

1️⃣Упрощение тестирования: Поскольку зависимости инжектируются извне, для тестирования можно легко подменить реальные зависимости моками или фейками.
2️⃣Улучшение модульности и гибкости: DI позволяет легко заменять компоненты системы без изменения кода, использующего эти компоненты.
3️⃣Уменьшение связности: Так как объекты не создают свои зависимости напрямую, связь между компонентами системы ослабевает, что упрощает управление кодом.

Как он работает:

Можно реализовать разными способами, включая:

Конструктор (Constructor Injection): Зависимости передаются объекту через его конструктор.
Сеттер (Setter Injection): Зависимости передаются через сеттеры или другие методы после создания объекта.
Интерфейс (Interface Injection): Объект предоставляет интерфейс, через который в него можно инжектировать зависимости.

Пример:
Без использования DI, объект может сам создавать свою зависимость:
class Service {}

class Client {
var service: Service

init() {
self.service = Service()
}
}

С использованием Constructor Injection:
class Service {}

class Client {
var service: Service

init(service: Service) {
self.service = service
}
}

// Использование
let service = Service()
let client = Client(service: service)


В этом примере Client требует Service для работы. Вместо того чтобы создавать Service напрямую, Client получает его через конструктор, что позволяет легко подменить Service при тестировании или если потребуется использовать другую реализацию Service.

Dependency Injection делает код более чистым, тестируемым и соответствующим принципам SOLID, особенно принципу инверсии зависимостей (Dependency Inversion Principle).

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🔥41
Ребят, напоминаю, что все вопросы, которые здесь публикуются можно посмотреть списком вместе с видео-ответами на моем сайте easyoffer.ru
4🤯1
Что лучше NSOperationQueue или GCD ?
Спросят с вероятностью 36%

Выбор между NSOperationQueue и Grand Central Dispatch (GCD) в Swift зависит от конкретных требований к задаче и предпочтений разработчика. Оба механизма предоставляют мощные инструменты для выполнения асинхронных операций и управления многопоточностью, но они имеют различные особенности и подходы к решению задач.

Grand Central Dispatch (GCD)

Это низкоуровневый API для многопоточного программирования, основанный на очередях. Он позволяет выполнять задачи асинхронно или синхронно, управляя потоками за вас на основе доступности системных ресурсов. GCD оптимизирован для максимальной производительности и простоты использования.

Преимущества:
Простота использования для выполнения асинхронных операций.
Автоматическое управление потоками на основе доступности системных ресурсов.
Подходит для легковесных задач и выполнения блоков кода.

NSOperationQueue

Это высокоуровневый API, построенный поверх GCD, который предоставляет больше контроля над операциями. Он работает с объектами NSOperation, которые представляют собой одну выполнимую задачу. NSOperation позволяет добавлять зависимости между операциями, приостанавливать и возобновлять выполнение очереди, а также наблюдать за завершением операции.

Преимущества:
Возможность добавления зависимостей между операциями.
Возможность отмены операций.
Поддержка KVO (Key-Value Observing) для наблюдения за изменениями свойств операций.
Больше контроля над выполнением операций по сравнению с GCD.

Что выбрать?

Используйте GCD, если:
Вам нужно выполнить простые асинхронные операции, не требующие сложного взаимодействия или зависимостей между задачами.
Вы хотите максимально упростить код.
Вам нужен более низкоуровневый контроль над многопоточностью.

Используйте NSOperationQueue, если:
Вам нужно выполнить комплексные задачи с зависимостями между операциями.
Вам нужна возможность отмены операций.
Вы хотите использовать готовые возможности для мониторинга выполнения операций.
Ваша задача требует сложной логики синхронизации и управления зависимостями между операциями.

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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍5
Чем архитектура помогает ?
Спросят с вероятностью 18%

Архитектура ПО играет критическую роль в процессе разработки, обеспечивая основу для создания систематизированных и управляемых IT-проектов. Вот основные аспекты, в которых архитектура оказывает существенное влияние:

1️⃣Обеспечение масштабируемости и гибкости
Хорошо спроектированная архитектура позволяет системе эффективно масштабироваться в ответ на увеличение нагрузки или расширение функциональности. Она предусматривает компоненты, которые могут быть легко модифицированы или расширены без внесения значительных изменений в другие части системы.

2️⃣Упрощение сопровождения и развертывания
Чёткая и структурированная архитектура упрощает процессы обслуживания, тестирования и развертывания программного обеспечения. Модульная структура помогает локализовать ошибки и устранять их, не затрагивая работу всей системы. Также она позволяет независимо разворачивать отдельные компоненты.

3️⃣Повышение производительности
Эффективная архитектура оптимизирует использование ресурсов и минимизирует накладные расходы, что напрямую влияет на производительность приложения. Она предусматривает использование подходящих шаблонов проектирования и технологий для удовлетворения требований к производительности.

4️⃣Улучшение безопасности
Определяют, как безопасность будет интегрирована в систему. Правильное разделение компонентов, а также использование надёжных протоколов и технологий могут значительно уменьшить риски безопасности и упростить реализацию защитных мер.

5️⃣Облегчение межкомандной работы
Когда она чётко определена, команды разработчиков могут работать над разными частями системы независимо друг от друга. Это стандартизирует технические подходы и упрощает интеграцию разработанных модулей.

6️⃣Снижение затрат
Хорошо спроектированная архитектура помогает снизить общие затраты на разработку и поддержку программного обеспечения, поскольку уменьшает количество ошибок, упрощает внесение изменений и сокращает время, необходимое для развертывания новых функций.

7️⃣Повышение надёжности и доступности
Разрабатывая архитектуру, можно предусмотреть механизмы для обеспечения высокой доступности и надёжности системы, включая резервирование, балансировку нагрузки и восстановление после сбоев.

8️⃣Удовлетворение бизнес-требований
Эффективная архитектура позволяет точнее соответствовать бизнес-требованиям и целям, обеспечивая гибкость в изменении функциональности в соответствии с изменяющимися условиями рынка или требованиями законодательства.

Архитектура ПО служит каркасом, который обеспечивает стабильность, надёжность и адаптируемость системы на протяжении всего жизненного цикла продукта. Правильная архитектура снижает риски и увеличивает шансы на успех проекта.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍42
Чем отличается frame от bounce ?
Спросят с вероятностью 36%

Понятия frame и bounds относятся к свойствам представлений (views), но имеют разные значения и используются в разных целях.

Frame

Представляет собой прямоугольник, который определяет положение и размер представления относительно его родительского представления (superview). Координаты frame указываются в системе координат родительского представления. Это означает, что frame показывает, где именно находится представление в родительском представлении и какого оно размера.

Пример: Если frame представления A равен (10, 20, 100, 200), это означает, что верхний левый угол A находится на 10 пикселей вправо и 20 пикселей вниз относительно верхнего левого угла его родительского представления, а размер A составляет 100 пикселей в ширину и 200 пикселей в высоту.

Bounds

Представляет собой прямоугольник, который определяет область отображения содержимого представления, но его координаты указываются в собственной системе координат представления. Это означает, что bounds представления всегда начинается с (0, 0) для верхнего левого угла. Изменение bounds может влиять на то, какое содержимое представления видимо, особенно если используется прокрутка.

Пример: Если bounds представления B равен (0, 0, 300, 400), это означает, что видимая область содержимого B начинается с верхнего левого угла и имеет размер 300 пикселей в ширину и 400 пикселей в высоту. Если вы измените bounds так, чтобы они начинались, например, с (50, 50, 300, 400), это сдвинет видимую область содержимого так, что верхняя левая точка видимого содержимого будет находиться на 50 пикселей вправо и 50 пикселей вниз от исходной верхней левой точки содержимого B.

Основные отличия

Система координат: Frame использует систему координат родительского представления, в то время как bounds использует собственную систему координат представления.
Использование: Frame чаще всего используется для определения положения и размера представления относительно его родительского представления, а bounds — для работы с содержимым внутри представления, например, когда необходимо управлять прокруткой.

Понимание различий между frame и bounds важно для правильной работы с макетами интерфейса и управлением представлениями в iOS и macOS разработке.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍2
👾 Ребят, напоминаю, у нас есть приватные группы где мы делимся реальными собеседованиями и тестовыми заданиями. Чтобы попасть в эти в группы воспользуйтесь ботами:
🤖 Доступ к базе собесов
🤖 Доступ к базе тестовых заданий
Каков жизненный цикл UIViewController ?
Спросят с вероятностью 36%

Жизненный цикл UIViewController описывает последовательность событий, происходящих с момента создания до уничтожения контроллера представления. Понимание этого жизненного цикла критически важно для правильного управления загрузкой, отображением, обновлением и уничтожением представлений в iOS-приложении. Вот ключевые этапы:

1️⃣Инициализация

Жизненный цикл начинается с инициализации. Обычно это происходит либо через инициализатор init(coder:) при загрузке контроллера из storyboard, либо через init(nibName:bundle:), если контроллер создаётся программно.

2️⃣Загрузка представления

`loadView`: Вызывается, когда представление контроллера загружается в память. Этот метод создаёт и назначает основное view контроллера, обычно не требуется его переопределять, если вы используете storyboard или xib-файлы.
`viewDidLoad`: Вызывается после загрузки основного представления контроллера в память. Здесь вы обычно выполняете начальную настройку интерфейса, которая должна произойти один раз за время жизни контроллера.

3️⃣Появление представления

`viewWillAppear(_:)`: Вызывается непосредственно перед тем, как представление контроллера станет видимым пользователю. Здесь можно настроить интерфейс или данные, которые должны обновляться каждый раз перед отображением представления.
`viewDidAppear(_:)`: Вызывается после того, как представление контроллера стало видимым пользователю. Здесь можно начать анимации, запустить процессы, которые должны происходить после того, как представление стало видимым.

4️⃣Обновление макета

`viewWillLayoutSubviews`: Вызывается перед тем, как контроллер представления расположит свои подпредставления. Это хорошее место, чтобы изменить размер или положение подпредставлений вручную.
`viewDidLayoutSubviews`: Вызывается после того, как контроллер представления расположил свои подпредставления. Здесь можно выполнить дополнительные настройки макета, зависящие от размеров подпредставлений.

5️⃣Исчезновение представления

`viewWillDisappear(_:)`: Вызывается непосредственно перед тем, как представление контроллера будет удалено с экрана. Используется для остановки анимаций или тяжёлых задач, сохранения состояния и так далее.
`viewDidDisappear(_:)`: Вызывается после того, как представление контроллера исчезло с экрана. Здесь можно очистить ресурсы, связанные с отображением представления.

6️⃣Уничтожение контроллера

`deinit`: Вызывается непосредственно перед тем, как контроллер представления будет уничтожен. Это место для очистки и освобождения ресурсов.

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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍71
Что известно о коллекциях (collection) ?
Спросят с вероятностью 18%

Коллекции — это структуры данных, предназначенные для группировки нескольких элементов. Они позволяют хранить, извлекать, манипулировать и коммуницировать с группами объектов. Различные языки программирования предлагают разные типы коллекций, но многие из них обладают общими чертами и функциональностью.

Общие типы коллекций

1️⃣Массивы (Arrays): Это самая базовая форма коллекций, представляющая собой упорядоченную последовательность элементов фиксированной длины. Они обеспечивают быстрый доступ к элементам по индексу.

2️⃣Списки (Lists): Списки похожи на массивы, но они позволяют динамически изменять размер. В зависимости от реализации, списки могут быть связанными списками (LinkedList) или массивными списками (ArrayList), каждый из которых имеет свои преимущества и недостатки в плане производительности операций вставки, удаления и доступа.

3️⃣Множества (Sets): Это коллекции, которые хранят только уникальные элементы. Они полезны, когда вам нужно обеспечить, чтобы в коллекции не было дубликатов. Примеры включают HashSet, который обеспечивает быстрый доступ за счет использования хеш-таблиц, и TreeSet, который сохраняет элементы в упорядоченном виде.

4️⃣Словари (Maps): Словари, или ассоциативные массивы, хранят данные в форме пар ключ-значение. Они позволяют быстро извлекать значение по ключу. Примеры включают HashMap и TreeMap.

5️⃣Очереди (Queues) и стеки (Stacks): Очереди обеспечивают порядок доступа First-In-First-Out (FIFO), тогда как стеки работают по принципу Last-In-First-Out (LIFO). Они используются во многих алгоритмах, например, в задачах парсинга или управления потоками выполнения.

Особенности и применение

Обобщение: Многие системы типов поддерживают обобщённые коллекции, позволяющие определять тип элементов, которые коллекция может содержать. Это обеспечивает типобезопасность и гибкость при работе с различными типами данных.
Производительность: Разные типы коллекций оптимизированы для различных операций. Например, доступ к элементу в массиве происходит за время O(1), в то время как вставка в середину списка может быть O(n). Выбор правильного типа коллекции важен для обеспечения оптимальной производительности приложения.
Итерация: Большинство коллекций поддерживают итерацию по своим элементам, что позволяет легко перебирать элементы коллекции.

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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍2
Друзья!

Хочу вас познакомить с замечательным пабликом SwiftyGroup! Здесь вы найдете ответы на самые актуальные вопросы с собеседований, а также сможете порешать интересные задачи и ознакомиться с полезными статьями.

В SwiftyGroup мы еженедельно публикуем:

Вопросы и ответы с реальных собеседований
Статьи по подготовке к собеседованиям и развитию профессиональных навыков
Задачи для самостоятельного решения и проверки своих знаний
Присоединяйтесь к нашему сообществу и будьте всегда готовы к любым профессиональным вызовам!
🔥2👀1
Что такое enum, raw value и associated value ?
Спросят с вероятностью 36%

enum (перечисление) — это тип, который позволяет группировать вместе тесно связанные значения. Перечисления могут иметь "raw values" (базовые значения), "associated values" (ассоциированные значения) или и то, и другое, что делает их мощным инструментом.

Raw Values (Базовые значения)

Представляют собой предустановленные значения для каждого из случаев перечисления. Все случаи перечисления имеют один и тот же тип данных для своих "raw values". Эти значения могут быть строками, символами, числами или значениями любого другого типа, который соответствует протоколу RawRepresentable.

Пример:
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
Здесь каждому случаю перечисления
Planet присваивается целочисленное значение, начиная с 1 для mercury и увеличиваясь на 1 для каждого последующего случая.

Associated Values (Ассоциированные значения)

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

Пример:
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

В этом примере Barcode может быть либо UPC-кодом с четырьмя целочисленными значениями, либо QR-кодом со строковым значением.

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

Перечисления являются мощным средством для организации связанных значений в вашем коде, позволяя при этом сохранять типобезопасность и ясность.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍71🔥1
Что такое синхронная задача ?
Спросят с вероятностью 36%

Синхронная задача — это такая операция или задача, выполнение которой блокирует дальнейшее продвижение программы до тех пор, пока она не будет завершена. То есть, при запуске синхронной задачи программа останавливает все последующие операции и ждёт, когда задача будет выполнена, прежде чем продолжить выполнение другого кода.

Эти операции просты в понимании и реализации, так как они следуют прямой последовательности выполнения: программа выполняет одну операцию за другой, в точном порядке их появления в коде. Это может быть полезно, когда нужно гарантировать, что некоторые данные будут обработаны или подготовлены до начала следующей операции.

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

Пример:
func loadUserData() {
let userData = fetchUserData() // Синхронный вызов, блокирующий поток
updateUI(with: userData) // Этот код будет выполнен только после завершения fetchUserData()
}

В этом примере fetchUserData() выполняется синхронно: updateUI(with:) не начнёт выполняться, пока fetchUserData() полностью не завершится и не вернёт данные пользователя.

Асинхронное выполнение позволяет приложению продолжать обрабатывать другие события или задачи, в то время как ожидается завершение длительной операции, тем самым улучшая взаимодействие с пользователем и общую производительность.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍72
В чём разница между open и public ?
Спросят с вероятностью 36%

open и public — это модификаторы доступа, которые определяют, как и где можно использовать классы, методы и свойства. Различие между open и public важно понимать при проектировании API библиотек и фреймворков, так как оно влияет на возможности наследования и переопределения в модулях и подключаемых пакетах.

Public

Уровень доступа позволяет элементам быть видимыми и доступными вне определённого модуля (библиотеки или фреймворка), в котором они объявлены. Однако он ограничивает возможность наследования классов и переопределения методов в модулях, отличных от того, где класс или метод были первоначально объявлены. То есть, можно использовать public классы и методы в любом месте вашего проекта или в других проектах, которые импортируют ваш модуль, но вы не можете создавать подклассы или переопределять public методы за пределами их оригинального модуля.

Open

Уровень доступа расширяет public возможности, позволяя не только использовать классы и методы вне модуля, но и наследовать классы, а также переопределить методы в подклассах, находящихся вне модуля, где был объявлен оригинальный класс. Он является наиболее гибким уровнем доступа и должен использоваться с осторожностью, так как он предоставляет внешним модулям возможность изменять поведение вашего кода.

Примеры:
// В модуле A
public class PublicClass {
public var property: Int = 0
public func method() {}
}

open class OpenClass {
open var property: Int = 0
open func method() {}
}

// В модуле B, который импортирует модуль A
class SubclassOfPublicClass: PublicClass {
// Это будет ошибка, если попытаться переопределить property или method
}

class SubclassOfOpenClass: OpenClass {
// Это разрешено: можно переопределить property и method
}


Когда использовать

public, когда хотите разрешить использование классов, методов или свойств вне вашего модуля, но не хотите разрешать их наследование или переопределение.
open, когда предоставляете API, который специально предназначен для наследования и переопределения в клиентском коде, включая код вне модуля.

Выбор между open и public влияет на архитектуру и возможности расширения вашего кода. Open предоставляет большую гибкость для пользователей вашего API, но требует более тщательного проектирования и документирования, чтобы обеспечить безопасное наследование и переопределение.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
11👍1
Привет, я Леха. Вопросы собеседований берутся с моего сайта easyoffer.ru. Его я делал как пет-проект, чтобы устроиться на работу, но сейчас проект уже перерастает в стартап и я пишу об этом в своем TG блоге Идущий к IT и на YouTube.

"Как считается вероятность вопросов?"

Об этом писал в статье на Habr

Если нашли ошибку в посте пишите @aurumsunset
Если хотите купить рекламу на канале пишите @easyoffer_adv
Чтобы получить доступ к приватной группе, где мы выкладываем реальные записи собеседований переходите в бота
Аналогично для тестовых заданий вот этот бот
Please open Telegram to view this post
VIEW IN TELEGRAM
7
Swift | Вопросы собесов pinned «Привет, я Леха. Вопросы собеседований берутся с моего сайта easyoffer.ru. Его я делал как пет-проект, чтобы устроиться на работу, но сейчас проект уже перерастает в стартап и я пишу об этом в своем TG блоге Идущий к IT и на YouTube. "Как считается вероятность…»
👾 823 вопросов собесов на Swift Developer
🔒 База реальных собесов
🔒 База тестовых заданий
👾 Список менторов

👩‍💻 Swift
Вакансии
LeetCode ответы
Тесты

👣 Golang
Вопросы собесов
Вакансии
LeetCode ответы
Тесты

👩‍💻 С/С++
Вопросы собесов
Вакансии
LeetCode ответы
Тесты

👩‍💻 PHP
Вопросы собесов
Вакансии
LeetCode ответы
Тесты

🖥 Frontend
Вопросы собесов
├ Вакансии
LeetCode ответы
Тесты

🖥 Тестировщик
├ Вопросы собесов
├ Вакансии
Тесты

🖥 Python
Вопросы собесов
Вакансии
├ LeetCode ответы
└ Тесты

👩‍💻 Java
├ Вопросы собесов
├ Вакансии
├ LeetCode ответы
└ Тесты

👩‍💻 Kotlin
├ Вопросы собесов
├ Вакансии
├ LeetCode ответы
└ Тесты

👩‍💻 С#
├ Вопросы собесов
├ Вакансии
├ LeetCode ответы
└ Тесты

🖥 Data Science
├ Вопросы собесов
├ Вакансии
└ Тесты

👩‍💻 DevOps
├ Вопросы собесов
├ Вакансии
└ Тесты

Backend
└ Вопросы собесов
Please open Telegram to view this post
VIEW IN TELEGRAM
👍94