Swift | Вопросы собесов
2.13K subscribers
28 photos
955 links
Download Telegram
🤔 Что такое autoclosure?

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

🤔Зачем нужен @autoclosure?

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

🚩Пример без

Допустим, у нас есть функция, которая принимает замыкание
func logMessage(_ message: () -> String) {
print("Лог: \(message())")
}

// Вызываем функцию, передавая замыкание
logMessage { "Сообщение: \(2 + 2)" }

🚩Пример с

Теперь используем `@autoc чтобы сделать вызов функции проще
func logMessage(_ message: @autoclosure () -> String) {
print("Лог: \(message())")
}

// Теперь аргумент можно передавать без {}
logMessage("Сообщение: \(2 + 2)")

🚩Где это полезно?

🟠`assert` и precondition
Стандартные функции Swift используют @autoclosure, чтобы избежать вычисления аргументов, если проверка не нужна:
assert(2 + 2 == 4, "Ошибка: 2 + 2 не равно 4!")

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

🤔Зачем нужен `@autoclosure`?

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

🤔Зачем нужен `@autoclosure`?

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

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

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

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

enum (перечисления) относится к типам значений (value types). Это означает, что при передаче перечисления функции или при его присвоении переменной создается новая копия этого перечисления. Это работает аналогично другим типам значений, таким как struct и базовые типы данных (Int, String, Double и т.д.).

🚩Особенности

🟠Копирование при присвоении
Когда переменной перечисления присваивается значение другой переменной перечисления, создается независимая копия этого значения.

🟠Безопасность типов
enum поддерживает безопасность типов, что позволяет создавать код, легкий для понимания и поддержки.

🟠Связанные значения
enum может хранить связанные значения различных типов.
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}


🟠Методы
enum может иметь методы, которые предоставляют функциональность, связанную с перечислением.
enum Planet {
case earth, mars, venus

func isHabitable() -> Bool {
switch self {
case .earth:
return true
default:
return false
}
}
}


Пример
enum TrafficLight {
case red, yellow, green
}

var light = TrafficLight.red
var lightCopy = light
lightCopy = .green

print(light) // Выводит "red"
print(lightCopy) // Выводит "green"


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
😁31👍1
🤔 Что известно про Firebase Remote Config?

Это инструмент для управления поведением приложения и его интерфейсом без выпуска обновлений. Разработчики могут изменять параметры в реальном времени, например, активировать функции или изменять дизайн. Это особенно полезно для A/B тестирования или настройки функций для разных групп пользователей. Remote Config интегрируется с другими инструментами Firebase, такими как Analytics.

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

Половина массива — это подмножество элементов массива, которое составляет примерно 50% его длины. В зависимости от контекста, это может быть:
Первая половина – элементы от начала массива до середины.
Вторая половина – элементы от середины до конца массива.
Любая подгруппа, близкая к 50% – например, при нечетном количестве элементов можно взять либо на один элемент больше, либо меньше.

let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let middleIndex = array.count / 2 // Делим пополам

let firstHalf = Array(array[..<middleIndex]) // Первая половина
let secondHalf = Array(array[middleIndex...]) // Вторая половина

print(firstHalf) // [1, 2, 3, 4, 5]
print(secondHalf) // [6, 7, 8, 9, 10]


🚩Зачем это нужно?

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

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2
Forwarded from easyoffer
💡 В EasyOffer 2.0 появится фильтрация вопросов по грейдам и типам интервью!

📊 Например, вот вероятности ТОП-30 вопросов, которые задают на HR-скрининге Python-разработчику уровня Middle/Senior. Данные основаны на 53 реальных интервью.

97% Какие у тебя зарплатные ожидания
73% Какие у тебя есть вопросы
44% Какие критерии при выборе будущей работы
41% Расскажи о себе
38% Почему ищешь работу
35% Расскажи про свой опыт
35% Расскажи про проект на предыдущей работе
32% Почему уволился с предыдущей работы
29% Где территориально сейчас живешь/находишься
23% Есть ли другие предложения по работе
17% Есть ли военный билет
17% Почему хочешь сменить работу
17% Как проводишь свободное время
17% Расскажи про задачи на предыдущей работе
17% Сколько коммерческого опыта работы с Python
17% С какими БД работал
14% Находишься ли в активном поиске работы
14% С каким стеком работаешь
14% Почему решил откликнуться на нашу вакансию
14% Какой текущий статус поиска работы
11% Почему решил стать программистом
11% С какими фреймворками работал
11% Какую зарплату получал на предыдущей работе
11% Работаешь ли в настоящий момент
11% На какой грейд себя оцениваешь
11% Как быстро можешь приступить к работе после получения офера
11% Расскажи про свои pet-проекты
8% Какие знаешь типы данных в Python
8% Что такое декоратор в Python
8% Что ищешь на новой работе

🚀 Скоро стартует краудфандинговая кампания, которая поможет ускорить разработку EasyOffer 2.0.
Первые спонсоры получат уникальные лимитированные награды!

📢 Если вам это интересно, подписывайтесь на канал 👉 этот телеграм канал
🤔 Почему приложения под Swift массивные?

Приложения на Swift часто массивные из-за включения всех зависимостей и библиотек в конечный бинарный файл. Статическая компиляция библиотек, а также особенности рантайма языка увеличивают размер приложений. Использование фреймворков, таких как SwiftUI, также вносит вклад в размер приложения. Оптимизация ресурсов и применение динамических библиотек могут снизить объём.

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

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

🟠Что значит "функция типа T"?
Функция в Swift — это тоже тип данных.
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}


Тип этой функции
(Int, Int) -> Int


🟠Пример: оператор `+` для функций
Допустим, у нас есть две функции, и мы хотим, чтобы оператор + создавал новую функцию, объединяя их поведение.
import Foundation

// Функция типа (Int) -> Int
func double(_ x: Int) -> Int {
return x * 2
}

func increment(_ x: Int) -> Int {
return x + 1
}

// Перегружаем оператор + для функций (Int) -> Int
func + (lhs: @escaping (Int) -> Int, rhs: @escaping (Int) -> Int) -> (Int) -> Int {
return { x in rhs(lhs(x)) } // Сначала вызываем первую, затем вторую
}

// Используем оператор
let combinedFunction = double + increment

print(combinedFunction(3)) // (3 * 2) + 1 = 7


🟠Пример: оператор `*` для функций
Можно сделать оператор *, который применяет функцию несколько раз.
// Перегружаем оператор * для дублирования применения функции
func * (lhs: @escaping (Int) -> Int, rhs: Int) -> (Int) -> Int {
return { x in
var result = x
for _ in 0..<rhs {
result = lhs(result)
}
return result
}
}

// Используем оператор
let tripleDouble = double * 3

print(tripleDouble(2)) // (2 * 2) * 2 * 2 = 16


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

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


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какие ситуации могут быть с user antaraction enabled false, когда vue не может обработать тач?

Если isUserInteractionEnabled = false в iOS-приложении (например, в UIView), это может повлиять на обработку тач-жестов и событий. Если ваш фронтенд на Vue.js работает внутри WebView в iOS-приложении, то Vue может не получать события касаний (touch и click).

🚩Почему это может происходить?

🟠`isUserInteractionEnabled = false` на WebView или родительском UIView
Если WebView (WKWebView или UIWebView) или его родительский UIView имеет isUserInteractionEnabled = false, то система не будет передавать события в WebView.
Решение: Убедитесь, что webView.isUserInteractionEnabled = true.

🟠Перекрывающий UIView с `isUserInteractionEnabled = false`
Если другой UIView (например, UIView-модальное окно или слой затемнения) перекрывает WebView, то iOS не передает события в нижележащие элементы. Даже если у этого UIView стоит isUserInteractionEnabled = false, он все равно блокирует тапы.
Решение: Убедитесь, что нет невидимых вьюх, блокирующих касания.

🟠WebView находится в UIScrollView с отключенным взаимодействием
Если WKWebView вложен в UIScrollView, у которого isUserInteractionEnabled = false, то жесты могут не передаваться в WebView.
Решение: Проверьте настройки UIScrollView, в который встроен WebView.

🟠Проблема с `gestureRecognizers`
Если в UIView или WKWebView добавлены кастомные UIGestureRecognizer, они могут перехватывать события, мешая Vue.
Решение: Отключите ненужные gestureRecognizers.

🟠JS блокирует события (например, `pointer-events: none`)
В Vue.js или в CSS может стоять pointer-events: none, что делает элементы некликабельными.
Решение: Проверьте стили в DevTools.

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

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
🤔 Почему Apple предпочитает использовать value type по умолчанию?

Apple предпочитает value types (структуры struct) по умолчанию в Swift по нескольким причинам

🟠Безопасность многопоточного кода
struct копируется при передаче, а не передается по ссылке, как class.
Это снижает вероятность гонки данных (data race), когда один поток изменяет объект, а другой читает его одновременно.
В многопоточной среде это делает код более безопасным.
struct Point {
var x: Int
var y: Int
}

var p1 = Point(x: 1, y: 2)
var p2 = p1 // p2 - это копия, изменения в p2 не затронут p1

p2.x = 10

print(p1.x) // 1
print(p2.x) // 10


🟠Производительность
struct хранятся в стеке, а не в куче, что делает их создание и удаление быстрее.
Куча (heap) требует управления памятью (ARC – Automatic Reference Counting), а struct — нет.
class MyClass { var value = 0 }  // В куче (heap), управляется ARC
struct MyStruct { var value = 0 } // В стеке (stack), копируется при передаче


🟠Предсказуемость и неизменяемость
struct ведут себя как примитивные типы (Int, Double), что делает код предсказуемым.
Их изменение происходит локально, без неожиданных эффектов в других частях программы.
class Car {
var speed: Int
init(speed: Int) { self.speed = speed }
}

var car1 = Car(speed: 60)
var car2 = car1 // car2 - это ссылка на тот же объект

car2.speed = 100 // Изменение затрагивает car1!

print(car1.speed) // 100 (хотя мы меняли car2!)


🟠Использование в стандартной библиотеке
Swift изначально построен на struct:
Int, Double, Bool, Array, Dictionary, String — это структуры.
Это делает язык более безопасным и производительным.
var arr1 = [1, 2, 3]
var arr2 = arr1 // Копия массива, а не ссылка!

arr2.append(4)

print(arr1) // [1, 2, 3] (не изменился!)
print(arr2) // [1, 2, 3, 4] (новый массив)


🚩Когда использовать `class`?

Хотя struct — предпочтительный выбор, class нужен, когда:
Нужна ссылочная семантика (например, объект должен изменяться в разных местах кода).
Есть сложные иерархии наследования.
Требуется работа с Objective-C (NSObject).

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

Среди базовых протоколов Swift: Equatable (сравнение объектов), Comparable (сравнение порядка), Hashable (хэширование объектов), Codable (кодирование и декодирование) и Identifiable (идентификация объектов). Эти протоколы часто используются для работы с коллекциями и данными.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Расскажи про механизм отмены в operatsion

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

🚩Как работает отмена `Operation`?

Вызывается cancel() – операция помечается как отмененная.
Флаг isCancelled становится true, но операция продолжает выполняться, если не проверяет этот флаг.
Операция должна самостоятельно проверять isCancelled и прерываться.
class MyOperation: Operation {
override func main() {
for i in 1...10 {
if isCancelled { return } // Проверяем, отменена ли операция
print("Выполняется шаг \(i)")
sleep(1) // Симуляция работы
}
}
}

let queue = OperationQueue()
let operation = MyOperation()

queue.addOperation(operation)

DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
operation.cancel() // Отменяем через 3 секунды
}


🚩Отмена асинхронных операций

Если операция асинхронная (isAsynchronous = true), просто проверять isCancelled недостаточно. Надо корректно управлять состояниями (isExecuting, isFinished).
class AsyncOperation: Operation {
private var _executing = false
private var _finished = false

override var isAsynchronous: Bool { true }

override var isExecuting: Bool {
get { return _executing }
set {
willChangeValue(for: \.isExecuting)
_executing = newValue
didChangeValue(for: \.isExecuting)
}
}

override var isFinished: Bool {
get { return _finished }
set {
willChangeValue(for: \.isFinished)
_finished = newValue
didChangeValue(for: \.isFinished)
}
}

override func start() {
if isCancelled {
isFinished = true
return
}

isExecuting = true
executeTask()
}

private func executeTask() {
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
if self.isCancelled {
self.complete()
return
}
print("Асинхронная операция завершена")
self.complete()
}
}

private func complete() {
isExecuting = false
isFinished = true
}
}

let queue = OperationQueue()
let asyncOp = AsyncOperation()
queue.addOperation(asyncOp)

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
asyncOp.cancel() // Отменяем через 1 секунду
}


🚩Отмена зависимых операций

Если у вас есть зависимости между операциями, отмена одной может автоматически отменить все последующие:
let op1 = MyOperation()
let op2 = MyOperation()
op2.addDependency(op1)

let queue = OperationQueue()
queue.addOperations([op1, op2], waitUntilFinished: false)

// Отменяем первую операцию, вторая тоже не выполнится
op1.cancel()


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

Команда PO в LLDB (print object) вызывает метод объекта, чтобы отобразить его состояние. Если метод содержит побочные эффекты или ошибки, это может привести к изменению состояния объекта во время отладки. Это особенно опасно при отладке сложных объектов с логикой.

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

Принцип инверсии зависимостей (Dependency Inversion Principle, DIP) гласит:
Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций.
Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

🚩Плохой пример (Нарушение DIP)

class MySQLDatabase {
func fetchData() -> String {
return "Данные из MySQL"
}
}

class DataManager {
let database = MySQLDatabase() // Прямая зависимость от MySQL

func getData() -> String {
return database.fetchData()
}
}


🚩Хороший пример (Используем DIP)

Вводим абстракцию (Протокол)
protocol Database {
func fetchData() -> String
}


Реализуем конкретные базы данных
class MySQLDatabase: Database {
func fetchData() -> String {
return "Данные из MySQL"
}
}

class PostgreSQLDatabase: Database {
func fetchData() -> String {
return "Данные из PostgreSQL"
}
}


Используем абстракцию в DataManager
class DataManager {
private let database: Database // Зависимость от абстракции

init(database: Database) {
self.database = database
}

func getData() -> String {
return database.fetchData()
}
}


Использование
let mySQLDataManager = DataManager(database: MySQLDatabase())
print(mySQLDataManager.getData()) // "Данные из MySQL"

let postgreSQLDataManager = DataManager(database: PostgreSQLDatabase())
print(postgreSQLDataManager.getData()) // "Данные из PostgreSQL"


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

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


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
😁11👀101🤔1🤯1
🤔 Что происходит с классом при компиляции?

При компиляции в Swift класс проходит несколько стадий обработки:
Анализ синтаксиса и семантики – компилятор проверяет код на ошибки.
Генерация промежуточного представления (IR) – создаётся код на уровне LLVM IR.
Оптимизация – Swift применяет различные оптимизации, например, inlining, dead code elimination и другие.
Генерация машинного кода – итоговый код превращается в исполняемый машинный код, специфичный для платформы.

🚩Что конкретно происходит с классом?

В отличие от структур, классы в Swift являются ссылочными типами и хранятся в куче (heap). Это означает, что:
- При создании объекта выделяется память в куче.
- Swift автоматически использует ARC (Automatic Reference Counting) для управления памятью.
- Методы класса могут вызываться через виртуальную таблицу (vtable), если класс использует динамическую диспетчеризацию.

🚩Важные моменты

- Если класс final, компилятор может оптимизировать вызовы методов, убрав динамическую диспетчеризацию.
- Наследование делает вызовы методов менее предсказуемыми (они идут через vtable).
- В отличие от структур, классы не копируются при передаче в функцию, а передаётся ссылка.

class Animal {
var name: String

init(name: String) {
self.name = name
}

func speak() {
print("Some sound")
}
}

final class Dog: Animal {
override func speak() {
print("Woof!")
}
}

let myDog = Dog(name: "Buddy")
myDog.speak()


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

Это структура данных, которая хранит пары ключ-значение. Его стоит использовать, если:
- Требуется быстрый доступ по ключу (O(1) для поиска)
- Неважен порядок элементов
- Ключи уникальны (словарь не допускает дубликатов ключей)
- Нужно легко изменять данные (добавление/удаление за O(1))


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

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

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

🟠Ссылочный тип
Когда вы присваиваете класс другой переменной, копируется не сам объект, а ссылка на него. Изменения, сделанные через одну ссылку, затронут и другие.

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

🟠Automatic Reference Counting (ARC)
Swift использует ARC для управления памятью. Объект удаляется из памяти, когда на него больше нет ссылок.

🟠Наследование
В отличие от структур, классы могут наследовать свойства и методы от других классов. Поддерживают переопределение методов (override).

🟠Идентичность объектов
Два объекта класса можно сравнивать по ссылке (===), а не только по значению (==).

class Animal {
var name: String

init(name: String) {
self.name = name
}

func speak() {
print("Some sound")
}
}

class Dog: Animal {
override func speak() {
print("Woof!")
}
}

let dog1 = Dog(name: "Buddy")
let dog2 = dog1 // Копируется ссылка, а не объект

dog2.name = "Charlie"

print(dog1.name) // "Charlie", так как dog1 и dog2 указывают на один объект


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