Цена за 48 часов в ленте | 1750,00 |
Цена за 1 час закрепления | N/A |
Взаимопиар | Нет |
stack
) — это структура данных и область памяти, используемая для хранения временных данных. В зависимости от контекста, стек может существовать в нескольких местах.func functionA() {
functionB()
}
func functionB() {
print("Вызов B")
}
functionA()
func infiniteRecursion() {
infiniteRecursion() // ❌ Бесконечный вызов
}
Array
).struct Stack {
private var elements: [T] = []
mutating func push(_ item: T) {
elements.append(item)
}
mutating func pop() -> T? {
return elements.popLast()
}
}
var stack = Stack()
stack.push(10)
stack.push(20)
print(stack.pop()!) // 20
Thread
) в многопоточном программировании получает свой стек.DispatchQueue.global().async {
print("Фоновый поток")
}
print("Главный поток")
func createPerson() {
let person = "Иван" // Создаётся в стеке
print(person)
}
createPerson() // Переменная person удаляется при выходе из функции
memory leak
) – это ситуация, когда память остаётся выделенной, но больше не используется программой и не освобождается. class Person {
var pet: Pet?
deinit { print("Person удалён") }
}
class Pet {
var owner: Person?
deinit { print("Pet удалён") }
}
var person: Person? = Person()
var pet: Pet? = Pet()
person?.pet = pet
pet?.owner = person
person = nil
pet = nil
weak
) или безвладельческие (unowned
) ссылки не увеличивают счётчик ссылок, что разрывает цикл.class Person {
var pet: Pet?
deinit { print("Person удалён") }
}
class Pet {
weak var owner: Person? // Слабая ссылка
deinit { print("Pet удалён") }
}
var person: Person? = Person()
var pet: Pet? = Pet()
person?.pet = pet
pet?.owner = person
person = nil // "Person удалён"
pet = nil // "Pet удалён"
unowned
похож на weak
, но он не может быть `nil`.class Owner {
var car: Car?
deinit { print("Owner удалён") }
}
class Car {
unowned var owner: Owner // Безвладельческая ссылка
init(owner: Owner) { self.owner = owner }
deinit { print("Car удалён") }
}
var owner: Owner? = Owner()
owner?.car = Car(owner: owner!)
owner = nil // "Owner удалён", "Car удалён"
self
удерживается замыканиемclass ViewController {
var closure: (() -> Void)?
func setup() {
closure = {
print(self) // Удерживает self, создавая цикл!
}
}
deinit { print("ViewController удалён") }
}
var vc: ViewController? = ViewController()
vc?.setup()
vc = nil // ❌ "ViewController" НЕ удалится
Xcode > Product > Profile
. Leaks
. deinit
не вызывается – значит, объект утёк в память.class Test {
deinit { print("Test удалён") }
}
var obj: Test? = Test()
obj = nil // Должно напечатать "Test удалён"
NotificationCenter
), KVO
или Combine
в жизненном цикле UIViewController
лучше размещать в методах, где гарантируется её актуальность и корректное удаление. override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(handleNotification),
name: .someNotification,
object: nil
)
}
@objc func handleNotification(_ notification: Notification) {
print("Получено уведомление")
}
viewWillAppear()
.var cancellable: AnyCancellable?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
cancellable = NotificationCenter.default.publisher(for: .someNotification)
.sink { _ in
print("Событие получено")
}
}
NotificationCenter
:override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: .someNotification, object: nil)
}
Combine
подписки (cancellable
)override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
cancellable?.cancel()
cancellable = nil
}
deinit {
NotificationCenter.default.removeObserver(self)
}
Float
. Double
имеет 64 бита, а Float
– 32 бита. Это значит, что Double
может хранить более точные значения, что особенно важно при математических вычислениях.sin()
, cos()
, pow()
) работают именно с Double
. let x = 3.14 // По умолчанию это Double
let y = sin(x) // sin() принимает Double
Double
выполняются так же быстро или даже быстрее, чем с Float
, из-за оптимизаций в аппаратном обеспечении.Float
может округлять числа с потерей точности, что может привести к неожиданным результатам. Float
:let a: Float = 0.1 + 0.2
print(a == 0.3) // false 😱
Float
, надо указать это явно:let number: Float = 3.14
let number = 3.14 as Float
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
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
}
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}]
}