В большинстве языков — float, double, или Float32, Float64:
- float — 32 бита, ограниченная точность.
- double — 64 бита, выше точность и диапазон. Python использует тип float, который реализован как 64-битный IEEE 754 double.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Словарь (Dictionary) представляет собой коллекцию пар ключ-значение, где каждый ключ должен быть уникальным. Чтобы использовать какой-либо тип в качестве ключа словаря, этот тип должен соответствовать протоколу
Hashable. Это требование обусловлено тем, что Swift использует хеш-таблицу для хранения элементов словаря, что обеспечивает быстрый доступ к его элементам.Должны быть уникальными: Каждый ключ в словаре должен быть уникальным. При попытке добавить в словарь элемент с ключом, который уже существует в словаре, старое значение будет заменено на новое.
Должны соответствовать протоколу
Hashable: Это означает, что тип ключа должен иметь способность быть правильно хешированным. Большинство базовых типов Swift (например, String, Int, Double и др.) уже соответствуют Hashable, поэтому их можно использовать в качестве ключей без дополнительных усилий.Могут быть любого типа: Значения в словаре могут быть любого типа, и они не обязаны соответствовать протоколу Hashable.
Могут повторяться: Разные ключи могут иметь одинаковые значения.
var personAge: [String: Int] = ["John": 30, "Sara": 25]
Вы также можете использовать собственные пользовательские типы в качестве ключей словаря, но для этого ваш тип должен соответствовать протоколу
Hashable. Это включает в себя реализацию требуемых методов для сравнения на равенство (==) и хеширования (hash(into:)).struct Person: Hashable {
var name: String
var id: Int
}
var peopleDictionary: [Person: String] = [Person(name: "John", id: 1): "Engineer"]Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
- unowned — это слабая ссылка, но с гарантией, что объект ещё существует во время обращения. Если объект уже освобождён — произойдёт крах (crash).
- unowned(unsafe) — ещё менее безопасный вариант, не делает проверку на nil вообще. Это низкоуровневая, "сырой" доступ к памяти, использовать его нужно крайне осторожно.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
@autoclosure — это специальный атрибут в Swift, который автоматически превращает переданное выражение в замыкание. Это позволяет отложить выполнение выражения до момента, когда оно действительно понадобится. @autoclosure?Обычно его используют для улучшения читаемости кода, особенно когда нужно лениво вычислять аргумент функции. Например, если переданный аргумент — это сложное вычисление, его выполнение можно отложить до нужного момента.
Допустим, у нас есть функция, которая принимает замыкание
func logMessage(_ message: () -> String) {
print("Лог: \(message())")
}
// Вызываем функцию, передавая замыкание
logMessage { "Сообщение: \(2 + 2)" }
Теперь используем `@autoc чтобы сделать вызов функции проще
func logMessage(_ message: @autoclosure () -> String) {
print("Лог: \(message())")
}
// Теперь аргумент можно передавать без {}
logMessage("Сообщение: \(2 + 2)")
Стандартные функции Swift используют @autoclosure, чтобы избежать вычисления аргументов, если проверка не нужна:assert(2 + 2 == 4, "Ошибка: 2 + 2 не равно 4!")
Допустим, у нас есть функция, которая выполняет блок только если включен режим отладкие в замыкание. Это позволяет отложить выполнение выражения до момента, когда оно действительно понадобится.
Обычно его используют для улучшения читаемости кода, особенно когда нужно.`@autoc но если нужно сохранить замыкание для будущего выполнения, это можно сделать рый автоматически превращает переданное выражение в замыкание. Это позволяет отложить выполнение выражения до момента, когда оно действительно понадобится.
Обычно его используют для улучшения читаемости кода, особенно когда нужно лениво вычислять аргумент функции.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
2. Включает выделение памяти и назначение значений свойствам (вручную или по умолчанию).
3. В Kotlin инициализация может выполняться через первичный конструктор, блоки init или вторичные конструкторы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊8
В 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
👍3
Пассивная модель — это подход, при котором объект модели не знает о существовании интерфейса (view) и не уведомляет его об изменениях. Контроллер сам запрашивает обновление данных и обновляет интерфейс вручную.
Активная модель — модель сама уведомляет представление или контроллер об изменениях, обычно через делегаты, нотификации или биндинги. Это повышает реактивность, но усложняет структуру.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
В Swift есть несколько способов отлавливать и диагностировать ошибки в коде:
Используется, если функция генерирует ошибку (
throws). enum LoginError: Error {
case wrongPassword
case userNotFound
}
func login(user: String, password: String) throws {
if user != "admin" { throw LoginError.userNotFound }
if password != "1234" { throw LoginError.wrongPassword }
}
do {
try login(user: "admin", password: "wrong")
} catch LoginError.wrongPassword {
print("Ошибка: Неверный пароль")
} catch {
print("Ошибка: \(error)")
}Эти функции прерывают выполнение программы, если что-то пошло не так.
assert() (только в Debug) let age = -5
assert(age >= 0, "Возраст не может быть отрицательным")
precondition() (работает в Release) precondition(age >= 0, "Возраст не может быть отрицательным")
fatalError() (прерывает программу) func getData() -> String {
fatalError("Метод ещё не реализован")
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Closure захватывает value type по значению. То есть создаётся копия значения, и она остаётся доступной внутри замыкания, даже если оригинальное значение вышло из области видимости.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Метод `hitTest(_:with:)` в
UIView используется для определения, какая вью была нажата пользователем. Он ищет самый глубокий (верхний) UI-элемент, который должен обработать касание. Если у
UIView выключено свойство isUserInteractionEnabled, то hitTest(_:with:) не будет работать – вью полностью игнорирует касания. let button = UIButton()
button.isUserInteractionEnabled = false
let touchPoint = CGPoint(x: 50, y: 50)
let result = button.hitTest(touchPoint, with: nil)
print(result) // nil ❌
Если
UIView почти полностью прозрачна (alpha меньше 0.01), то она не будет участвовать в обработке событий.let view = UIView()
view.alpha = 0.005
let touchPoint = CGPoint(x: 50, y: 50)
let result = view.hitTest(touchPoint, with: nil)
print(result) // nil ❌
Если вью скрыта (
isHidden = true), hitTest(_:with:) не сработает, так как iOS её вообще не обрабатываетlet view = UIView()
view.isHidden = true
let touchPoint = CGPoint(x: 50, y: 50)
let result = view.hitTest(touchPoint, with: nil)
print(result) // nil ❌
hitTest(_:with:) проверяет только внутри `bounds` вью, и если точка находится за пределами, он вернёт `nil`.let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let touchPoint = CGPoint(x: 150, y: 150) // Вне границ вью
let result = view.hitTest(touchPoint, with: nil)
print(result) // nil ❌
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊2
Dependency Inversion — это принцип, согласно которому высокоуровневые модули не должны зависеть от низкоуровневых напрямую, а через абстракции. Dependency Injection — это механизм, с помощью которого зависимости передаются извне, реализуя этот принцип.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Половина массива — это подмножество элементов массива, которое составляет примерно 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
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊7
Да, отслеживание статуса задачи в
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)Если задача короткая и простая → НЕ ОБЯЗАТЕЛЬНО.
Если задача важная, может быть отменена или зависит от других задач → ЛУЧШЕ ОТСЛЕЖИВАТЬ.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Нужно выносить бизнес-логику в модель, а форматирование данных — во вью-модель или presenter. Контроллер должен только координировать взаимодействие между этими слоями.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Механизм Copy-on-Write (CoW) используется для оптимизации производительности и использования памяти при копировании объектов. Этот механизм особенно полезен для неизменяемых (immutable) структур данных. CoW часто ассоциируется со стандартными коллекциями и собственными типами данных, реализованными как структуры (value types), такие как
Array, String, Dictionary, и Set.Работает так, что копия объекта создаётся только в тот момент, когда происходит попытка модификации. До этого момента все копии объекта фактически ссылаются на одни и те же данные в памяти. Это позволяет сэкономить как время, так и память, поскольку избегается ненужное дублирование данных, когда оно не требуется.
Автоматически применяет механизм CoW к своим стандартным коллекциям, таким как
Array, String, Dictionary, и Set. Это означает, что при передаче этих объектов в функции или при их копировании реальное дублирование данных происходит только в случае модификации одной из копий. Таким образом, если вы создаёте копию массива и не изменяете его, обе переменные будут указывать на одни и те же данные в памяти. Как только вы модифицируете одну из копий, Swift создаст реальную копию данных для этой копии, обеспечивая независимость данных между оригиналом и копией.var originalArray = [1, 2, 3]
var copiedArray = originalArray // На этом этапе данные не дублируются
copiedArray.append(4) // Теперь данные копируются, потому что copiedArray модифицируется
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Счётчик ссылок (ARC) уменьшается, когда ссылка на объект уничтожается, т.е. когда переменная, содержащая ссылку, выходит из области видимости или явно устанавливается в nil.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊4👍1🔥1
Мьютекс (от англ. "mutex" - mutual exclusion, взаимное исключение) — это механизм синхронизации, используемый в многопоточном программировании для предотвращения одновременного доступа нескольких потоков к общим ресурсам, таким как переменные, структуры данных или файлы. Он помогает избежать состояния гонки (race condition), когда результат выполнения программы зависит от неопределённого порядка доступа потоков к ресурсу.
Мьютекс обеспечивает доступ к общему ресурсу только одному потоку в каждый момент времени. Когда один поток захватывает мьютекс, другие потоки должны ждать, пока мьютекс не будет освобождён.
Поток захватывает мьютекс перед доступом к общему ресурсу и освобождает его после завершения работы с этим ресурсом. Если мьютекс уже захвачен другим потоком, текущий поток будет блокирован до тех пор, пока мьютекс не будет освобождён.
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())")
Мьютексы защищают общие ресурсы от одновременного доступа, предотвращая повреждение данных.
Код становится более предсказуемым и стабильным, так как исключаются состояния гонки.
Если мьютексы захватываются в неправильном порядке, это может привести к ситуации, когда два или более потока блокируют друг друга, ожидая освобождения мьютексов.
Чрезмерное использование мьютексов может привести к снижению производительности из-за увеличения времени ожидания потоков.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
CocoaPods — это менеджер зависимостей для проектов iOS/macOS. Он позволяет подключать сторонние библиотеки в проект, управлять их версиями, устанавливать и обновлять автоматически.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
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) // 10struct хранятся в стеке, а не в куче, что делает их создание и удаление быстрее. Куча (
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] (новый массив)
Хотя
struct — предпочтительный выбор, class нужен, когда: Нужна ссылочная семантика (например, объект должен изменяться в разных местах кода).
Есть сложные иерархии наследования.
Требуется работа с Objective-C (
NSObject).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3