Swift | Вопросы собесов
2.13K subscribers
28 photos
949 links
Download Telegram
🤔 В чем суть оптимизации copy on write?

Copy on Write (COW) — это оптимизация, которая откладывает копирование данных до тех пор, пока они не будут изменены. В Swift, структуры и коллекции используют эту технику, чтобы избежать ненужных копий, если данные остаются неизменными. Когда структура или коллекция копируется, реальное копирование происходит только при попытке изменить данные, что снижает накладные расходы. Это помогает улучшить производительность и снизить использование памяти.

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

Приложения на Swift могут быть массивными из-за нескольких факторов:

🚩Причины

🟠Стандартная библиотека
Включает много функций и структур данных, что увеличивает размер бинарного файла.
🟠Архитектура приложения
Современные приложения часто используют множество внешних библиотек и фреймворков, добавляющих объем.
🟠Поддержка нескольких архитектур
Компиляция для разных архитектур (например, arm64, x86_64) увеличивает размер исполняемого файла.
🟠Ресурсы и медиафайлы
Большое количество изображений, видео и аудиофайлов увеличивают размер приложения.
🟠Символы отладки
Включение символов отладки для разработки и анализа сбоев добавляет объем.
🟠Статические библиотеки
Статические библиотеки увеличивают размер исполняемого файла по сравнению с динамическими.
🟠Кросс-компиляция
Поддержка старых версий iOS требует включения дополнительных библиотек и кода.

🚩Оптимизация размера

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

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое value types?

Value types в Swift — это типы данных, которые копируются при передаче в другую переменную или константу. Примеры value types включают структуры (struct), перечисления (enum) и встроенные типы данных, такие как Int и String. Когда вы изменяете копию value type, оригинальная переменная остаётся неизменной. Это поведение помогает избегать неожиданных изменений данных при работе с несколькими переменными.

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

🟠Побочные эффекты
PO вызывает методы description или debugDescription, которые могут изменять состояние объекта.

🟠Производительность
Тяжелые вычисления в методах description или debugDescription могут замедлить отладку.

🟠Проблемы с потоками
Доступ к объекту в многопоточной среде может привести к состоянию гонки.

🟠Краш приложения
Ошибки в методах description или debugDescription могут привести к сбоям при использовании PO.

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

🚩Примеры проблем

Побочные эффекты
class DangerousObject {
var counter = 0
var description: String {
counter += 1 // Изменение состояния
return "Counter: \(counter)"
}
}


Производительность
class HeavyObject {
var description: String {
let result = (0..<1_000_000).map { $0 * $0 }.reduce(0, +)
return "Result: \(result)"
}
}


Проблемы с потоками
class ThreadUnsafeObject {
var data = [Int]()
var description: String {
return "Data count: \(data.count)"
}
}


Краш приложения
class CrashObject {
var description: String {
fatalError("Should not be called")
}
}


Зависания
class LockObject {
let lock = NSLock()
var description: String {
lock.lock()
defer { lock.unlock() }
return "Locked"
}
}


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

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

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

Это текстовый протокол для общения в реальном времени. Он позволяет пользователям обмениваться сообщениями в каналах (чат-румах) или через личные сообщения.

🚩Характеристики

🟠Каналы
Объединяют пользователей для обсуждения общих тем.
🟠Личные сообщения
Прямой обмен сообщениями между пользователями.
🟠Серверы
Поддерживают несколько каналов и управляют соединениями пользователей.
🟠Клиенты
Программы, используемые для подключения к IRC-серверам и участия в чатах.

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

🟠Подключение к IRC-серверу.
🟠Вход в канал (например, #example).
🟠Обмен сообщениями с другими пользователями в канале или через личные сообщения.

🚩Плюсы

Простота и быстрота обмена сообщениями.
Возможность участия в нескольких каналах одновременно.

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

Инкапсуляция реализуется через модификаторы доступа (private, fileprivate, internal, public, open), ограничивающие доступ к свойствам и методам. Это позволяет контролировать, какие части кода могут изменять данные объекта.

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

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

🚩Механизмы реализации Synchronized

Различные механизмы синхронизации реализуют Synchronized по-разному, но общая идея заключается в использовании блокировок (локов), чтобы обеспечить эксклюзивный доступ к ресурсу.

🟠NSLock
Это простая блокировка, предоставляемая Foundation framework в Swift:
class ThreadSafeClass {
private var internalState = 0
private let lock = NSLock()

func increment() {
lock.lock()
internalState += 1
lock.unlock()
}

func getState() -> Int {
lock.lock()
let state = internalState
lock.unlock()
return state
}
}


🟠DispatchQueue
DispatchQueue позволяет организовать выполнение кода в синхронном или асинхронном режиме.
class ThreadSafeClass {
private var internalState = 0
private let queue = DispatchQueue(label: "com.example.threadSafeQueue")

func increment() {
queue.sync {
internalState += 1
}
}

func getState() -> Int {
return queue.sync {
internalState
}
}
}


🟠objc_sync_enter / objc_sync_exit
Эти функции используются для синхронизации в Objective-C и могут быть использованы в Swift.
class ThreadSafeClass: NSObject {
private var internalState = 0

func increment() {
objc_sync_enter(self)
internalState += 1
objc_sync_exit(self)
}

func getState() -> Int {
objc_sync_enter(self)
let state = internalState
objc_sync_exit(self)
return state
}
}


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

Hashable — это протокол, позволяющий объектам быть хэшируемыми для использования в структурах данных, таких как Set или Dictionary. Он требует реализации метода hash(into:).

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

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

🚩Как работают

🟠Аллокация (выделение памяти)
Статическая аллокация: Память выделяется во время компиляции и существует на протяжении всего времени выполнения программы. Используется для глобальных и статических переменных.
int globalVar = 10; // Статическая память     


Стековая аллокация: Память выделяется при вызове функции и освобождается при выходе из функции. Используется для локальных переменных.
void function() {
int localVar = 20; // Стековая память
}


Куча (динамическая аллокация): Память выделяется по запросу во время выполнения программы и освобождается вручную (в языках с ручным управлением памятью) или автоматически (в языках с автоматическим управлением памятью, например, через сборщик мусора).
int *ptr = (int*)malloc(sizeof(int) * 10); // Выделение памяти в куче
free(ptr); // Освобождение памяти


🟠Деаллокация (освобождение памяти)
Вручную: Программист отвечает за освобождение памяти, выделенной в куче.
free(ptr);     


Автоматически: Сборщик мусора (Garbage Collector) автоматически освобождает память, которая больше не используется.
// В Java нет необходимости освобождать память вручную.     


🚩Примеры

C/C++ (ручное управление памятью):
#include <stdio.h>
#include <stdlib.h>

int main() {
int *arr = (int*)malloc(sizeof(int) * 5); // Выделение памяти
if (arr == NULL) {
// Ошибка выделения памяти
return 1;
}
// Использование массива
for (int i = 0; i < 5; i++) {
arr[i] = i;
}
// Освобождение памяти
free(arr);
return 0;
}


Python (автоматическое управление памятью):
def create_list():
my_list = [i for i in range(5)] # Выделение памяти автоматически
return my_list # Память освобождается автоматически, когда объект больше не используется

my_list = create_list()
print(my_list)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤔1
🤔 Для чего опционал нужен в Swift?

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

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

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

🚩Основные характеристики

🟠Автоматическая генерация документации
JSDoc позволяет автоматически создавать HTML-документацию из аннотированных комментариев в коде.
🟠Поддержка типов и параметров
JSDoc позволяет описывать типы данных параметров и возвращаемых значений функций.
🟠Описание функций, методов и классов
JSDoc используется для документирования всех аспектов кода, включая функции, методы, классы и модули.

/**
* Adds two numbers together.
* @param {number} a - The first number.
* @param {number} b - The second number.
* @returns {number} The sum of the two numbers.
*/
function add(a, b) {
return a + b;
}

/**
* Represents a person.
* @class
*/
class Person {
/**
* Creates a person.
* @param {string} name - The name of the person.
* @param {number} age - The age of the person.
*/
constructor(name, age) {
this.name = name;
this.age = age;
}

/**
* Greets someone.
* @param {string} [greetName='Stranger'] - The name of the person to greet.
* @returns {string} The greeting message.
*/
greet(greetName = 'Stranger') {
return `Hello, ${greetName}! My name is ${this.name}.`;
}
}


🚩Основные теги JSDoc

@param — Описание параметров функции.
@returns — Описание возвращаемого значения функции.
@class — Описание класса.
@constructor — Описание конструктора класса.
@typedef — Описание типа данных.

🚩Плюсы

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

🚩Генерация документации

Для генерации документации с использованием JSDoc требуется установить и использовать инструмент командной строки JSDoc.

1⃣Установка JSDoc
npm install -g jsdoc   


2⃣Генерация документации
jsdoc yourJavaScriptFile.js   


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

Основные способы: принудительное развертывание (!), опциональная привязка (if let), guard let, использование оператора ?? для значений по умолчанию.

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

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

🚩Event Emitter в JavaScript

В JavaScript Event Emitter часто используется с помощью библиотеки events, которая встроена в Node.js. Вот как это работает

1⃣Создание EventEmitter и подписка на события
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();

// Подписка на событие 'event'
eventEmitter.on('event', (message) => {
console.log(`Received event with message: ${message}`);
});


2⃣Инициация события
// Инициация события 'event'
eventEmitter.emit('event', 'Hello, World!');


🚩Event Emitter в браузере

В браузере события также часто обрабатываются с использованием колбэков через API, такие как addEventListener.

1⃣Добавление обработчика события
const button = document.getElementById('myButton');

// Подписка на событие 'click'
button.addEventListener('click', () => {
console.log('Button clicked!');
});


2⃣Инициация события (напрямую из кода)
// Инициация события 'click'
button.click();


🚩Реализация собственного EventEmitter

Можно создать собственный класс EventEmitter, который будет использовать колбэки для обработки событий.
class EventEmitter {
constructor() {
this.events = {};
}

on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
}

emit(event, ...args) {
if (this.events[event]) {
this.events[event].forEach(listener => listener(...args));
}
}

off(event, listener) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(l => l !== listener);
}
}
}

// Использование:
const emitter = new EventEmitter();

// Подписка на событие
emitter.on('message', (msg) => {
console.log(`Message: ${msg}`);
});

// Инициация события
emitter.emit('message', 'Hello, Event Emitter!');


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯42😁1
🤔 Что может быть ключом и значением для Dictionary?

Ключ должен быть типом, реализующим протокол Hashable, а значение может быть любым типом.

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

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

🚩Признаки DDD

🟠Доменная модель
Ubiquitous Language: Общий язык, используемый всей командой.
Доменные объекты: Сущности, значимые объекты, агрегаты, доменные события.

🟠Слои архитектуры
Доменный слой: Содержит модели, агрегаты, репозитории, доменные сервисы.
Слой приложений: Управляет потоками работы и координирует доменные объекты.
Инфраструктурный слой: Реализация репозиториев, доступ к базам данных.
Презентационный слой: Взаимодействие с пользователем.

🟠Репозитории и фабрики
Репозитории: Обеспечивают доступ к агрегатам.
Фабрики: Управляют созданием сложных объектов.

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

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

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

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

🚩Пример с колбеками

function fetchData(callback) {
setTimeout(() => {
callback("Data received");
}, 1000);
}

fetchData((data) => {
console.log(data); // "Data received"
});


🚩Пример с Promises

function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
}

fetchData().then((data) => {
console.log(data); // "Data received"
});


🚩Плюсы

Чистота кода
Promises помогают избежать вложенности колбеков (callback hell), делая код более линейным и читаемым.
Обработка ошибок
Promises обеспечивают единый механизм обработки ошибок с помощью .catch(), что упрощает отладку.
Цепочка вызовов
Promises поддерживают цепочки вызовов (.then()), что упрощает выполнение последовательных асинхронных операций.

🚩Асинхронные функции (async/await)

Современный синтаксис JavaScript включает async/await, который еще больше упрощает работу с асинхронным кодом на основе Promises, делая его похожим на синхронный код.
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
}

async function fetchDataAsync() {
try {
const data = await fetchData();
console.log(data); // "Data received"
} catch (error) {
console.error(error);
}
}

fetchDataAsync();


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

Для многопоточности используются GCD (Grand Central Dispatch), OperationQueue и недавно добавленный Swift Concurrency с ключевыми словами async/await.

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

В Domain-Driven Design (DDD) управление зависимостями важно для создания четко разделенных и легко управляемых компонентов. Это достигается следующими методами:

🚩Методы управления зависимостями в DDD

🟠Инъекция зависимостей
Инъекция зависимостей позволяет передавать зависимости через конструкторы или сеттеры, снижая связанность и упрощая тестирование.
interface UserRepository {
findById(id: string): Promise<User | null>;
}

class UserService {
private userRepository: UserRepository;

constructor(userRepository: UserRepository) {
this.userRepository = userRepository;
}

public async getUserById(id: string): Promise<User | null> {
return await this.userRepository.findById(id);
}
}


🟠Сервисы домена
Сервисы домена содержат бизнес-логику, не принадлежащую конкретным сущностям или значимым объектам, и могут взаимодействовать с несколькими объектами или внешними сервисами.
class PaymentService {
private paymentGateway: PaymentGateway;

constructor(paymentGateway: PaymentGateway) {
this.paymentGateway = paymentGateway;
}

public async processPayment(order: Order): Promise<boolean> {
return await this.paymentGateway.charge(order.totalAmount);
}
}


🟠Анти-коррупционные слои
Анти-коррупционные слои защищают доменную модель от внешних влияний и преобразуют данные в понятные форматы.
class ExternalUserService {
public getUserData(id: string): ExternalUser {
// Получение данных от внешнего сервиса
}
}

class UserService {
private externalUserService: ExternalUserService;

constructor(externalUserService: ExternalUserService) {
this.externalUserService = externalUserService;
}

public getUser(id: string): User {
const externalUser = this.externalUserService.getUserData(id);
return new User(externalUser.id, externalUser.name, externalUser.email);
}
}


🟠Контейнеры зависимостей
Контейнеры управляют созданием и жизненным циклом зависимостей, упрощая конфигурацию и разрешение зависимостей.
import "reflect-metadata";
import { Container, injectable, inject } from "inversify";

@injectable()
class UserRepositoryImpl implements UserRepository {
public async findById(id: string): Promise<User | null> {
// Реализация метода
}
}

@injectable()
class UserService {
private userRepository: UserRepository;

constructor(@inject("UserRepository") userRepository: UserRepository) {
this.userRepository = userRepository;
}

public async getUserById(id: string): Promise<User | null> {
return await this.userRepository.findById(id);
}
}

// Конфигурация контейнера
const container = new Container();
container.bind<UserRepository>("UserRepository").to(UserRepositoryImpl);
container.bind<UserService>(UserService).toSelf();

// Разрешение зависимостей
const userService = container.get<UserService>(UserService);


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
2