Swift | Вопросы собесов
2.13K subscribers
28 photos
952 links
Download Telegram
🤔 Какие есть два типа инициализаторов?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
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
🤔 Как интерфейс связывается с конкретной реализацией?

Связывание интерфейсов с конкретными реализациями осуществляется через инъекцию зависимостей (Dependency Injection), фабрики (Factories) и контейнеры зависимостей (Dependency Injection Containers). Эти методы абстрагируют зависимости и упрощают замену реализаций.

🚩Методы

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

class UserRepositoryImpl implements UserRepository {
public async findById(id: string): Promise<User | null> {
return { id, name: "John Doe" };
}
}

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);
}
}

const userRepository = new UserRepositoryImpl();
const userService = new UserService(userRepository);


🟠Фабрики
Фабрики создают объекты, инкапсулируя логику создания и облегчая управление.
interface UserRepository {
findById(id: string): Promise<User | null>;
}

class UserRepositoryImpl implements UserRepository {
public async findById(id: string): Promise<User | null> {
return { id, name: "John Doe" };
}
}

class UserRepositoryFactory {
static create(): UserRepository {
return new UserRepositoryImpl();
}
}

const userRepository = UserRepositoryFactory.create();
const userService = new UserService(userRepository);


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

interface UserRepository {
findById(id: string): Promise<User | null>;
}

@injectable()
class UserRepositoryImpl implements UserRepository {
public async findById(id: string): Promise<User | null> {
return { id, name: "John Doe" };
}
}

@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
🤔1
🤔 Что такое Retain Cycle?

Retain Cycle — это ситуация, когда два объекта удерживают друг друга через сильные ссылки, что приводит к утечке памяти. Для предотвращения используют слабые (weak) или неявно развернутые (unowned) ссылки.

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

Singletone нарушает несколько принципов хорошего проектирования кода, особенно из набора принципов SOLID.

🚩Нарушение Принципа

🟠Единственной Ответственности (Single Responsibility Principle, SRP)
Класс должен иметь только одну причину для изменения. Singletone выполняет две задачи: управляет своим состоянием и контролирует создание своего единственного экземпляра. Это смешивание обязанностей делает класс сложнее и приводит к ситуации, когда изменение в одной из обязанностей может повлиять на другую.
class Singleton:
_instance = None

def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance

def some_business_logic(self):
pass

# Здесь Singleton отвечает за управление состоянием и контролем создания экземпляра


🟠Открытости/Закрытости (Open/Closed Principle, OCP)
Классы должны быть открыты для расширения, но закрыты для модификации. Singletone трудно расширять без модификации его кода. Для изменения логики создания экземпляра или поведения необходимо изменять сам класс, что нарушает OCP.

🟠Инверсии Зависимостей (Dependency Inversion Principle, DIP)
Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба типа модулей должны зависеть от абстракций. Singletone нарушает DIP, так как привязывает код к конкретной реализации через глобальный доступ к своему экземпляру. Это делает тестирование и замену реализации сложными, поскольку зависимость жестко закодирована.
class DatabaseConnection:
_instance = None

def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(DatabaseConnection, cls).__new__(cls, *args, **kwargs)
return cls._instance

# Любой код, использующий DatabaseConnection, теперь жестко привязан к этой реализации


🚩Проблемы с тестированием
Может создавать скрытые зависимости: Singletone часто используют глобальные состояния, которые могут усложнить тестирование. Сложность при мокировании: Из-за глобального доступа к синглтону сложно подменить его поведение в тестах.

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