Swift | Вопросы собесов
2.13K subscribers
28 photos
949 links
Download Telegram
🤔 Почему приложения массивные?

Приложения на 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
🤔 Как устроен responder chain?

Responder chain — это цепочка объектов, через которую передаются события пользовательского интерфейса до тех пор, пока они не будут обработаны. Она начинается с текущего объекта и продолжается к его родителям (например, от UIView к UIViewController).

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