Swift | Вопросы собесов
2.13K subscribers
28 photos
957 links
Download Telegram
Forwarded from easyoffer
Осталось всего 14 дней до завершения краудфандинга

Сейчас самое подходящее время подключиться, если вы ждали или откладывали:

Все, кто поддержат проект сейчас, до релиза, получат:
🚀 PRO-доступ на 1 год по цене месячной подписки
Бета-доступ к EasyOffer 2.0 (конец мая)

👉 Поддержать: https://planeta.ru/campaigns/easyoffer
🤔 Что такое retail release?

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

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

В Swift нет множественного наследования классов, но можно использовать множественное наследование через протоколы.

🚩Почему нет множественного наследования классов?

Swift запрещает множественное наследование классов, потому что оно может привести к конфликтам и алмазной проблеме (diamond problem).
Допустим, в языке с поддержкой множественного наследования у нас есть два родительских класса с одинаковым методом:
class A {
public:
void greet() { cout << "Hello from A"; }
};

class B {
public:
void greet() { cout << "Hello from B"; }
};

// C наследуется от A и B
class C : public A, public B {};

C obj;
obj.greet(); // Какой метод вызвать? A или B?


🚩Как обойти ограничение? Используем протоколы!

В Swift можно реализовать множественное наследование через протоколы, поскольку класс может соответствовать нескольким протоколам одновременно.
protocol Flyable {
func fly()
}

protocol Swimmable {
func swim()
}

class Animal {}

class Duck: Animal, Flyable, Swimmable {
func fly() {
print("Утка летит")
}

func swim() {
print("Утка плывёт")
}
}

let duck = Duck()
duck.fly() // Утка летит
duck.swim() // Утка плывёт


🚩Что делать, если нужен код по умолчанию?

Если хочется, чтобы протокол предоставлял реализацию по умолчанию (почти как родительский класс), можно использовать extension:
protocol Walker {
func walk()
}

extension Walker {
func walk() {
print("Иду вперёд")
}
}

class Person: Walker {}

let human = Person()
human.walk() // "Иду вперёд" (метод взят из extension)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Перечислите и расскажи о счётчиках ссылок

Каждый объект имеет счётчик ссылок, отражающий, сколько активных ссылок на него существует:
- retain — увеличивает счётчик.
- release — уменьшает.
- dealloc вызывается, когда счётчик становится 0.
В ARC всё это происходит не вручную, а автоматически. Цель — не допустить утечек памяти и преждевременного освобождения объектов.


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

В Swift переменные (свойства), объявленные в протоколе, должны указывать:

🟠Только для чтения (`get`)
Если свойство объявлено как { get }, класс или структура, реализующая протокол, должна предоставить как минимум геттер
protocol Animal {
var name: String { get } // Только чтение
}

struct Dog: Animal {
let name = "Барсик" // Реализуем только get
}

let dog = Dog()
print(dog.name) // "Барсик"


Можно также использовать вычисляемое свойство:
struct Cat: Animal {
var name: String {
return "Мурзик"
}
}


🟠Для чтения и записи (`get set`)
Если свойство { get set }, класс или структура обязательно должны предоставить и get, и set.
protocol Vehicle {
var speed: Int { get set } // Чтение и запись
}

class Car: Vehicle {
var speed: Int = 100 // Реализуем и get, и set
}

let car = Car()
car.speed = 120 // Можно изменить значение
print(car.speed) // 120


Вычисляемое свойство тоже подойдёт, если оно имеет get и set:
class Bike: Vehicle {
private var internalSpeed = 50

var speed: Int {
get { return internalSpeed }
set { internalSpeed = newValue }
}
}


🟠Статические свойства (`static`)
Если свойство должно быть общим для всех экземпляров (не индивидуальным), то оно объявляется static.
protocol Config {
static var appVersion: String { get }
}

struct AppSettings: Config {
static let appVersion = "1.0.0"
}

print(AppSettings.appVersion) // "1.0.0"


Класс может использовать class var, если свойство можно переопределять в подклассах:
class AppInfo: Config {
class var appVersion: String {
return "2.0.0"
}
}


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

Когда происходит первый доступ к view, или когда вызывается метод loadView(). Тогда UIViewController инициализирует дерево вью


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Forwarded from easyoffer
🎉 Easyoffer 2.0 — самый успешный краудфандинг в истории рунета в категории "Технологии"!

Мы это сделали! За считанные часы после старта, благодаря вашей поддержке, проект не просто стартовал — он взлетел.

💸 Собрано: 2 276 840 рублей

Это не просто цифра — это ваше доверие, ваша вера в идею, и ваша инвестиция в будущее карьеры сотен (а скоро — тысяч) специалистов.

💼 Благодаря этой сумме мы уже:

— Наняли ещё пару разработчиков и аналитиков
— Запустили активный сбор и разметку новых данных
— Ускорили разработку и подняли планку качества

Спасибо каждому, кто поверил в нас на старте! Дальше — только масштабирование и развитие. Мы строим сервис, который станет must-have для всех, кто ищет работу в IT.

👉 Присоединяйтесь сейчас — это только начало.
🔥1
🤔 Что такое Satisfiable?

В контексте Swift термин Satisfiable (удовлетворяемый) относится к тому, может ли конкретный тип соответствовать (удовлетворять) требованиям протокола.

🚩Что значит, что протокол satisfiable?
Протокол считается satisfiable, если его можно реализовать без противоречий. Например, если в протоколе указаны требования, которые могут быть выполнены в классе или структуре.
protocol Animal {
var name: String { get }
func speak()
}

struct Dog: Animal {
var name = "Барсик"

func speak() {
print("Гав-гав")
}
}

let dog = Dog()
dog.speak() // "Гав-гав"


🚩Когда протокол не satisfiable?

Протокол не может быть удовлетворён (то есть, не satisfiable), если он содержит требования, которые невозможно реализовать в конкретном типе.
protocol Impossible {
var value: Self { get } // Self требует, чтобы свойство содержало сам тип
}

struct Example: Impossible {
var value: Example // ОШИБКА: бесконечная рекурсия!
}


🚩Проверка satisfiability в Swift

Если вы видите ошибку Protocol 'X' cannot be satisfied, значит, Swift не может найти способ правильно реализовать все его требования.
Проверьте ассоциированные типы и Self – они должны корректно ссылаться на реализуемый тип.
Проверьте требования протокола – убедитесь, что все свойства и методы могут быть реализованы в классе/структуре.
Попробуйте использовать any Protocol – если Self создаёт проблемы, возможно, нужно использовать any:
   func test(value: any Impossible) { } // Позволяет работать с протоколом без строгого Self


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

Используй do-catch для перехвата throw, try? и try! для безопасного вызова функций, которые могут выбросить ошибку. Также можно логировать через os_log, print, или использовать краш-репортинг-сервисы (Sentry, Firebase Crashlytics).


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

В Swift есть несколько инструментов для работы с многопоточностью и параллельным выполнением кода. Вот основные из них:

🟠GCD (Grand Central Dispatch) – главный инструмент для потоков
GCD – это низкоуровневая технология, позволяющая управлять задачами (тасками) в очередях (DispatchQueue).
DispatchQueue.global(qos: .background).async {
print("Фоновый поток")

DispatchQueue.main.async {
print("Вернулись в главный поток")
}
}


🟠OperationQueue – более удобный API для задач
OperationQueue – это более гибкая и объектно-ориентированная альтернатива GCD.
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 2 // Ограничение на 2 задачи одновременно

queue.addOperation {
print("Операция 1")
}

queue.addOperation {
print("Операция 2")
}


🟠Actors – безопасная работа с потоками в Swift 5.5+
С actor можно работать с потоками без гонок данных, потому что все его свойства защищены от одновременного доступа.
actor Counter {
private var value = 0

func increment() {
value += 1
}

func getValue() -> Int {
return value
}
}

let counter = Counter()

Task {
await counter.increment()
print(await counter.getValue()) // Потокобезопасный доступ
}


🟠Task & Async/Await (Swift 5.5+) – современный подход к асинхронности
С async/await код становится читаемым и удобным.
func fetchData() async -> String {
try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 секунда задержки
return "Данные загружены"
}

Task {
let result = await fetchData()
print(result)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Что такое PRO-подписка на easyoffer 2.0?

easyoffer PRO — это не просто доступ к базе, а полноценный инструмент для получения оффера.

🧠 База вопросов с собеседований

+ Анализ на основе 4,000 собеседований
+ Вероятность встречи каждого вопроса
+ Фильтрация по грейдам, компаниям, типам интервью
+ Примеры ответов: текстовые и видео
+ Готовьтесь к собеседованию в конкретную компанию

🛠 Тренажер "Проработка вопросов"

+ Флеш-карточки + интервальные повторения
+ Персональная система показа карточек в зависимости от ваших ответов
+ Упор на наиболее частые вопросы
+ Фокус на слабые места и быстрый прогресс

🎭 Тренажер "Реальное собеседование"

+ Сценарии на основе реальных интервью
+ Подготовка к конкретным компаниям
+ Итоговая статистика: прошёл/не прошёл

🧩 База задач с собеседований

+ Live-coding и System Design задачи
+ Оценка вероятности встречи задачи
+ Подготовка к задачам по конкретным компаниям

📋 База тестовых заданий

+ Задания из реальных вакансий
+ Фильтрация по технологиям и грейдам
+ Лучшие решения в доступе

📈 Тренды технологий в вакансиях

+ Топ-100 навыков, которые требуют компании
+ Динамика популярности технологий
+ Фильтрация по грейдам

🎁 Специальная цена до релиза:
3200 руб. за целый год

Сейчас PRO на 1 год стоит как будет стоить 1 месяц после релиза. Покупка также открывает доступ к закрытому бета-тестированию.
+ Вы можете активировать подписку в любой момент, например, когда начнете искать работу.

Предзаказ здесь: https://planeta.ru/campaigns/easyoffer

📌 Цена поднимется сразу после запуска.

Если вы хотите перестать угадывать, что спросят на собеседовании, и начать точечно готовиться на основе реальных данных — easyoffer PRO именно для вас.

Экономьте время. Получайте оффер легко.
🤔 Что такое верстка на AutoLayout, а что такое верстка на frame?

- AutoLayout — это система ограничений (constraints), определяющих расположение элементов вне зависимости от размера экрана. Используется при адаптивной, универсальной верстке.
- Frame-верстка — это явное указание координат и размеров каждого элемента. Быстро, но не гибко — плохо масштабируется под разные устройства и ориентации.


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

Перед вызовом layoutIfNeeded() или layoutSubviews() в iOS-приложении, нужно изменить значение констрейнта и вызвать анимацию, если необходимо. Вот основные шаги:

🟠Обновление значения констрейнта
Перед вызовом layoutIfNeeded(), измените свойство констрейнта (например, constant у NSLayoutConstraint).
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!

override func viewDidLoad() {
super.viewDidLoad()

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.changeButtonHeight()
}
}

func changeButtonHeight() {
heightConstraint.constant = 100 // Меняем значение констрейнта
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded() // Перестраиваем макет
}
}
}


🟠Если меняется набор констрейнтов
Если нужно удалить/добавить констрейнты, используйте `activate()` / `deactivate()`.
var expanded = false

@IBOutlet weak var smallHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var largeHeightConstraint: NSLayoutConstraint!

func toggleHeight() {
expanded.toggle()

if expanded {
NSLayoutConstraint.deactivate([smallHeightConstraint])
NSLayoutConstraint.activate([largeHeightConstraint])
} else {
NSLayoutConstraint.deactivate([largeHeightConstraint])
NSLayoutConstraint.activate([smallHeightConstraint])
}

UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}


🟠Если работа идёт в `viewDidLoad()`
Во viewDidLoad() элементы ещё не отрисованы, поэтому layoutIfNeeded() не сработает. Используйте viewDidAppear() или вызовите layoutIfNeeded() после view.layoutIfNeeded().
override func viewDidLoad() {
super.viewDidLoad()
heightConstraint.constant = 100
view.layoutIfNeeded() // НЕ обновит макет, потому что он ещё не загружен
}


Решение
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

heightConstraint.constant = 100
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}


Разница между layoutIfNeeded() и setNeedsLayout()
heightConstraint.constant = 100
view.setNeedsLayout() // Обновление произойдет на следующем цикле рендера


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Как загрузить изображение из интернета и отобразить его в ImageView — все это должно происходить после нажатия кнопки?

Процесс выглядит так:
1. Пользователь нажимает кнопку.
2. Запускается сетевой запрос по URL изображения.
3. После завершения загрузки изображение преобразуется в нужный формат.
4. Полученное изображение устанавливается в элемент ImageView.
Важно, чтобы сетевой запрос выполнялся в фоновом потоке, а обновление интерфейса — в основном UI-потоке.


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

В Swift существует несколько видов диспетчеризации, которые определяют, как и когда вызываются методы или функции. Основные виды диспетчеризации включают статическую диспетчеризацию (static dispatch), диспетчеризацию по таблице виртуальных функций (vtable dispatch), диспетчеризацию по свидетелю (witness table dispatch) и динамическую диспетчеризацию (dynamic dispatch). Рассмотрим их подробнее:

🟠Статическая диспетчеризация (Static Dispatch)
Вызов функции или метода определяется на этапе компиляции. Используется для функций и методов, которые не переопределяются в подклассах или не являются динамическими. Для структур, перечислений и final классов.
     struct MyStruct {
func printMessage() {
print("Hello from MyStruct")
}
}

let instance = MyStruct()
instance.printMessage() // Вызов определяется на этапе компиляции


🟠Диспетчеризация по таблице виртуальных функций (Vtable Dispatch)
Используется для вызова методов класса, которые могут быть переопределены в подклассах. Виртуальная таблица (vtable) используется для определения, какой метод вызывать. Для классов и их подклассов.
     class BaseClass {
func printMessage() {
print("Hello from BaseClass")
}
}

class SubClass: BaseClass {
override func printMessage() {
print("Hello from SubClass")
}
}

let instance: BaseClass = SubClass()
instance.printMessage() // Вызов определяется в runtime с использованием vtable


🟠Диспетчеризация по свидетелю (Witness Table Dispatch)
Используется для вызова методов протоколов, реализованных типами. Таблица свидетелей (witness table) используется для определения, какой метод вызывать. Для типов, соответствующих протоколам.
     protocol MyProtocol {
func printMessage()
}

struct MyStruct: MyProtocol {
func printMessage() {
print("Hello from MyStruct")
}
}

let instance: MyProtocol = MyStruct()
instance.printMessage() // Вызов определяется в runtime с использованием witness table


🟠Динамическая диспетчеризация (Dynamic Dispatch)
Используется для вызова методов, отмеченных как dynamic или методов Objective-C. Метод определяется в runtime с использованием Objective-C runtime. Для методов, которые должны быть динамически разрешены в runtime, обычно для взаимодействия с Objective-C.
     import Foundation

class MyClass: NSObject {
@objc dynamic func printMessage() {
print("Hello from MyClass")
}
}

let instance = MyClass()
instance.printMessage() // Вызов определяется в runtime с использованием Objective-C runtime


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

UserDefaults — это хранилище для сохранения простых данных (строки, числа, массивы). Но если нужно сохранить сложные объекты, их сначала кодируют в `Data` (Codable), а затем сохраняют.

🟠Сохранение и загрузка простых данных
Для примитивных типов (строки, числа, массивы, словари) UserDefaults работает без кодирования:
let defaults = UserDefaults.standard

// Сохранение
defaults.set("Иван", forKey: "username")
defaults.set(25, forKey: "age")

// Чтение
let name = defaults.string(forKey: "username") ?? "Нет имени"
let age = defaults.integer(forKey: "age")

print(name, age) // Иван 25


🟠Сохранение сложных объектов (Codable)
Если нужно сохранить свой объект, сначала его нужно закодировать в Data.
struct User: Codable {
let name: String
let age: Int
}


Сохранение в UserDefaults
let user = User(name: "Иван", age: 25)
let defaults = UserDefaults.standard

if let encoded = try? JSONEncoder().encode(user) {
defaults.set(encoded, forKey: "user")
}


Загрузка из UserDefaults
if let savedData = defaults.data(forKey: "user"),
let savedUser = try? JSONDecoder().decode(User.self, from: savedData) {
print(savedUser.name, savedUser.age) // Иван 25
}


🟠Удаление данных из `UserDefaults`
Чтобы удалить ключ:
defaults.removeObject(forKey: "user")


🟠Сохранение массива объектов
Можно сохранить массив объектов, просто закодировав его:
let users = [
User(name: "Иван", age: 25),
User(name: "Анна", age: 30)
]

if let encoded = try? JSONEncoder().encode(users) {
defaults.set(encoded, forKey: "users")
}

// Читаем массив обратно
if let savedData = defaults.data(forKey: "users"),
let savedUsers = try? JSONDecoder().decode([User].self, from: savedData) {
print(savedUsers) // [{name: Иван, age: 25}, {name: Анна, age: 30}]
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Forwarded from easyoffer
📅 Осталось 7 дней до конца краудфандинга

Мы на финишной прямой!

Если ты планировал присоединиться, но ещё не успел, сейчас идеальный момент.

Вознаграждения за поддержку:

🚀 PRO подписка к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу.
Приглашение на закрытое бета-тестирование

👉 Поддержать easyoffer 2.0

Не откладывай на последний момент

📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ
🤔 В чем различие очередей serial и concurrent?

- Serial (последовательные): выполняют задачи поочерёдно, одна за другой.
- Concurrent (параллельные): позволяют выполнять несколько задач одновременно, обеспечивая более высокую производительность.


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

В Swift (и во многих других языках программирования) по умолчанию числовой литерал с плавающей запятой интерпретируется как `Double`, а не Float.

🚩Основные причины:

🟠Бóльшая точность
Double имеет 64 бита, а Float32 бита. Это значит, что Double может хранить более точные значения, что особенно важно при математических вычислениях.

🟠Совместимость со стандартными API
Большинство API и стандартных библиотек Swift (например, sin(), cos(), pow()) работают именно с Double.
Например:
   let x = 3.14 // По умолчанию это Double
let y = sin(x) // sin() принимает Double


🟠Производительность на современных процессорах
На современных 64-битных процессорах операции с Double выполняются так же быстро или даже быстрее, чем с Float, из-за оптимизаций в аппаратном обеспечении.

🟠Меньше неожиданных ошибок округления
Float может округлять числа с потерей точности, что может привести к неожиданным результатам.
Пример ошибки округления в Float:
   let a: Float = 0.1 + 0.2
print(a == 0.3) // false 😱


🚩Как сделать `Float` вручную?
Если всё же нужен Float, надо указать это явно:
let number: Float = 3.14


или
let number = 3.14 as Float


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

Стек используется для хранения локальных переменных и вызовов функций — он быстрый и автоматически управляется. Куча используется для хранения объектов с динамическим временем жизни, управление памятью здесь происходит через ARC или GC.


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