uz
Feedback
Swift | Вопросы собесов

Swift | Вопросы собесов

Kanalga Telegram’da o‘tish

Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv

Ko'proq ko'rsatish
2 196
Obunachilar
+124 soatlar
-17 kunlar
-1330 kunlar
Postlar arxiv
🤔 Что такое мьютекс (mutex)? Мьютекс (от англ. "mutex" - mutual exclusion, взаимное исключение) — это механизм синхронизации, используемый в многопоточном программировании для предотвращения одновременного доступа нескольких потоков к общим ресурсам, таким как переменные, структуры данных или файлы. Он помогает избежать состояния гонки (race condition), когда результат выполнения программы зависит от неопределённого порядка доступа потоков к ресурсу. 🚩Основные концепции мьютекса 🟠Взаимное исключение Мьютекс обеспечивает доступ к общему ресурсу только одному потоку в каждый момент времени. Когда один поток захватывает мьютекс, другие потоки должны ждать, пока мьютекс не будет освобождён. 🟠Захват и освобождение Поток захватывает мьютекс перед доступом к общему ресурсу и освобождает его после завершения работы с этим ресурсом. Если мьютекс уже захвачен другим потоком, текущий поток будет блокирован до тех пор, пока мьютекс не будет освобождён. 🚩Пример использования мьютекса в Swift
import Foundation

class SafeCounter {
    private var value = 0
    private let lock = NSLock()

    func increment() {
        lock.lock()        // Захват мьютекса
        value += 1
        lock.unlock()      // Освобождение мьютекса
    }

    func getValue() -> Int {
        lock.lock()        // Захват мьютекса
        let currentValue = value
        lock.unlock()      // Освобождение мьютекса
        return currentValue
    }
}

let counter = SafeCounter()
DispatchQueue.global().async {
    for _ in 0..<1000 {
        counter.increment()
    }
}

DispatchQueue.global().async {
    for _ in 0..<1000 {
        counter.increment()
    }
}

// Подождём немного, чтобы дать потокам закончить работу
Thread.sleep(forTimeInterval: 1)
print("Final counter value: \(counter.getValue())")
🚩Плюсы и минусы Безопасность данных Мьютексы защищают общие ресурсы от одновременного доступа, предотвращая повреждение данных. ➕Предсказуемость Код становится более предсказуемым и стабильным, так как исключаются состояния гонки. ➖Мёртвые блокировки (Deadlocks) Если мьютексы захватываются в неправильном порядке, это может привести к ситуации, когда два или более потока блокируют друг друга, ожидая освобождения мьютексов. ➖Производительность Чрезмерное использование мьютексов может привести к снижению производительности из-за увеличения времени ожидания потоков. Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое Quality of Service? Quality of Service (QoS) — это система приоритетов, определяющая, насколько срочно и важно выполнить задачу. От этого зависит, сколько ресурсов система выделит. Например, для UI используется самый высокий уровень (user-interactive), а для фоновых задач — низкий (background). Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Чем отличается garbage collector и подсчет ссылок? Garbage Collector (GC) и Automatic Reference Counting (ARC) – это два разных подхода к управлению памятью в программировании. Они решают одну задачу: автоматическое освобождение неиспользуемой памяти, но делают это по-разному. 🚩Garbage Collector (GC) Java, Kotlin, C#, Python, JavaScript - GC периодически просматривает всю память приложения и ищет объекты, на которые больше нет ссылок. - Когда такие объекты находятся, они удаляются, а память освобождается. - Это автоматический процесс, который запускается по мере необходимости. 🚩Подсчет ссылок (ARC - Automatic Reference Counting) Где используется: Swift, Objective-C - Каждый объект имеет счетчик ссылок (reference count). - Когда переменная создает ссылку на объект, счетчик увеличивается. - Когда переменная перестает ссылаться на объект, счетчик уменьшается. - Когда счетчик достигает нуля, объект удаляется из памяти сразу же.
class Person {
    var pet: Pet?
}

class Pet {
    var owner: Person?
}

let person = Person()
let pet = Pet()

person.pet = pet
pet.owner = person // Теперь оба объекта держат друг друга, и ARC их не удалит
Решение – использовать weak:
class Pet {
    weak var owner: Person? // Теперь утечки памяти не будет
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что под капотом стэка? Это абстрактная структура данных, работающая по принципу LIFO (Last In, First Out), что означает "последний пришёл — первый вышел". Это значит, что последний добавленный элемент будет первым при извлечении из стека. Под капотом реализации стека могут быть разные, и они зависят от конкретного языка программирования и задач, которые необходимо решить. 🟠Массивы Один из самых распространённых способов реализации стека — это использование массива. В такой реализации элементы стека хранятся в массиве, и индекс последнего элемента (вершина стека) отслеживается отдельной переменной.
struct Stack<Element> {
    private var storage: [Element] = []

    mutating func push(_ element: Element) {
        storage.append(element)
    }

    mutating func pop() -> Element? {
        return storage.popLast()
    }

    func peek() -> Element? {
        return storage.last
    }

    var isEmpty: Bool {
        return storage.isEmpty
    }
}
🟠Связные списки Стек можно реализовать с использованием связных списков, где каждый элемент списка содержит данные и ссылку на следующий элемент в стеке. Вершина стека в такой реализации — это начало связного списка.
class Node<Element> {
    var value: Element
    var next: Node?

    init(value: Element) {
        self.value = value
    }
}

struct Stack<Element> {
    private var head: Node<Element>?

    mutating func push(_ element: Element) {
        let node = Node(value: element)
        node.next = head
        head = node
    }

    mutating func pop() -> Element? {
        let node = head
        head = head?.next
        return node?.value
    }

    func peek() -> Element? {
        return head?.value
    }

    var isEmpty: Bool {
        return head == nil
    }
}
🟠Стек вызовов Это системный стек, который используется во время выполнения программы для хранения информации о вызовах функций/методов. Он хранит адреса возврата, параметры функций, локальные переменные и другие данные, необходимые для управления вызовами функций и их возврата. 🚩Зачем он нужен? Обратную польскую нотацию для вычисления арифметических выражений. Управление вызовами функций в программном стеке. Поддержка операций undo в приложениях. Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое NSManagedObjectId, можем ли мы сохранить его на потом если приложение закроется? NSManagedObjectID – это уникальный идентификатор объекта в Core Data, который остаётся неизменным на протяжении всего жизненного цикла объекта. 🚩Как сохранить `NSManagedObjectID`? Используем uriRepresentation() – это строка (URL), которая уникально идентифицирует объект.
func saveObjectID(_ object: NSManagedObject) {
    let objectID = object.objectID.uriRepresentation().absoluteString
    UserDefaults.standard.set(objectID, forKey: "savedObjectID")
}
🚩Как восстановить объект по `NSManagedObjectID`? 1. Получаем URL из UserDefaults. 2. Преобразуем URL в NSManagedObjectID. 3. Загружаем объект из Core Data.
func fetchSavedObjectID(context: NSManagedObjectContext) -> NSManagedObject? {
    guard let objectIDString = UserDefaults.standard.string(forKey: "savedObjectID"),
          let objectURL = URL(string: objectIDString) else { return nil }

    let objectID = context.persistentStoreCoordinator?.managedObjectID(forURIRepresentation: objectURL)

    if let objectID = objectID {
        return context.object(with: objectID)
    }
    return nil
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Какая разница между Dependency Inversion и Dependency Injection? Dependency Inversion — это принцип, согласно которому высокоуровневые модули не должны зависеть от низкоуровневых напрямую, а через абстракции. Dependency Injection — это механизм, с помощью которого зависимости передаются извне, реализуя этот принцип. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Как сравниваются значения в dictionary? В Swift словарь (`Dictionary<Key, Value>`) – это неупорядоченная коллекция пар `ключ → значение`, где ключи уникальны. 🟠Сравнение двух словарей (`==`) Swift позволяет сравнивать два словаря по их ключам и значениям, если и ключи, и значения соответствуют протоколу Equatable.
let dict1 = ["name": "Alice", "age": "25"]
let dict2 = ["name": "Alice", "age": "25"]
let dict3 = ["name": "Bob", "age": "30"]

print(dict1 == dict2) // ✅ true (значения одинаковые)
print(dict1 == dict3) // ❌ false (разные значения)
Ошибка при сравнении Dictionary без Equatable Если значения не соответствуют `Equatable`, сравнение не сработает:
struct User {
    let name: String
}

let dict1 = ["user": User(name: "Alice")]
let dict2 = ["user": User(name: "Alice")]

// Ошибка: Type 'User' does not conform to protocol 'Equatable'
// print(dict1 == dict2)
Решение: Сделать User Equatable:
struct User: Equatable {
    let name: String
}

print(dict1 == dict2) // Теперь работает!
🟠Поиск и сравнение отдельных значений Можно сравнивать отдельные элементы по ключу.
let dict = ["name": "Alice", "age": "25"]

if dict["name"] == "Alice" {
    print("Имя совпадает") // ✅
}
🟠Сравнение по ключам (`keys`) и значениям (`values`) Можно сравнить только ключи или только значения.
let dict1 = ["name": "Alice", "age": "25"]
let dict2 = ["age": "30", "name": "Alice"]

print(dict1.keys == dict2.keys) // ✅ true (ключи одинаковые)
Сравнение значений
print(Set(dict1.values) == Set(dict2.values)) // ✅ true (если порядок неважен)
🟠Сравнение словарей с разными типами (`Any`) Если словарь хранит Any, то прямое сравнение не сработает, и нужно сравнивать элементы вручную.
let dict1: [String: Any] = ["name": "Alice", "age": 25]
let dict2: [String: Any] = ["name": "Alice", "age": 25]

// Функция сравнения словарей с `Any`
func areDictionariesEqual(_ dict1: [String: Any], _ dict2: [String: Any]) -> Bool {
    return NSDictionary(dictionary: dict1).isEqual(to: dict2)
}

print(areDictionariesEqual(dict1, dict2)) // ✅ true
Ставь 👍 и забирай 📚 Базу знаний

🤔 Какие есть способы верстать? В iOS существует несколько способов вёрстки пользовательского интерфейса. Каждый из них имеет свои плюсы и минусы в зависимости от проекта. 🟠Interface Builder (Storyboard & XIB) Используется: визуальный редактор в Xcode. Storyboard - Позволяет создавать весь UI в одном файле .storyboard. - Поддерживает Auto Layout и Size Classes для адаптивного дизайна. - Можно настраивать Segue (переходы между экранами). 🟠Верстка кодом (без Storyboard) Используется: Полностью программная вёрстка без использования Interface Builder.
let button = UIButton()
button.setTitle("Нажми", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)

NSLayoutConstraint.activate([
    button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
🟠SwiftUI – декларативный подход Используется: Современный способ верстки с декларативным синтаксисом.
struct ContentView: View {
    var body: some View {
        VStack {
            Text("Привет, SwiftUI!")
                .font(.largeTitle)
            Button("Нажми меня") {
                print("Кнопка нажата")
            }
        }
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Как можно создать любую переменную и записать туда любой тип данных? В Swift — через тип Any. Пример: var anything: Any = "string", потом anything = 42. Однако, чтобы использовать значение, нужно приведение типа (as?, as!). Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что должны реализовывать переменные содержащиеся в протоколе? В 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"
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Есть ли в свифте множественное наследование? В 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)
Ставь 👍 и забирай 📚 Базу знаний

🤔 Расскажи про структуры Структуры (struct) – это один из основных типов данных в Swift. Они значимые (value type), то есть при передаче копируются, а не передаются по ссылке. 🚩Главные особенности `struct` Value type – при передаче копируется (в отличие от классов) Нет ARC (автоматического подсчета ссылок) – производительность выше Могут иметь методы, свойства, инициализаторы Работают с протоколами (protocol-oriented programming) Не поддерживают наследование 🚩Пример структуры
struct Car {
    var model: String
    var year: Int

    func description() -> String {
        return "\(model) – \(year)"
    }
}

let car1 = Car(model: "Tesla", year: 2023)
var car2 = car1 // Создается копия

print(car1.description()) // Tesla – 2023
print(car2.description()) // Tesla – 2023

car2.year = 2024 // Изменяем car2, но car1 остается прежним
print(car1.year) // 2023
print(car2.year) // 2024
🚩Мутируемые структуры (`mutating`) По умолчанию методы не могут изменять свойства структуры. Чтобы изменить их внутри метода, нужно использовать mutating
struct Counter {
    var count = 0

    mutating func increment() {
        count += 1
    }
}

var counter = Counter()
counter.increment()
print(counter.count) // 1
Ставь 👍 и забирай 📚 Базу знаний

🤔 Где фреймы наиболее яркий пример использования? Фреймы (frames) в iOS-разработке используются для задания размеров и расположения элементов интерфейса (UIView) вручную. 🟠Кастомные анимации Когда нужно анимировать движение элемента, проще всего работать с его frame, так как он напрямую управляет origin (координаты) и size (размеры).
UIView.animate(withDuration: 0.5) {
    self.button.frame.origin.x += 100
}
🟠Ручная верстка (без Auto Layout) Если вы не используете Auto Layout или хотите задать положение элементов программно, frame позволяет точно указать размеры и координаты.
let button = UIButton(type: .system)
button.frame = CGRect(x: 50, y: 100, width: 200, height: 50)
button.setTitle("Нажми меня", for: .normal)
view.addSubview(button)
🟠Оптимизация производительности При динамической подгрузке ячеек в UITableView или UICollectionView можно вручную вычислять frame для ускорения работы, вместо использования Auto Layout, который может замедлить скроллинг. 🟠Работа с Core Graphics и CALayer При рисовании или настройке слоев CALayer используется frame, чтобы точно определить размеры слоя.
let borderLayer = CALayer()
borderLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
borderLayer.borderWidth = 2
borderLayer.borderColor = UIColor.red.cgColor
view.layer.addSublayer(borderLayer)
Ставь 👍 и забирай 📚 Базу знаний

🤔 Расскажи про кодирование и декодирование в 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}]
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Надо ли отслеживать статус задачи в dispatchworkitem? Да, отслеживание статуса задачи в DispatchWorkItem может быть полезным, но это зависит от требований приложения. 🟠Когда это полезно? Если задача может быть отменена (cancel()) Если выполнение задачи можно приостановить или продолжить Если нужно проверить завершение перед выполнением следующего действия*
let workItem = DispatchWorkItem {
    print("Задача выполняется")
}

// Запускаем задачу
DispatchQueue.global().async(execute: workItem)

// Отмена перед выполнением
workItem.cancel()

// Проверяем статус выполнения
if workItem.isCancelled {
    print("Задача отменена")
} else {
    print("Задача выполнена")
}
🟠Можно ли проверить, завершена ли задача? В DispatchWorkItem нет метода проверки завершения. Но можно вручную отслеживать завершение с помощью notify:
let workItem = DispatchWorkItem {
    print("Задача выполняется")
}

// Сообщаем о завершении
workItem.notify(queue: .main) {
    print("Задача завершена")
}

DispatchQueue.global().async(execute: workItem)
🟠Надо ли всегда отслеживать статус? Если задача короткая и простая → НЕ ОБЯЗАТЕЛЬНО. Если задача важная, может быть отменена или зависит от других задач → ЛУЧШЕ ОТСЛЕЖИВАТЬ. Ставь 👍 и забирай 📚 Базу знаний

🤔 В каком методе жизненного цикла можно поставить отступы к vue? Если вы хотите задать отступы (margins, padding) для UIView в жизненном цикле UIViewController, то важно выбрать правильный момент, когда размеры view уже определены. 🚩Пример установки отступов в `viewDidLayoutSubviews()`
class MyViewController: UIViewController {
    let myView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        myView.backgroundColor = .red
        view.addSubview(myView)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        // Установка отступов (margins)
        myView.frame = view.bounds.insetBy(dx: 20, dy: 50)
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что означает принцип open closed? Принцип OCP (Open-Closed Principle) гласит: "Программные сущности должны быть открыты для расширения, но закрыты для модификации." Это значит, что код должен позволять добавлять новый функционал без изменения существующего кода. 🚩Почему это важно? Меньше багов – изменения не ломают старый код. Лучшая поддержка – новый функционал добавляется без переписывания старого. Гибкость – можно расширять систему без изменения её базовой логики. 🚩Пример нарушения принципа OCP Допустим, у нас есть класс, который рисует фигуры:
class ShapeDrawer {
    func draw(shape: String) {
        if shape == "circle" {
            print("Рисуем круг")
        } else if shape == "square" {
            print("Рисуем квадрат")
        }
    }
}
🚩Как исправить? Используем OCP! Лучше использовать наследование или протоколы, чтобы расширять функциональность, не меняя существующий код:
protocol Drawable {
    func draw()
}

class Circle: Drawable {
    func draw() {
        print("Рисуем круг")
    }
}

class Square: Drawable {
    func draw() {
        print("Рисуем квадрат")
    }
}

class ShapeDrawer {
    func draw(shape: Drawable) {
        shape.draw()
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое notification центр? Это механизм в iOS и macOS для обмена сообщениями между различными частями приложения. Он позволяет объектам отправлять и получать уведомления без необходимости напрямую ссылаться друг на друга, что способствует более гибкому и модульному дизайну. 🚩Основные аспекты 🟠Отправка уведомлений Любой объект может отправить уведомление с помощью Notification Center. Уведомления идентифицируются по имени (Notification.Name). Можно передать дополнительную информацию в виде словаря (userInfo).
NotificationCenter.default.post(name: .myNotification, object: nil)   
🟠Получение уведомлений Объекты могут регистрироваться для получения уведомлений с определенным именем. Для обработки уведомлений используется метод, который будет вызван при получении уведомления.
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: .myNotification, object: nil)
   
@objc func handleNotification(notification: Notification) {
    print("Received notification")
}   
🟠Удаление наблюдателей Важно удалять наблюдателей, когда они больше не нужны, чтобы избежать утечек памяти. Обычно это делается в методе deinit или перед уничтожением объекта.
NotificationCenter.default.removeObserver(self, name: .myNotification, object: nil)   
🚩ПлюсыСлабая связанность Объекты не нужно напрямую ссылаться друг на друга, что улучшает модульность кода. ➕Гибкость Позволяет легко организовать обмен сообщениями между различными частями приложения. ➕Повторное использование Уведомления могут использоваться многими объектами, что облегчает реализацию функций, таких как обновление интерфейса или реагирование на события. 🚩Примеры использования 1⃣Обновление интерфейса Когда данные изменяются, можно отправить уведомление для обновления пользовательского интерфейса.
NotificationCenter.default.post(name: .dataDidUpdate, object: nil)   
2⃣Реакция на системные события Например, можно подписаться на уведомление о смене состояния сети.
NotificationCenter.default.addObserver(self, selector: #selector(handleNetworkChange), name: .reachabilityChanged, object: nil)   
3⃣Межмодульное взаимодействие Различные модули приложения могут общаться друг с другом через Notification Center, не создавая сильных зависимостей.
NotificationCenter.default.post(name: .userDidLogin, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: .userDidLogin, object: nil)
Ставь 👍 и забирай 📚 Базу знаний

🤔 Может ли value type передаваться по ссылке? По умолчанию значимые типы (value types) — это структуры, перечисления, кортежи. Они передаются по значению, то есть создаётся копия. Но если обернуть value type в inout, использовать UnsafeMutablePointer или ссылочный контейнер (например, класс), то можно добиться передачи по ссылке. Однако это скорее обходное поведение, а не правило. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Почему по дефолту дабл, а не фолт? В 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
Ставь 👍 и забирай 📚 Базу знаний