Классы и структуры имеют множество общих характеристик, но также имеют ключевые различия, которые определяют их использование в различных ситуациях.
Классы: Ссылочный тип.
Структуры: Значимый тип.
Классы: Передаются по ссылке. При присваивании переменной другого объекта, оба объекта указывают на одну и ту же область памяти.
Структуры: Передаются по значению. При присваивании переменной другой структуры, создается копия структуры.
// Класс
class PersonClass {
var name: String
init(name: String) {
self.name = name
}
}
let person1 = PersonClass(name: "Alice")
let person2 = person1
person2.name = "Bob"
print(person1.name) // "Bob" (оба объекта указывают на одну и ту же память)
// Структура
struct PersonStruct {
var name: String
}
var person3 = PersonStruct(name: "Alice")
var person4 = person3
person4.name = "Bob"
print(person3.name) // "Alice" (создана копия структуры)
Классы: Поддерживают наследование, то есть один класс может наследовать свойства и методы другого класса.
Структуры: Не поддерживают наследование.
// Класс с наследованием
class Vehicle {
var speed: Int = 0
func description() -> String {
return "Moving at \(speed) km/h"
}
}
class Car: Vehicle {
var hasSunroof: Bool = false
}
let myCar = Car()
myCar.speed = 120
myCar.hasSunroof = true
print(myCar.description()) // "Moving at 120 km/h"
Классы: Могут иметь деинициализаторы (deinitializers), которые вызываются перед освобождением экземпляра класса.
Структуры: Не имеют деинициализаторов.
class MyClass {
deinit {
print("MyClass is being deinitialized")
}
}
Классы: Используют автоматическое управление памятью с подсчетом ссылок (ARC). Объекты удаляются, когда на них больше нет сильных ссылок.
Структуры: Удаляются автоматически, когда выходят из области видимости.
Оба: Поддерживают расширения (extensions), что позволяет добавлять новые функциональности к существующим классам или структурам.
Оба: Поддерживают соответствие протоколам.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Обычно — с помощью JSONEncoder/Decoder, PropertyListEncoder, NSKeyedArchiver, в зависимости от формата. Также можно использовать Data(base64Encoded:) и String(data:encoding:).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Когда вы открываете несколько экранов (UIViewController) в iOS, они обычно создают стек представлений (View Controller Stack). В зависимости от способа открытия экранов (модально или через навигационный стек), поведение
dismiss будет разным.Если экраны открывались модально (
present), то dismiss на последнем экране просто закроет только этот экран, и управление вернётся к предыдущему. let newVC = UIViewController()
present(newVC, animated: true)
Позже вызываем:
dismiss(animated: true)
Если вызвать
dismiss на первом модально представленном контроллере, все последующие модальные контроллеры закроются сразу.// Открываем два экрана последовательно
let vc1 = UIViewController()
let vc2 = UIViewController()
present(vc1, animated: true)
vc1.present(vc2, animated: true)
Если вызвать
dismiss на vc2:vc2.dismiss(animated: true)
Если вызвать
dismiss на vc1:vc1.dismiss(animated: true)
Если экраны открывались через
UINavigationController (pushViewController), то dismiss не работает для удаления последнего экрана. Нужно использовать popViewController.let vc1 = UIViewController()
let vc2 = UIViewController()
navigationController?.pushViewController(vc1, animated: true)
navigationController?.pushViewController(vc2, animated: true)
Теперь если мы вызовем:
vc2.dismiss(animated: true)
Правильный способ закрытия последнего экрана в
UINavigationController:navigationController?.popViewController(animated: true)
Если вы хотите закрыть весь стек экранов, используйте:
navigationController?.popToRootViewController(animated: true)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
По умолчанию Operation — это одноразовая, неблокирующая, однопоточная операция, реализуемая через BlockOperation или кастомный подкласс Operation. Её тип — абстрактный базовый класс, от которого нужно наследоваться или использовать конкретные реализации (например, BlockOperation). По умолчанию операция выполняется синхронно, пока не будет помещена в OperationQueue, где она становится асинхронной.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Структуры (
struct) – это один из основных типов данных в Swift. Они значимые (value type), то есть при передаче копируются, а не передаются по ссылке. 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По умолчанию методы не могут изменять свойства структуры. Чтобы изменить их внутри метода, нужно использовать
mutatingstruct Counter {
var count = 0
mutating func increment() {
count += 1
}
}
var counter = Counter()
counter.increment()
print(counter.count) // 1Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Они определяют, насколько элемент предпочитает сохранять свой минимальный размер. Чем выше значение, тем меньше вероятность, что элемент растянется больше, чем необходимо его контенту.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
Подписку на уведомления (
NotificationCenter), KVO или Combine в жизненном цикле UIViewController лучше размещать в методах, где гарантируется её актуальность и корректное удаление. Подписка на события обычно происходит в `viewDidLoad()`, так как этот метод вызывается один раз при создании контроллера.
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`.
deinit {
NotificationCenter.default.removeObserver(self)
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
init — это конструктор, который отвечает за инициализацию объекта: присваивает значения свойствам, вызывает базовый инициализатор, устанавливает зависимости. Вызывается при создании экземпляра класса или структуры.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Stack (стек) – это структура данных, работающая по принципу LIFO (Last In, First Out – "последним пришел, первым ушел").
В Swift нет встроенного стека (кроме
Array), но можно создать свой:struct Stack<T> {
private var elements: [T] = []
mutating func push(_ item: T) {
elements.append(item)
}
mutating func pop() -> T? {
return elements.popLast() // Удаляет и возвращает верхний элемент
}
func peek() -> T? {
return elements.last // Возвращает верхний элемент без удаления
}
func isEmpty() -> Bool {
return elements.isEmpty
}
}
// Пример использования:
var stack = Stack<Int>()
stack.push(10)
stack.push(20)
stack.push(30)
print(stack.pop()!) // 30
print(stack.peek()!) // 20
print(stack.isEmpty()) // falseОбратный порядок выполнения (рекурсия) – стек вызовов функций.
Алгоритмы (обратная польская нотация, DFS – поиск в глубину)
История действий (назад-вперед в браузере, отмена в редакторе).
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
На iOS используют App Groups — механизм общего контейнера, доступного сразу для нескольких приложений одного разработчика. Также можно использовать Keychain Sharing или URL Scheme, если не требуется постоянный доступ к данным.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Объектно-ориентированное программирование (ООП) — это парадигма, основанная на концепции "объектов", которые могут содержать данные в виде полей (часто называемых атрибутами или свойствами) и код в виде процедур (часто называемых методами). ООП фокусируется на использовании объектов для моделирования реального мира (или абстракций), облегчая разработку и поддержку сложных программ. Существует четыре основных принципа:
Механизм ООП, который объединяет данные (атрибуты) и код (методы), манипулирующий этими данными, внутри одного объекта и скрывает детали реализации от внешнего использования. Это позволяет защитить внутреннее состояние объекта от прямого доступа извне и обеспечить контролируемый интерфейс для работы с этим объектом.
Позволяет создавать новый класс на основе уже существующего класса, перенимая его свойства и методы. Новый класс может добавлять собственные свойства и методы или модифицировать унаследованные. Наследование обеспечивает повторное использование кода, упрощает его расширение и поддержку.
Способность объектов с одинаковым интерфейсом предоставлять различную реализацию для одного и того же метода. Это означает, что функция или метод могут использоваться для различных типов объектов, и каждый тип может реализовать эту функцию или метод по-своему. Полиморфизм упрощает написание общего кода для работы с объектами разных классов и обеспечивает гибкость в его использовании.
Позволяет скрыть сложность системы, представляя её ключевые аспекты и скрывая детали реализации. Это достигается за счёт использования абстрактных классов и интерфейсов, которые определяют шаблон для классов-наследников. Абстракция помогает сосредоточиться на взаимодействии объектов на более высоком уровне, игнорируя ненужные детали.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это свойство ООП, при котором один и тот же интерфейс может использоваться для разных типов объектов. Один метод может вызываться у разных классов с разной реализацией.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
NSManagedObjectID – это уникальный идентификатор объекта в Core Data, который остаётся неизменным на протяжении всего жизненного цикла объекта. Используем
uriRepresentation() – это строка (URL), которая уникально идентифицирует объект. func saveObjectID(_ object: NSManagedObject) {
let objectID = object.objectID.uriRepresentation().absoluteString
UserDefaults.standard.set(objectID, forKey: "savedObjectID")
}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
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
– UIView,
– UIViewController,
– UIWindow,
– UIApplication.
Они могут обрабатывать события и передавать их по цепочке.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
В
Operation (ранее NSOperation) в Foundation есть встроенный механизм отмены, который позволяет корректно завершить операцию, если она больше не нужна. Однако отмена не прерывает выполнение автоматически – код внутри операции должен сам проверять флаг отмены и корректно завершаться. Вызывается
cancel() – операция помечается как отмененная. Флаг
isCancelled становится true, но операция продолжает выполняться, если не проверяет этот флаг. Операция должна самостоятельно проверять
isCancelled и прерываться. class MyOperation: Operation {
override func main() {
for i in 1...10 {
if isCancelled { return } // Проверяем, отменена ли операция
print("Выполняется шаг \(i)")
sleep(1) // Симуляция работы
}
}
}
let queue = OperationQueue()
let operation = MyOperation()
queue.addOperation(operation)
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
operation.cancel() // Отменяем через 3 секунды
}Если операция асинхронная (
isAsynchronous = true), просто проверять isCancelled недостаточно. Надо корректно управлять состояниями (isExecuting, isFinished).class AsyncOperation: Operation {
private var _executing = false
private var _finished = false
override var isAsynchronous: Bool { true }
override var isExecuting: Bool {
get { return _executing }
set {
willChangeValue(for: \.isExecuting)
_executing = newValue
didChangeValue(for: \.isExecuting)
}
}
override var isFinished: Bool {
get { return _finished }
set {
willChangeValue(for: \.isFinished)
_finished = newValue
didChangeValue(for: \.isFinished)
}
}
override func start() {
if isCancelled {
isFinished = true
return
}
isExecuting = true
executeTask()
}
private func executeTask() {
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
if self.isCancelled {
self.complete()
return
}
print("Асинхронная операция завершена")
self.complete()
}
}
private func complete() {
isExecuting = false
isFinished = true
}
}
let queue = OperationQueue()
let asyncOp = AsyncOperation()
queue.addOperation(asyncOp)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
asyncOp.cancel() // Отменяем через 1 секунду
}Если у вас есть зависимости между операциями, отмена одной может автоматически отменить все последующие:
let op1 = MyOperation()
let op2 = MyOperation()
op2.addDependency(op1)
let queue = OperationQueue()
queue.addOperations([op1, op2], waitUntilFinished: false)
// Отменяем первую операцию, вторая тоже не выполнится
op1.cancel()
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Даже при отсутствии вложенности, сложность может быть O(n^2), если один цикл зависит от результата работы предыдущего. Также важно, как обрабатываются данные внутри: сложные операции в теле могут значительно повлиять на производительность.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
Приложения, написанные на Swift, могут быть довольно большими по размеру.
Swift — это относительно новый язык, и его стандартная библиотека не встроена в iOS (как, например, Objective-C runtime). Это значит, что при компиляции приложения в его бинарь включаются стандартные Swift-библиотеки.
При публикации в App Store, Xcode компилирует приложение для нескольких архитектур (arm64, armv7, x86_64). Это называется Fat Binary — один исполняемый файл включает версии для разных процессоров.
С версии Swift 5.0 ABI (Application Binary Interface) стабилизирован. Это означает, что в iOS 12.2+ уже есть встроенные Swift-библиотеки.
SwiftUI и Combine — новые технологии, они не так оптимизированы, как UIKit. При их использовании код разрастается за счёт декларативного подхода и дополнительной логики от Apple.
Если приложение использует локализацию, изображения, шрифты, CoreML, ARKit, это тоже увеличивает размер .ipa.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Потокобезопасный код:
- Не вызывает крашей.
- Не вызывает конфликтов доступа.
- Защищает внутреннее состояние при параллельном использовании.
В Swift thread-safety достигается через:
- Синхронизацию (DispatchQueue, lock).
- Immutable-структуры.
- Использование actor и
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Это возможность центрального процессора (ЦПУ) или программы выполнять несколько задач (потоков) одновременно. В контексте программирования она используется для улучшения производительности приложений за счёт параллельной обработки задач. Это особенно важно для задач, требующих интенсивных вычислений, или приложений, которые должны одновременно реагировать на множество входных данных, таких как пользовательский интерфейс.
Минимальная единица обработки, которая может быть выполнена операционной системой.
Способность программы делать прогресс в нескольких задачах одновременно. Конкуренция достигается за счёт переключения между задачами.
Способность программы выполнять несколько операций одновременно, используя множество процессоров или ядер.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1