В Swift ссылки (references) на объекты могут быть сильными (strong) и слабыми (weak). Они отличаются способом управления памятью и временем жизни объектов, на которые ссылаются.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
var person1: Person? = Person(name: "Alice")
var person2: Person? = person1 // person2 имеет сильную ссылку на тот же объект, что и person1
person1 = nil // Объект все еще удерживается в памяти благодаря person2
print(person2?.name) // Output: Alice
person2 = nil // Теперь объект будет удалён из памяти, так как нет сильных ссылокclass Person {
var name: String
init(name: String) {
self.name = name
}
}
class Apartment {
var tenant: Person?
init(tenant: Person?) {
self.tenant = tenant
}
}
var alice: Person? = Person(name: "Alice")
var apartment: Apartment? = Apartment(tenant: alice)
// Создание слабой ссылки для предотвращения циклической зависимости
class Tenant {
var name: String
weak var apartment: Apartment? // Слабая ссылка
init(name: String) {
self.name = name
}
}
let tenant = Tenant(name: "Bob")
apartment?.tenant = alice
alice = nil // Объект Person будет удалён из памяти, так как больше нет сильных ссылок
print(apartment?.tenant?.name) // Output: nilСильные и слабые ссылки в Swift различаются по способу управления памятью и временем жизни объектов. Сильные ссылки удерживают объекты в памяти, тогда как слабые ссылки позволяют объектам быть удалёнными, предотвращая циклические ссылки и утечки памяти.
В двух фразах: Сильные ссылки удерживают объекты в памяти и не позволяют им быть удалёнными, пока на них существуют такие ссылки. Слабые ссылки не удерживают объекты, что позволяет им быть удалёнными из памяти, когда нет других сильных ссылок, предотвращая утечки памяти.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Anonymous Quiz
14%
Упрощает доступ к свойствам
79%
Определяет удобный инициализатор
4%
Улучшает производительность
3%
Объявляет протокол
❤1👍1
Grand Central Dispatch (GCD) — это мощная технология в iOS и macOS, предоставляемая Apple для управления многопоточностью и параллелизмом в приложениях. GCD позволяет легко выполнять задачи асинхронно, управлять очередями задач и эффективно использовать системные ресурсы. Вот основные аспекты GCD:
let serialQueue = DispatchQueue(label: "com.example.serialQueue")
let concurrentQueue = DispatchQueue(label: "com.example.concurrentQueue", attributes: .concurrent)
DispatchQueue.global(qos: .background).async {
// Долгосрочная фоновая задача
print("Background task")
}
let serialQueue = DispatchQueue(label: "com.example.serialQueue")
serialQueue.async {
// Задача в пользовательской сериализованной очереди
print("Serial queue task")
}
let serialQueue = DispatchQueue(label: "com.example.serialQueue")
serialQueue.sync {
// Синхронная задача
print("Sync task")
}
let delay = DispatchTime.now() + .seconds(5)
DispatchQueue.main.asyncAfter(deadline: delay) {
// Задача, выполненная через 5 секунд
print("Delayed task")
}
let group = DispatchGroup()
let queue = DispatchQueue.global()
group.enter()
queue.async {
// Первая задача
print("First task")
group.leave()
}
group.enter()
queue.async {
// Вторая задача
print("Second task")
group.leave()
}
group.notify(queue: DispatchQueue.main) {
// Все задачи завершены
print("All tasks are done")
}
let concurrentQueue = DispatchQueue(label: "com.example.concurrentQueue", attributes: .concurrent)
concurrentQueue.async(flags: .barrier) {
// Барьерная задача
print("Barrier task")
}
Grand Central Dispatch (GCD) — это мощная и простая в использовании технология для управления многопоточностью и параллелизмом в приложениях iOS и macOS. Она предоставляет разработчикам средства для выполнения задач асинхронно, управления очередями задач и эффективного использования системных ресурсов.
В двух фразах: GCD позволяет легко и эффективно управлять многопоточностью в приложениях iOS и macOS. Это достигается с помощью очередей задач, асинхронного выполнения, групп задач и барьерных задач.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2❤1
Anonymous Quiz
13%
Hashable
30%
Comparable
55%
Equatable
2%
Codable
👍2
Куча (heap) в Swift управляется с помощью механизма автоматического управления памятью (ARC), который использует подсчёт ссылок (reference counting) для автоматического выделения и освобождения памяти. Рассмотрим основные аспекты и типы ссылок:
class Person {
let name: String
init(name: String) { self.name = name }
}
var person1: Person? = Person(name: "Alice") // Счётчик ссылок: 1
var person2: Person? = person1 // Счётчик ссылок: 2
person1 = nil // Счётчик ссылок: 1
person2 = nil // Счётчик ссылок: 0, объект освобождается
class Apartment {
weak var tenant: Person?
}
var alice: Person? = Person(name: "Alice")
var apartment = Apartment()
apartment.tenant = alice
alice = nil // Объект освобождается, так как слабые ссылки не удерживают объект в памяти
class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
}
class CreditCard {
let number: Int
unowned let customer: Customer
init(number: Int, customer: Customer) {
self.number = number
self.customer = customer
}
}
var john: Customer? = Customer(name: "John")
john!.card = CreditCard(number: 1234, customer: john!)
john = nil // Объект Customer и CreditCard освобождаются одновременно
В Swift ARC управляет памятью, используя сильные, слабые и неустранимые ссылки для автоматического выделения и освобождения памяти, предотвращая утечки и циклические зависимости.
В двух фразах: Swift использует ARC для автоматического управления памятью с помощью подсчёта ссылок. Сильные ссылки удерживают объекты в памяти, слабые и неустранимые ссылки помогают избежать утечек и циклических зависимостей.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
Anonymous Quiz
2%
Delegates
31%
Error Handling
66%
Try-Catch
1%
Optionals
❤1👍1
В Swift value типы (структуры и перечисления) обычно хранятся в стеке, что обеспечивает их высокую производительность. Однако в некоторых случаях value типы могут стать reference, то есть храниться в куче. Это происходит в следующих ситуациях:
Когда значение типа захватывается замыканием, оно может быть перемещено в кучу для обеспечения корректного управления памятью и жизненного цикла.
struct MyStruct {
var value: Int
}
func createClosure() -> () -> Int {
let myStruct = MyStruct(value: 42)
return { myStruct.value }
}
let closure = createClosure()
print(closure()) // Output: 42В этом примере
myStruct захватывается замыканием, что приводит к его размещению в куче.Когда value тип заворачивается в объект класса, он хранится в куче.
class Box<T> {
var value: T
init(_ value: T) {
self.value = value
}
}
struct MyStruct {
var value: Int
}
let boxedStruct = Box(MyStruct(value: 42))
print(boxedStruct.value.value) // Output: 42В этом примере структура
MyStruct обернута в объект класса Box, что приводит к её размещению в куче.Когда value тип используется в качестве свойства класса, он будет храниться в куче вместе с экземпляром класса.
struct MyStruct {
var value: Int
}
class MyClass {
var myStruct: MyStruct
init(myStruct: MyStruct) {
self.myStruct = myStruct
}
}
let instance = MyClass(myStruct: MyStruct(value: 42))
// instance.myStruct хранится в кучеВ этом примере структура
MyStruct является свойством класса MyClass, поэтому её экземпляры хранятся в куче вместе с экземплярами MyClass.Коллекции, такие как массивы, словари и множества, хранящие value типы, могут размещать эти значения в куче, если коллекция становится слишком большой.
struct MyStruct {
var value: Int
}
let array = [MyStruct(value: 1), MyStruct(value: 2), MyStruct(value: 3)]
// Элементы массива могут быть размещены в кучеКогда массив содержит много элементов, память для них может быть выделена в куче для управления их жизненным циклом.
Value типы в Swift могут стать reference, когда они захватываются замыканиями, оборачиваются в классы, являются свойствами классов или хранятся в больших коллекциях. Это необходимо для управления памятью и жизненным циклом данных в более сложных сценариях.
В двух фразах: Value типы в Swift могут храниться в куче, когда захватываются замыканиями, оборачиваются в классы, используются в качестве свойств классов или хранятся в больших коллекциях. Это помогает управлять памятью и жизненным циклом данных в сложных сценариях.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🔥3👍1
Anonymous Quiz
5%
Codable
18%
Sequence
73%
AsyncSequence
4%
IteratorProtocol
👍2
UIResponder — это базовый класс для объектов, которые могут обрабатывать события в iOS-приложениях, такие как касания, жесты и нажатия клавиш. UIResponder управляет цепочкой ответчиков, передавая события от одного объекта к другому, если текущий объект не может их обработать.Объекты, унаследованные от
UIResponder, могут обрабатывать различные события через методы, такие как touchesBegan, touchesMoved, touchesEnded и touchesCancelled.Определяет, как события передаются между объектами, гарантируя, что все события будут обработаны.
class CustomView: UIView {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
print("Touches began")
}
}UIResponder — это ключевой класс для обработки событий в iOS, предоставляющий методы для работы с касаниями и другими взаимодействиями пользователя.В двух фразах:
UIResponder обрабатывает события в iOS и управляет цепочкой ответчиков. Он является базовым классом для таких объектов, как UIView и UIViewController, обеспечивая их способность реагировать на события.Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4
Anonymous Quiz
92%
Замыкания
3%
Протоколы
4%
Делегаты
1%
Модули
❤1
Autorelease pool — это механизм управления памятью в Objective-C и Swift, который помогает автоматизировать освобождение объектов, когда они больше не нужны. Этот механизм используется для временного хранения объектов, которым необходимо отправить сообщение
release в будущем, чтобы освободить их память. Autorelease pool обеспечивает автоматическое управление памятью и предотвращает утечки памяти, особенно в случаях, когда создаётся много временных объектов.release.Objective-C:
@autoreleasepool {
// Создание временных объектов
NSString *tempString = [[NSString alloc] initWithFormat:@"Hello, %@", @"World"];
// tempString автоматически освободится, когда пул спустится
}Swift:
autoreleasepool {
// Создание временных объектов
let tempString = NSString(format: "Hello, %@", "World")
// tempString автоматически освободится, когда пул спустится
}Управление памятью в циклах: При создании большого количества временных объектов внутри цикла autorelease pool предотвращает увеличение использования памяти.
for i in 0..<1000 {
autoreleasepool {
let tempString = NSString(format: "Iteration %d", i)
// tempString освобождается в конце каждой итерации
}
}Автоматическое освобождение объектов: Autorelease pool позволяет избежать явного вызова
release для каждого объекта, предоставляя автоматическое управление памятью.Создание объектов: Когда объект создаётся с использованием методов, которые возвращают autoreleased объект, он добавляется в текущий autorelease pool.
NSString *string = [NSString stringWithFormat:@"Hello, World"];
Спуск пула: Когда пул спускается, всем объектам, находящимся в пуле, отправляется сообщение
release, что приводит к их освобождению, если нет других сильных ссылок на них.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🤔2
Anonymous Quiz
20%
Указывает на косвенные ссылки
65%
Позволяет рекурсивные перечисления
7%
Делает перечисление асинхронным
9%
Упрощает сериализацию
👍1
Метод
viewWillAppear вызывается в жизненном цикле UIViewController перед тем, как его представление (view) становится видимым пользователю. Этот метод вызывается каждый раз, когда представление контроллера собирается появиться на экране, даже если оно уже было загружено в память.UIViewControllerЗагрузка представления:
loadView(): Вызывается, когда представление контроллера загружается в память.viewDidLoad(): Вызывается после загрузки представления в память. Используется для первоначальной настройки представления и инициализации данных.Перед появлением на экране:
viewWillAppear(_:): Вызывается непосредственно перед тем, как представление контроллера становится видимым на экране. Это хороший момент для обновления данных и интерфейса, если они могли измениться.Появление на экране:
viewDidAppear(_:): Вызывается после того, как представление контроллера стало видимым на экране. Здесь можно запускать анимации или начинать задачи, которые должны выполняться только после того, как представление полностью отображено.Перед исчезновением с экрана:
viewWillDisappear(_:): Вызывается непосредственно перед тем, как представление контроллера исчезнет с экрана. Это подходящее место для остановки анимаций, сохранения состояния и освобождения ресурсов.Исчезновение с экрана:
viewDidDisappear(_:): Вызывается после того, как представление контроллера исчезло с экрана. Используется для выполнения действий, которые должны произойти после того, как представление перестало быть видимым.class MyViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Обновление интерфейса перед тем, как представление станет видимым
print("viewWillAppear: Представление скоро станет видимым")
// Обновление данных
updateData()
}
func updateData() {
// Логика обновления данных
}
}viewWillAppearСтавь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Anonymous Quiz
6%
weak
94%
lazy
0%
unowned
0%
deferred
❤1
Управление памятью (Memory Management) в iOS включает использование автоматического подсчета ссылок (ARC) и инструментов Xcode для анализа и профилирования памяти. ARC автоматически управляет памятью, увеличивая и уменьшая счетчик ссылок на объекты. Когда объект больше не имеет сильных ссылок (strong references), он освобождается.
Automatic Reference Counting (ARC)
class Person {
var name: String
weak var spouse: Person?
init(name: String) {
self.name = name
}
}Xcode Instruments
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Anonymous Quiz
41%
Equatable
39%
Comparable
12%
Hashable
7%
CaseIterable
👍1
Очереди (queues) в iOS и macOS используются для управления задачами в многопоточном программировании с помощью Grand Central Dispatch (GCD). Существуют два основных типа очередей: последовательные (serial) и конкурентные (concurrent). Они различаются по способу выполнения задач.
let serialQueue = DispatchQueue(label: "com.example.serialQueue")
serialQueue.async {
print("Task 1")
}
serialQueue.async {
print("Task 2")
}
// Task 1 будет выполнена перед Task 2
let concurrentQueue = DispatchQueue(label: "com.example.concurrentQueue", attributes: .concurrent)
concurrentQueue.async {
print("Task 1")
}
concurrentQueue.async {
print("Task 2")
}
// Task 1 и Task 2 могут быть выполнены одновременно
DispatchQueue.main.async {
print("Update UI")
}
// Эта задача будет выполнена на главном потоке DispatchQueue.global(qos: .userInitiated).async {
print("High priority task")
}
DispatchQueue.global(qos: .background).async {
print("Low priority task")
}
// Задачи будут выполнены в соответствии с их приоритетом Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Anonymous Quiz
8%
as!
85%
as?
4%
as
2%
is?
👍1
Динамическая диспетчеризация в Swift начинает работать, когда методы или свойства вызываются во время выполнения программы (runtime), а не на этапе компиляции. Это может быть связано с различными механизмами, включая использование
@objc и динамических ключевых слов, протоколы с необязательной реализацией, и взаимодействие с Objective-C API. Давайте рассмотрим основные случаи, когда применяется динамическая диспетчеризация:Использование `@objc` и динамических ключевых слов: Методы и свойства, помеченные атрибутом
@objc или ключевым словом dynamic, используют динамическую диспетчеризацию через Objective-C runtime. Это позволяет изменять поведение методов в процессе выполнения, например, через механизм замен (swizzling).import Foundation
class MyClass: NSObject {
@objc dynamic func myMethod() {
print("Original implementation")
}
}
let obj = MyClass()
obj.myMethod() // Вызов через динамическую диспетчеризацию
Протоколы с необязательной реализацией: Протоколы, объявленные с
@objc, могут иметь необязательные методы, которые вызываются через динамическую диспетчеризацию. Это позволяет проверять наличие метода и вызывать его только при наличии.@objc protocol MyProtocol {
@objc optional func optionalMethod()
}
class MyClass: NSObject, MyProtocol {
func optionalMethod() {
print("Optional method implementation")
}
}
let obj: MyProtocol = MyClass()
obj.optionalMethod?() // Вызов через динамическую диспетчеризацию Интерактивное взаимодействие с Objective-C API: Методы, которые взаимодействуют с Objective-C API или наследуются от классов, написанных на Objective-C, используют динамическую диспетчеризацию для вызова методов через Objective-C runtime.
import UIKit
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Этот метод вызывается через динамическую диспетчеризацию
}
}
Преимущества:
Недостатки:
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
Anonymous Quiz
3%
open
12%
public
58%
internal
27%
private
👍2