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

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

رفتن به کانال در Telegram

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

نمایش بیشتر
2 196
مشترکین
+124 ساعت
-17 روز
-1330 روز
جذب مشترکین
ژوئیه '26
ژوئیه '26
+15
در 0 کانال‌ها
ژوئن '26
+32
در 0 کانال‌ها
Get PRO
مه '26
+21
در 0 کانال‌ها
Get PRO
آوریل '26
+23
در 0 کانال‌ها
Get PRO
مارس '26
+35
در 0 کانال‌ها
Get PRO
فوریه '26
+45
در 1 کانال‌ها
Get PRO
ژانویه '26
+58
در 0 کانال‌ها
Get PRO
دسامبر '25
+28
در 0 کانال‌ها
Get PRO
نوامبر '25
+156
در 1 کانال‌ها
Get PRO
اکتبر '25
+26
در 0 کانال‌ها
Get PRO
سپتامبر '25
+41
در 0 کانال‌ها
Get PRO
اوت '25
+38
در 0 کانال‌ها
Get PRO
ژوئیه '25
+27
در 0 کانال‌ها
Get PRO
ژوئن '25
+34
در 0 کانال‌ها
Get PRO
مه '25
+50
در 0 کانال‌ها
Get PRO
آوریل '25
+87
در 0 کانال‌ها
Get PRO
مارس '25
+151
در 2 کانال‌ها
Get PRO
فوریه '25
+123
در 1 کانال‌ها
Get PRO
ژانویه '25
+127
در 53 کانال‌ها
Get PRO
دسامبر '24
+55
در 1 کانال‌ها
Get PRO
نوامبر '24
+75
در 0 کانال‌ها
Get PRO
اکتبر '24
+193
در 42 کانال‌ها
Get PRO
سپتامبر '24
+348
در 251 کانال‌ها
Get PRO
اوت '24
+98
در 0 کانال‌ها
Get PRO
ژوئیه '24
+140
در 54 کانال‌ها
Get PRO
ژوئن '24
+411
در 244 کانال‌ها
Get PRO
مه '24
+646
در 191 کانال‌ها
Get PRO
آوریل '24
+353
در 23 کانال‌ها
تاریخ
رشد مشترکین
اشارات
کانال‌ها
28 ژوئیه0
27 ژوئیه+2
26 ژوئیه0
25 ژوئیه0
24 ژوئیه0
23 ژوئیه+1
22 ژوئیه0
21 ژوئیه0
20 ژوئیه+1
19 ژوئیه+1
18 ژوئیه0
17 ژوئیه+1
16 ژوئیه0
15 ژوئیه+2
14 ژوئیه+1
13 ژوئیه0
12 ژوئیه+1
11 ژوئیه+1
10 ژوئیه0
09 ژوئیه+1
08 ژوئیه0
07 ژوئیه0
06 ژوئیه0
05 ژوئیه0
04 ژوئیه0
03 ژوئیه0
02 ژوئیه+3
01 ژوئیه0
پست‌های کانال
🤔 Что такое мьютекс (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) Если мьютексы захватываются в неправильном порядке, это может привести к ситуации, когда два или более потока блокируют друг друга, ожидая освобождения мьютексов. ➖Производительность Чрезмерное использование мьютексов может привести к снижению производительности из-за увеличения времени ожидания потоков. Ставь 👍 и забирай 📚 Базу знаний

2
🤔 Что такое Quality of Service? Quality of Service (QoS) — это система приоритетов, определяющая, насколько срочно и важно выполнить задачу. От этого зависит, сколько ресурсов система выделит. Например, для UI используется самый высокий уровень (user-interactive), а для фоновых задач — низкий (background). Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
171
3
🤔 Чем отличается 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? // Теперь утечки памяти не будет } Ставь 👍 и забирай 📚 Базу знаний
200
4
🤔 Что под капотом стэка? Это абстрактная структура данных, работающая по принципу 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 в приложениях. Ставь 👍 и забирай 📚 Базу знаний
187
5
🤔 Что такое 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 } Ставь 👍 и забирай 📚 Базу знаний
184
6
🤔 Какая разница между Dependency Inversion и Dependency Injection? Dependency Inversion — это принцип, согласно которому высокоуровневые модули не должны зависеть от низкоуровневых напрямую, а через абстракции. Dependency Injection — это механизм, с помощью которого зависимости передаются извне, реализуя этот принцип. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
190
7
🤔 Как сравниваются значения в 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 Ставь 👍 и забирай 📚 Базу знаний
204
8
🤔 Какие есть способы верстать? В 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("Кнопка нажата") } } } } Ставь 👍 и забирай 📚 Базу знаний
218
9
🤔 Как можно создать любую переменную и записать туда любой тип данных? В Swift — через тип Any. Пример: var anything: Any = "string", потом anything = 42. Однако, чтобы использовать значение, нужно приведение типа (as?, as!). Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
218
10
🤔 Что должны реализовывать переменные содержащиеся в протоколе? В 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" } } Ставь 👍 и забирай 📚 Базу знаний
231
11
🤔 Есть ли в свифте множественное наследование? В 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) Ставь 👍 и забирай 📚 Базу знаний
222
12
🤔 Расскажи про структуры Структуры (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 Ставь 👍 и забирай 📚 Базу знаний
225
13
🤔 Где фреймы наиболее яркий пример использования? Фреймы (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) Ставь 👍 и забирай 📚 Базу знаний
231
14
🤔 Расскажи про кодирование и декодирование в 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}] } Ставь 👍 и забирай 📚 Базу знаний
230
15
🤔 Надо ли отслеживать статус задачи в 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) 🟠Надо ли всегда отслеживать статус? Если задача короткая и простая → НЕ ОБЯЗАТЕЛЬНО. Если задача важная, может быть отменена или зависит от других задач → ЛУЧШЕ ОТСЛЕЖИВАТЬ. Ставь 👍 и забирай 📚 Базу знаний
233
16
🤔 В каком методе жизненного цикла можно поставить отступы к 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) } } Ставь 👍 и забирай 📚 Базу знаний
260
17
🤔 Что означает принцип 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() } } Ставь 👍 и забирай 📚 Базу знаний
263
18
🤔 Что такое 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) Ставь 👍 и забирай 📚 Базу знаний
261
19
🤔 Может ли value type передаваться по ссылке? По умолчанию значимые типы (value types) — это структуры, перечисления, кортежи. Они передаются по значению, то есть создаётся копия. Но если обернуть value type в inout, использовать UnsafeMutablePointer или ссылочный контейнер (например, класс), то можно добиться передачи по ссылке. Однако это скорее обходное поведение, а не правило. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
259
20
🤔 Почему по дефолту дабл, а не фолт? В Swift (и во многих других языках программирования) по умолчанию числовой литерал с плавающей запятой интерпретируется как `Double`, а не Float. 🚩Основные причины: 🟠Бóльшая точность Double имеет 64 бита, а Float – 32 бита. Это значит, что 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 Ставь 👍 и забирай 📚 Базу знаний
283