ПОП (протокольно-ориентированное программирование) — это стиль программирования, используемый в Swift, при котором поведение описывается через протоколы, а не через наследование. Ключевые аспекты: расширения (extensions), дефолтные реализации, композиция поведения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊4
Классы и структуры имеют множество общих характеристик, но также имеют ключевые различия, которые определяют их использование в различных ситуациях.
Классы: Ссылочный тип.
Структуры: Значимый тип.
Классы: Передаются по ссылке. При присваивании переменной другого объекта, оба объекта указывают на одну и ту же область памяти.
Структуры: Передаются по значению. При присваивании переменной другой структуры, создается копия структуры.
// Класс
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