Слабые ссылки (weak references) играют важную роль в управлении памятью, особенно когда нужно предотвратить циклы сильных ссылок (retain cycles) и утечки памяти.
Циклы сильных ссылок возникают, когда два объекта держат сильные ссылки друг на друга, что препятствует их освобождению из памяти. Слабые ссылки разрывают этот цикл, позволяя одному из объектов освобождаться.
class Person {
var name: String
weak var friend: Person?
init(name: String) {
self.name = name
}
}
var alice: Person? = Person(name: "Alice")
var bob: Person? = Person(name: "Bob")
alice?.friend = bob
bob?.friend = alice
alice = nil // Теперь объекты могут быть освобождены
bob = nil Утечки памяти происходят, когда объекты, которые больше не нужны, не освобождаются из памяти. Слабые ссылки помогают избежать этих утечек, обеспечивая правильное освобождение памяти. Делегаты часто объявляются как слабые ссылки, чтобы избежать утечек памяти.
protocol TaskDelegate: AnyObject {
func taskDidFinish()
}
class Task {
weak var delegate: TaskDelegate?
func complete() {
delegate?.taskDidFinish()
}
}
class ViewController: TaskDelegate {
var task = Task()
init() {
task.delegate = self
}
func taskDidFinish() {
print("Task finished")
}
} Слабые ссылки удобны для временных зависимостей, когда объект не должен удерживаться в памяти, если нет других сильных ссылок. Использование слабых ссылок для временных объектов.
class Cache {
weak var temporaryObject: SomeClass?
}
class SomeClass {
// Код класса
}
var cache = Cache()
var object = SomeClass()
cache.temporaryObject = object
object = SomeClass() // Старый объект удаляется, так как на него нет сильных ссылок Основное преимущество слабых ссылок заключается в их способности разрывать циклы ссылок, предотвращая утечки памяти.
Слабые ссылки позволяют объектам освобождаться из памяти, когда на них больше нет сильных ссылок, что улучшает управление ресурсами.
Использование слабых ссылок обеспечивает более гибкое и безопасное управление зависимостями между объектами.
Необходимо учитывать, что слабые ссылки могут стать nil в любой момент, поэтому требуется дополнительная проверка.
Требуется хорошее понимание жизненного цикла объектов и управления памятью, чтобы правильно использовать слабые ссылки.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это расширение для iOS-приложений, которое позволяет модифицировать push-уведомления до их показа. Например, можно добавить изображение, вложение или изменить текст перед отображением пользователю.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Фреймы (frames) в iOS-разработке используются для задания размеров и расположения элементов интерфейса (UIView) вручную.
Когда нужно анимировать движение элемента, проще всего работать с его
frame, так как он напрямую управляет origin (координаты) и size (размеры). UIView.animate(withDuration: 0.5) {
self.button.frame.origin.x += 100
}Если вы не используете 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, который может замедлить скроллинг.При рисовании или настройке слоев
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)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В большинстве языков — 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