Swift | Вопросы собесов
2.22K subscribers
30 photos
962 links
Download Telegram
🤔 Чем отличается композиция от наследования?

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

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

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

🤔 Основные типы данных

🟠Примитивные типы данных
Представляют целые числа. Int, UIn
       let age: Int = 25


Представляют дробные числа. Float, Double
       let pi: Double = 3.14159


Представляют логические значения true или false. Bool
       let isActive: Bool = true


Представляют отдельные символы. Character
       let letter: Character = "A"


🟠Составные типы данных (Composite data types)
Представляют последовательности символов. String
       let greeting: String = "Hello, World!"


Представляют упорядоченные коллекции элементов одного типа. Array<T>
       let numbers: [Int] = [1, 2, 3, 4, 5]


Представляют коллекции пар ключ-значение. Dictionary<Key, Value>
       let user: [String: String] = ["name": "Alice", "age": "30"]


Представляют коллекции уникальных элементов. Set<T>
       let uniqueNumbers: Set<Int> = [1, 2, 3, 4, 5]


🟠Пользовательские типы данных (User-defined data types)
Представляют тип данных с набором связанных значений. enum
       enum CompassPoint {
case north
case south
case east
case west
}


Представляют группы связанных значений. struct
       struct Person {
var name: String
var age: Int
}
let person = Person(name: "Alice", age: 30)


Представляют объекты с состоянием и поведением. class
       class Car {
var model: String
var year: Int

init(model: String, year: Int) {
self.model = model
self.year = year
}
}
let car = Car(model: "Tesla", year: 2021)


🟠Специальные типы данных
Представляют группы нескольких значений различных типов. (Type1, Type2, ...)
       let coordinates: (Int, Int) = (10, 20)


Представляют значение, которое может быть либо некоторым значением, либо nil. Optional<T>
       var optionalName: String? = "Alice"


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

Класс user представляет собой объект с полями и методами для описания функциональности. Класс data (или его аналог) чаще всего содержит только данные и минимум логики, используется для передачи информации между слоями приложения. В Swift структуры часто применяются вместо data-классов, так как они работают как типы значений. Класс user может иметь сложную логику, тогда как data сосредоточен на представлении информации.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔3
🤔 Что такое 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