Swift | Вопросы собесов
2.13K subscribers
28 photos
936 links
Download Telegram
Привет, ребят, хочу сделать так, чтобы для каждого вопроса было поясняющее видео в reels/shorts формате.

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

Если интересует такая подработка напишите мне @kivaiko
👍15
Сколько может быть куч и стеков в приложении ?
Спросят с вероятностью 27%

В операционных системах, используемых для запуска приложений, обычно используется понятие одной кучи (heap) и множества стеков (stack) для управления памятью. Их количество зависит от модели выполнения приложения, в частности, от количества потоков, которые оно использует.

Куча

Как правило, в приложении используется одна куча для динамического распределения памяти. Эта область памяти используется для выделения и освобождения памяти во время выполнения программы, например, при создании объектов в куче (в языках программирования высокого уровня, таких как C#, Java, Python, Swift и других). Однако, в зависимости от реализации операционной системы и среды выполнения, может существовать несколько куч:

Общая куча (Global Heap): Используется всеми потоками приложения.
Приватные/локальные кучи: Операционные системы или среды выполнения могут предоставлять возможность создавать отдельные кучи для использования определёнными частями приложения или для управления специфическими типами данных.

Стек

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

Основной поток (Main Thread): Имеет свой стек.
Рабочие потоки (Worker Threads): Каждый из них имеет свой стек.

Куча: Обычно одна на приложение, но могут быть случаи, когда используется несколько куч (например, для управления разными типами ресурсов или в многопоточных приложениях с приватными кучами для каждого потока).
Стек: Один на каждый поток выполнения в приложении.

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

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

🔐 База собесов | 🔐 База тестовых
8🔥3
Какая разница между semaphore и mutex ?
Спросят с вероятностью 18%

Семафоры и мьютексы (mutexes) используются для синхронизации доступа к ресурсам. Хотя оба этих инструмента обеспечивают средства контроля за доступом к ресурсам, они имеют различные цели и реализации.

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

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

Semaphore (Семафор)
Используется для управления доступом к ограниченному числу ресурсов. Он может быть настроен так, чтобы позволять доступ нескольким потокам одновременно.

Ключевые особенности:
Счётчик: Управляется с помощью счётчика, который указывает количество доступных ресурсов или разрешений.
Гибкость: Могут быть использованы для регулирования доступа к нескольким экземплярам ресурса, в то время как мьютексы всегда предназначены только для одного ресурса.
Блокировка и освобождение: Когда поток запрашивает семафор, счётчик уменьшается. Когда поток освобождает семафор, счётчик увеличивается. Если счётчик равен нулю, потоки будут заблокированы до его освобождения.

Отличия и когда использовать

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

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

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

🔐 База собесов | 🔐 База тестовых
👍7
Как можно решить проблему с долгой необоснованной прогрузкой картинок ?
Спросят с вероятностью 18%

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

1️⃣Оптимизация изображений
Сжатие изображений: Уменьшение размера файлов изображений без значительной потери качества может значительно ускорить их загрузку. Используйте форматы файлов, такие как JPEG для фотографий или PNG для изображений с прозрачностью, и инструменты сжатия.

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

2️⃣Использование кеширования
Кеширование браузера: Убедитесь, что HTTP-заголовки кеширования настроены правильно, чтобы браузеры могли сохранять изображения в кеше. Это уменьшит количество загрузок тех же изображений при повторных посещениях.

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

3️⃣Ленивая загрузка (Lazy Loading)
Загружает контент по мере необходимости, когда он находится в области просмотра, а не сразу все изображения на странице. Это может значительно ускорить время загрузки страницы и уменьшить использование данных.

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

5️⃣Предзагрузка ресурсов
Если вы знаете, что пользователь скорее всего будет нуждаться в определенных изображениях в процессе навигации, можно использовать предзагрузку (Preloading). Это указание браузеру заранее загрузить определенные ресурсы, которые скоро понадобятся.

6️⃣Использование CDN
Размещает ваш контент на множестве серверов по всему миру, что уменьшает латентность, ускоряя загрузку ресурсов благодаря физической близости к пользователю.

7️⃣Мониторинг производительности
Регулярно проверяйте и анализируйте производительность загрузки ваших изображений с помощью инструментов, таких как Google PageSpeed Insights, Lighthouse и других. Это поможет вам идентифицировать проблемные области и отслеживать эффективность внедренных улучшений.

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

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

🔐 База собесов | 🔐 База тестовых
👍4🤯2🤔1
В чем заключается суть оптимизации ?
Спросят с вероятностью 18%

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

Цели:

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

2️⃣Сокращение потребления ресурсов: Уменьшение объёма используемой оперативной памяти, дискового пространства или пропускной способности сети. Это может быть критически важно для приложений, работающих на устройствах с ограниченными ресурсами, например, на мобильных устройствах.

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

4️⃣Улучшение масштабируемости: Оптимизация программного обеспечения для обработки большего количества задач параллельно или обслуживания большего числа пользователей одновременно.

5️⃣Улучшение удобства пользователя: Сокращение времени отклика приложения на действия пользователя, что делает интерфейс более отзывчивым и приятным в использовании.

Методы:

1️⃣Профилирование: Использование специальных инструментов для анализа, где приложение проводит больше всего времени или потребляет больше всего ресурсов. Это помогает идентифицировать "узкие места" и приоритизировать усилия по оптимизации.

2️⃣Оптимизация алгоритмов: Замена медленных алгоритмов на более быстрые и эффективные. Например, использование хеш-таблиц вместо списков для быстрого поиска данных.

3️⃣Асинхронное программирование: Использование асинхронных операций для улучшения отклика приложения, позволяя пользовательскому интерфейсу оставаться отзывчивым во время выполнения длительных операций.

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

5️⃣Избегание избыточности: Удаление повторяющихся или ненужных операций в коде.

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

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

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

ARC, или Automatic Reference Counting — это система управления памятью. Он автоматически отслеживает и управляет жизненным циклом объектов в памяти, освобождая разработчика от необходимости вручную увеличивать или уменьшать счетчик ссылок на объекты.

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

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

Увеличение счетчика ссылок: Каждый раз, когда вы создаете новую сильную ссылку (strong reference) на объект (например, присваивая объект переменной или свойству), ARC автоматически увеличивает счетчик ссылок на этот объект.
Уменьшение счетчика ссылок: Когда сильная ссылка на объект уничтожается (например, когда переменная выходит из области видимости или ей присваивается значение nil), ARC уменьшает счетчик ссылок на объект.
Освобождение памяти: Когда счетчик ссылок на объект достигает нуля, ARC автоматически освобождает память, занимаемую этим объектом.

ARC и управление циклическими ссылками:

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

Для решения этой проблемы предлагается два типа ссылок, которые не увеличивают счетчик ссылок:
weak: Слабые ссылки (weak) не увеличивают счетчик ссылок и автоматически становятся nil, когда объект уничтожается. Они обычно используются для предотвращения циклических ссылок, когда объекты могут быть уничтожены в любой момент.
unowned: Несильные ссылки (unowned) похожи на слабые, но предполагают, что другой объект будет иметь тот же срок жизни или более долгий срок жизни. unowned ссылки не становятся nil и могут привести к ошибкам времени выполнения, если вы попытаетесь получить доступ к объекту, который уже был освобожден.

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

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

🔐 База собесов | 🔐 База тестовых
👍5
🔥Тесты для подготовки к собеседованию🔥
Выбери своё направление:

1. Frontend
2. Python
3. Java
4. Тестировщик QA
5. Data Science
6. DevOps
7. C#
8. С/C++
9. Golang
10. PHP
11. Kotlin
12. Swift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍4
Какие есть два типа инициализаторов ?
Спросят с вероятностью 27%

Существуют два основных типа инициализаторов: обозначенные (Designated) и вспомогательные (Convenience). Эти типы инициализаторов играют важную роль в процессе инициализации экземпляров классов, помогая управлять процессом создания объектов с корректным начальным состоянием.

Обозначенные инициализаторы (Designated Initializers)

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

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

Пример:
class Person {
var name: String
var age: Int

init(name: String, age: Int) {
self.name = name
self.age = age
}
}

В этом примере
init(name: String, age: Int) является обозначенным инициализатором для класса Person, который инициализирует все свойства класса.

Вспомогательные инициализаторы (Convenience Initializers)

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

Пример:
class Person {
var name: String
var age: Int

init(name: String, age: Int) {
self.name = name
self.age = age
}

convenience init() {
self.init(name: "Unknown", age: 0)
}
}


Здесь convenience init() является вспомогательным инициализатором, который предоставляет возможность создать экземпляр Person с некоторыми значениями по умолчанию.

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

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

Понимание этих двух типов инициализаторов важно для корректной инициализации объектов, особенно при работе с наследованием и расширением классов.

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

🔐 База собесов | 🔐 База тестовых
🔥75👍4
Когда использовать Set вместо Array ?
Спросят с вероятностью 18%

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

Array (Массив)
Это упорядоченная коллекция элементов, которая позволяет хранить дублирующиеся значения. Массивы предоставляют следующие характеристики:

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

Использование массивов:
Когда порядок элементов важен.
Когда необходимо часто получать доступ к элементам по индексу.
Когда вам нужно часто добавлять и удалять элементы из конца коллекции (особенно для динамически расширяемых массивов).

Set (Множество)
Представляет собой неупорядоченную коллекцию уникальных элементов. Это означает, что множество не может содержать дубликатов. Основные характеристики множеств включают:

1️⃣Уникальность: Все элементы в множестве уникальны.
2️⃣Неупорядоченность: Элементы в множестве не хранятся в каком-либо определенном порядке.
3️⃣Эффективность операций: Операции добавления, удаления и проверки на вхождение обычно более эффективны для множеств по сравнению с массивами из-за использования хеш-таблиц.

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

Примеры:

Массив:
var visitors = ["Alice", "Bob", "Alice", "Joe"]
print(visitors[1]) // Выводит "Bob"
// Используется для учёта всех посещений, включая повторные


Множество:
var uniqueVisitors: Set = ["Alice", "Bob", "Alice", "Joe"]
print(uniqueVisitors) // Выводит ["Alice", "Bob", "Joe"]
// Используется для учёта уникальных посетителей


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

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

🔐 База собесов | 🔐 База тестовых
🔥9👍31
Как в Swift устроена инкапсуляция ?
Спросят с вероятностью 27%

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

Уровни доступа:

1️⃣Public: Члены класса доступны из любого кода в том же модуле и вне его. Используется для определения интерфейса публичного API.
2️⃣Open: Такой же уровень доступа, как и public, но в дополнение позволяет классам и членам класса быть наследованными и переопределенными вне модуля, в котором они объявлены.
3️⃣Internal: Члены класса доступны в любом месте кода в их собственном модуле или приложении, но недоступны за его пределами. Это уровень доступа по умолчанию.
4️⃣Fileprivate: Ограничивает доступ к членам класса в пределах того же файла исходного кода.
5️⃣Private: Самый строгий уровень доступа, ограничивающий область видимости членов класса контекстом, в котором они объявлены. Начиная с Swift 4, private также означает доступность в расширениях класса в том же файле.

Примеры:
class SomeClass {
private var privateVariable: Int = 0 // Доступна только внутри `SomeClass`
fileprivate func fileprivateMethod() {} // Доступен в любом месте внутри того же файла исходного кода
internal func internalMethod() {} // Доступен в любом месте внутри того же модуля (по умолчанию)
public var publicVariable: Int = 0 // Доступна из любого места в том же модуле и из внешних модулей
open func openMethod() {} // Может быть переопределен во внешних модулях
}

private class PrivateClass {} // Доступен только внутри текущего файла


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

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

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

Протокол Hashable позволяет объекту быть использованным в качестве ключа в словаре (Dictionary) или элемента в множестве (Set). Чтобы объект мог выполнять эту роль, он должен быть уникально идентифицируемым, чтобы каждый экземпляр объекта мог быть сравним с другими экземплярами и иметь уникальное хэш-значение. Это требование обеспечивается реализацией двух требований протокола: Equatable и hash(into:).

Equatable

Это протокол, который требует от типов предоставить реализацию оператора равенства (==), позволяя сравнивать два экземпляра данного типа. Для использования в качестве ключа словаря или элемента множества объекты должны поддерживать возможность такого сравнения на равенство.

hash(into:)

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

Пример:
struct Person: Hashable {
var name: String
var age: Int

static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}

func hash(into hasher: inout Hasher) {
hasher.combine(name)
hasher.combine(age)
}
}


В этом примере Person структура реализует Hashable, предоставляя реализации для == и hash(into:). Это позволяет использовать Person в качестве ключей в Dictionary или элементов в Set.

Данный протокол необходим для:

Использования объектов в качестве ключей словаря. Эффективный поиск и доступ к элементам словаря требуют уникального идентификатора для каждого ключа.
Включения объектов в множество. Множества (Set) гарантируют уникальность своих элементов, что требует возможности сравнения этих элементов на равенство и вычисления их хэш-значений.

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

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

🔐 База собесов | 🔐 База тестовых
👍81
Для чего нужен optional ?
Спросят с вероятностью 27%

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

Основные цели использования:

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

2️⃣Упрощение кода: Вместо того чтобы использовать специальные значения (например, -1 или 0 для числовых значений) для обозначения отсутствия реального значения, опционалы позволяют использовать nil. Это делает код чище и его намерения — более ясными.

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

Пример:
var maybeString: String? = "Hello"
print(maybeString) // Выведет "Optional("Hello")"

// Для безопасного извлечения значения из опционала можно использовать условное связывание
if let actualString = maybeString {
print(actualString) // Выведет "Hello"
} else {
print("maybeString не содержит значения")
}

// Или использовать оператор разворачивания опционала
print(maybeString!) // Выведет "Hello", но приведёт к ошибке выполнения, если maybeString == nil

// Использование оператора объединения с nil для предоставления значения по умолчанию
print(maybeString ?? "Значение отсутствует")


Механизмы работы:

Принудительное извлечение: Использование ! после имени опционала. Это рискованный подход, так как при попытке извлечения значения из nil произойдёт ошибка выполнения.
Опциональное связывание: Позволяет безопасно проверить и извлечь значение из опционала.
Опциональные цепочки: Позволяют запрашивать свойства, методы и индексы на опциональном значении и возвращают опционал.
Оператор объединения с nil (`??`): Позволяет задать значение по умолчанию, которое будет использовано в случае, если опционал содержит nil.

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

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

🔐 База собесов | 🔐 База тестовых
👍3
Зачем нужны свойства "Content Hugging Priority" ?
Спросят с вероятностью 18%
ID 7449

Свойства "Content Hugging Priority" и "Content Compression Resistance Priority" играют ключевую роль в системе Auto Layout. Эти свойства помогают определить, как вьюшки (views) должны быть отформатированы и как они реагируют на изменения в доступном пространстве в интерфейсе пользователя. Рассмотрим подробнее, что означает каждое из этих свойств и как они используются в разработке интерфейсов.

Content Hugging Priority

Определяет, насколько сильно вьюшка должна "обнимать" своё содержимое. Это свойство указывает на желательность вьюшки быть как можно ближе к своим внутренним размерам, основанным на своем содержимом.

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

Если у вас есть метка (label) с текстом, которая должна расширяться или сжиматься в зависимости от количества текста, установка высокого Content Hugging Priority для этой метки гарантирует, что она будет расти и уменьшаться как можно точнее по размеру текста.

Content Compression Resistance Priority

Определяет, насколько сильно вьюшка должна противостоять сжатию размеров меньше, чем размеры её содержимого.

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

Для кнопки с текстом "Купить сейчас!" вы захотите установить высокий приоритет сопротивления сжатию, чтобы убедиться, что текст кнопки всегда полностью видим и не сжат.

Взаимодействие свойств

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

Понимание и правильное использование Content Hugging Priority и Content Compression Resistance Priority позволяют разработчикам создавать гибкие и адаптивные интерфейсы, которые хорошо выглядят на разных устройствах и при различных условиях содержимого.

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

🔐 База собесов | 🔐 База тестовых
👍5
🤔 Какая конструкция в Swift позволяет безопасно развернуть опционал?
Anonymous Quiz
67%
if let
27%
guard else
4%
unwrap
2%
force unwrap
👍2
Какие методы жизненного цикла у view controller'а известны ?
Спросят с вероятностью 18%

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

1️⃣loadView()
Вызывается, когда контроллеру вью нужно создать свою view. Обычно вы не должны вызывать этот метод напрямую или его переопределять, если только вы не загружаете view не из storyboard, а создаёте её программно.

2️⃣viewDidLoad()
Вызывается после загрузки view контроллера в память. Этот метод вызывается один раз за время существования контроллера и является местом для выполнения всех начальных настроек, создания визуальных элементов, которые не изменяются, и первоначальной конфигурации данных.

3️⃣viewWillAppear(_:)
Вызывается перед тем, как view будет добавлена к иерархии view. Используется для выполнения задач, связанных с появлением view, таких как обновление пользовательского интерфейса, запуск анимаций или мониторинг изменений в данных или состоянии.

4️⃣viewDidAppear(_:)
Вызывается после того, как view добавлена к иерархии view и представлена на экране. Это хорошее место для начала анимаций, загрузки данных, которые необходимо обновлять каждый раз при появлении view, или для начала таких операций, как отслеживание местоположения или внешние запросы данных, которые должны запускаться только когда view активна.

5️⃣viewWillDisappear(_:)
Вызывается перед тем, как view будет удалена из иерархии view. Это время для остановки анимаций, сохранения измененных данных и отмены любых задач, начатых при появлении view.

6️⃣viewDidDisappear(_:)
Вызывается после удаления view из иерархии view. Здесь можно освободить ресурсы, связанные с view, остановить службы, такие как таймеры, или отписаться от уведомлений, которые не нужны, когда view не видно.

7️⃣viewWillLayoutSubviews()
Вызывается перед тем, как контроллер вью будет располагать свои подвиды. Этот метод хорош для изменения размеров или изменения расположения подвидов вручную.

8️⃣viewDidLayoutSubviews()
Вызывается после того, как контроллер вью расположил свои подвиды. Это полезно, если вам нужно сделать дополнительные настройки после того, как система расположения завершила свою работу.

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

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

🔐 База собесов | 🔐 База тестовых
🔥73
Какие есть способы развертывания optional ?
Спросят с вероятностью 27%

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

1️⃣Принудительное развертывание (forced unwrapping)

Использует оператор ! для доступа к значению опционала напрямую. Этот способ следует использовать только тогда, когда вы уверены, что опционал содержит значение, иначе приложение аварийно завершит работу, если опционал окажется равным nil.
let optionalNumber: Int? = 5
let number: Int = optionalNumber! // Принудительное развертывание


2️⃣Опциональное связывание (optional binding)

Позволяет проверить, содержит ли опционал значение, и, если да, сразу же присвоить это значение переменной или константе. Это безопасный способ работы с опционалами.
if let number = optionalNumber {
print("У нас есть значение: \(number)")
} else {
print("Значение отсутствует")
}


3️⃣Опциональное связывание с guard

Так же, как и предыдущий метод, но позволяет рано выйти из блока кода, если значение отсутствует. Это удобно для уменьшения вложенности и улучшения читаемости кода.
guard let number = optionalNumber else {
print("Значение отсутствует")
return
}
print("У нас есть значение: \(number)")


4️⃣Оператор объединения (nil coalescing operator)

Позволяет задать значение по умолчанию, которое будет использоваться в случае, если опционал равен nil.
let number = optionalNumber ?? 0 // Возвращает 0, если optionalNumber равен nil


5️⃣Опциональные цепочки (optional chaining)

Позволяют запрашивать свойства, методы и индексы на опционале в манере, которая не вызовет ошибки, если опционал равен nil. Вместо этого выражение вернет nil.
let count: Int? = optionalString?.count


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

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

🔐 База собесов | 🔐 База тестовых
👍17
Что такое автоматический подсчет ссылок ?
Спросят с вероятностью 18%

Автоматический подсчёт ссылок (Automatic Reference Counting, ARC) — это технология управления памятью, которая автоматически отслеживает и управляет памятью объектов в языках программирования, таких как Objective-C и Swift. ARC используется для облегчения задачи разработчиков, автоматизируя процесс управления памятью, который ранее требовал явного выделения и освобождения памяти.

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

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

Когда счетчик ссылок объекта достигает нуля, это означает, что на объект больше нет активных ссылок, и память, занимаемая объектом, может быть освобождена. ARC тогда автоматически вызывает деструктор объекта (если он есть) и освобождает память.

Преимущества:
Уменьшение утечек памяти: Значительно уменьшает риск утечек памяти, так как автоматически освобождает объекты, которые больше не используются.
Простота использования: Поскольку он автоматизирует управление памятью, разработчикам не нужно явно вызывать методы для выделения и освобождения памяти, что упрощает написание кода и уменьшает вероятность ошибок.
Безопасность и чистота кода: Управление памятью с ARC более безопасно, чем традиционное ручное управление памятью, и способствует написанию более чистого и легко поддерживаемого кода.

Недостатки:
Циклические ссылки: Одна из основных проблем ARC — это управление циклическими ссылками, когда два объекта взаимно ссылаются друг на друга, что приводит к тому, что счетчики ссылок никогда не достигают нуля. Разработчики должны явно управлять такими ситуациями с помощью слабых (weak) и неуправляемых (unowned) ссылок.
Контроль над временем жизни объекта: В некоторых случаях разработчикам может потребоваться более тонкий контроль над временем жизни объекта, чем тот, который предоставляет ARC.

Использование ссылок

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

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

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

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

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

Использование MemoryLayout

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

Пример использования MemoryLayout в Swift:
struct ExampleStruct {
var a: Int
var b: Bool
}

print("Size of ExampleStruct: \(MemoryLayout<ExampleStruct>.size)")
print("Stride of ExampleStruct: \(MemoryLayout<ExampleStruct>.stride)")
print("Alignment of ExampleStruct: \(MemoryLayout<ExampleStruct>.alignment)")


Размер протокола

Может быть запутанным, так как протоколы сами по себе не занимают пространство; они определяют интерфейс, которому должны соответствовать типы данных. Протоколы в Swift не имеют прямого размера в памяти, так как они не являются конкретными данными, а скорее определяют "шаблон", который должны следовать объекты или структуры.

Однако, если вы работаете с экземплярами типов, соответствующих протоколу, то может возникнуть вопрос о размере этих экземпляров. В случае использования типа Any или любого другого обобщенного типа, который может принимать значения любых типов, соответствующих протоколу, размер такой переменной будет определяться как размер указателя в данной системе (обычно это 8 байт на 64-битных системах).

Пример определения размера типа, соответствующего протоколу:
protocol SomeProtocol {
var num: Int { get set }
}

struct SomeStruct: SomeProtocol {
var num: Int
}

print("Size of SomeStruct: \(MemoryLayout<SomeStruct>.size)")


В этом примере, размер SomeStruct, которая соответствует SomeProtocol, будет равен размеру его единственного свойства num типа Int.

Размеры типов данных, соответствующих протоколу, зависят от их конкретной реализации, а сам протокол не имеет непосредственного "размера" в традиционном понимании.

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

🔐 База собесов | 🔐 База тестовых
🔥41
🤔 Какой модификатор доступа в Swift является наиболее ограничивающим?
Anonymous Quiz
1%
public
14%
internal
84%
fileprivate
1%
open
Что может быть ключом и значением для dictionary ?
Спросят с вероятностью 27%

Словарь (Dictionary) представляет собой коллекцию пар ключ-значение, где каждый ключ должен быть уникальным. Чтобы использовать какой-либо тип в качестве ключа словаря, этот тип должен соответствовать протоколу Hashable. Это требование обусловлено тем, что Swift использует хеш-таблицу для хранения элементов словаря, что обеспечивает быстрый доступ к его элементам.

Ключи

Должны быть уникальными: Каждый ключ в словаре должен быть уникальным. При попытке добавить в словарь элемент с ключом, который уже существует в словаре, старое значение будет заменено на новое.
Должны соответствовать протоколу `Hashable`: Это означает, что тип ключа должен иметь способность быть правильно хешированным. Большинство базовых типов Swift (например, String, Int, Double и др.) уже соответствуют Hashable, поэтому их можно использовать в качестве ключей без дополнительных усилий.

Значения

Могут быть любого типа: Значения в словаре могут быть любого типа, и они не обязаны соответствовать протоколу Hashable.
Могут повторяться: Разные ключи могут иметь одинаковые значения.

Пример:
var personAge: [String: Int] = ["John": 30, "Sara": 25]


В этом примере ключами являются строки (String), представляющие имена людей, а значениями — целые числа (Int), представляющие их возраст. Тип String соответствует Hashable, что делает его подходящим в качестве ключа для Dictionary.

Собственные типы в качестве ключей

Вы также можете использовать собственные пользовательские типы в качестве ключей словаря, но для этого ваш тип должен соответствовать протоколу Hashable. Это включает в себя реализацию требуемых методов для сравнения на равенство (==) и хеширования (hash(into:)).
struct Person: Hashable {
var name: String
var id: Int
}

var peopleDictionary: [Person: String] = [Person(name: "John", id: 1): "Engineer"]


Здесь Person — это пользовательский тип, соответствующий Hashable, что позволяет использовать его в качестве ключа. Значения в этом словаре — строки, описывающие профессию человека.

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

🔐 База собесов | 🔐 База тестовых
1