В Swift (и во многих других языках программирования) по умолчанию числовой литерал с плавающей запятой интерпретируется как `Double`, а не
Float.  Double имеет 64 бита, а Float – 32 бита. Это значит, что Double может хранить более точные значения, что особенно важно при математических вычислениях.Большинство API и стандартных библиотек Swift (например,
sin(), cos(), pow()) работают именно с Double.  Например:
let x = 3.14 // По умолчанию это Double
let y = sin(x) // sin() принимает Double
На современных 64-битных процессорах операции с
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
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Принцип абстракции и обобщения. Дженерики позволяют создавать универсальные и типобезопасные компоненты, не дублируя код для каждого типа.
Также они поддерживают принцип повторного использования и инкапсуляцию логики.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  В iOS существует несколько способов вёрстки пользовательского интерфейса. Каждый из них имеет свои плюсы и минусы в зависимости от проекта.
Используется: визуальный редактор в Xcode.
Storyboard
- Позволяет создавать весь UI в одном файле
.storyboard.- Поддерживает Auto Layout и Size Classes для адаптивного дизайна.
- Можно настраивать Segue (переходы между экранами).
Используется: Полностью программная вёрстка без использования Interface Builder.
let button = UIButton()
button.setTitle("Нажми", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
Используется: Современный способ верстки с декларативным синтаксисом.
struct ContentView: View {
    var body: some View {
        VStack {
            Text("Привет, SwiftUI!")
                .font(.largeTitle)
            Button("Нажми меня") {
                print("Кнопка нажата")
            }
        }
    }
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Witness table — механизм Swift для протоколов, в ней хранится соответствие реализаций протокольным методам.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Это абстрактная структура данных, работающая по принципу LIFO (Last In, First Out), что означает "последний пришёл — первый вышел". Это значит, что последний добавленный элемент будет первым при извлечении из стека. Под капотом реализации стека могут быть разные, и они зависят от конкретного языка программирования и задач, которые необходимо решить.
Один из самых распространённых способов реализации стека — это использование массива. В такой реализации элементы стека хранятся в массиве, и индекс последнего элемента (вершина стека) отслеживается отдельной переменной.
struct Stack<Element> {
    private var storage: [Element] = []
    mutating func push(_ element: Element) {
        storage.append(element)
    }
    mutating func pop() -> Element? {
        return storage.popLast()
    }
    func peek() -> Element? {
        return storage.last
    }
    var isEmpty: Bool {
        return storage.isEmpty
    }
}Стек можно реализовать с использованием связных списков, где каждый элемент списка содержит данные и ссылку на следующий элемент в стеке. Вершина стека в такой реализации — это начало связного списка.
class Node<Element> {
    var value: Element
    var next: Node?
    init(value: Element) {
        self.value = value
    }
}
struct Stack<Element> {
    private var head: Node<Element>?
    mutating func push(_ element: Element) {
        let node = Node(value: element)
        node.next = head
        head = node
    }
    mutating func pop() -> Element? {
        let node = head
        head = head?.next
        return node?.value
    }
    func peek() -> Element? {
        return head?.value
    }
    var isEmpty: Bool {
        return head == nil
    }
}Это системный стек, который используется во время выполнения программы для хранения информации о вызовах функций/методов. Он хранит адреса возврата, параметры функций, локальные переменные и другие данные, необходимые для управления вызовами функций и их возврата.
Обратную польскую нотацию для вычисления арифметических выражений. Управление вызовами функций в программном стеке. Поддержка операций undo в приложениях.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Pod — это библиотека или фреймворк, подключаемый через CocoaPods, менеджер зависимостей в iOS. Он автоматически загружает, компилирует и подключает сторонние библиотеки к проекту.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍1
  Forwarded from easyoffer
  
Новая фича на easyoffer – Автоотлики
Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
  Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
Это высокоуровневый механизм синхронизации, который объединяет взаимное исключение (mutex) и условные переменные (condition variables) для управления доступом к объектам в многопоточной среде.
Только один поток может выполнить защищенный блок кода в любой момент времени.
Позволяют потокам ожидать определенных условий, а другим потокам уведомлять их о наступлении этих условий.
class ThreadSafeClass {
    private var internalState = 0
    private let queue = DispatchQueue(label: "com.example.threadSafeQueue")
    
    func increment() {
        queue.sync {
            internalState += 1
        }
    }
    
    func getState() -> Int {
        return queue.sync {
            internalState
        }
    }
}С
NSLockclass ThreadSafeClass {
    private var internalState = 0
    private let lock = NSLock()
    
    func increment() {
        lock.lock()
        internalState += 1
        lock.unlock()
    }
    
    func getState() -> Int {
        lock.lock()
        let state = internalState
        lock.unlock()
        return state
    }
}С
objc_sync_enter и objc_sync_exitclass ThreadSafeClass: NSObject {
    private var internalState = 0
    
    func increment() {
        objc_sync_enter(self)
        internalState += 1
        objc_sync_exit(self)
    }
    
    func getState() -> Int {
        objc_sync_enter(self)
        let state = internalState
        objc_sync_exit(self)
        return state
    }
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Один из самых простых и гибких способов реализовать абстракцию — это использование протоколов (protocols).
Протоколы определяют набор требований (свойств, методов), не реализуя их, и позволяют легко заменять конкретные реализации в коде. Это даёт возможность:
- Заменять реализацию (например, для тестирования).
- Разделять ответственность.
- Поддерживать слабую связность компонентов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Это механизм в iOS и macOS для обмена сообщениями между различными частями приложения. Он позволяет объектам отправлять и получать уведомления без необходимости напрямую ссылаться друг на друга, что способствует более гибкому и модульному дизайну.
Любой объект может отправить уведомление с помощью Notification Center. Уведомления идентифицируются по имени (
Notification.Name). Можно передать дополнительную информацию в виде словаря (userInfo).NotificationCenter.default.post(name: .myNotification, object: nil)
Объекты могут регистрироваться для получения уведомлений с определенным именем. Для обработки уведомлений используется метод, который будет вызван при получении уведомления.
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: .myNotification, object: nil)
@objc func handleNotification(notification: Notification) {
print("Received notification")
}
Важно удалять наблюдателей, когда они больше не нужны, чтобы избежать утечек памяти. Обычно это делается в методе
deinit или перед уничтожением объекта.NotificationCenter.default.removeObserver(self, name: .myNotification, object: nil)
Объекты не нужно напрямую ссылаться друг на друга, что улучшает модульность кода.
Позволяет легко организовать обмен сообщениями между различными частями приложения.
Уведомления могут использоваться многими объектами, что облегчает реализацию функций, таких как обновление интерфейса или реагирование на события.
Когда данные изменяются, можно отправить уведомление для обновления пользовательского интерфейса.
NotificationCenter.default.post(name: .dataDidUpdate, object: nil)
Например, можно подписаться на уведомление о смене состояния сети.
NotificationCenter.default.addObserver(self, selector: #selector(handleNetworkChange), name: .reachabilityChanged, object: nil)
Различные модули приложения могут общаться друг с другом через Notification Center, не создавая сильных зависимостей.
NotificationCenter.default.post(name: .userDidLogin, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: .userDidLogin, object: nil)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍1
  Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Если вы хотите задать отступы (margins, padding) для
UIView в жизненном цикле UIViewController, то важно выбрать правильный момент, когда размеры view уже определены.  class MyViewController: UIViewController {
    let myView = UIView()
    override func viewDidLoad() {
        super.viewDidLoad()
        myView.backgroundColor = .red
        view.addSubview(myView)
    }
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        // Установка отступов (margins)
        myView.frame = view.bounds.insetBy(dx: 20, dy: 50)
    }
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Они определяют, насколько элемент предпочитает сохранять свой минимальный размер. Чем выше значение, тем меньше вероятность, что элемент растянется больше, чем необходимо его контенту.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Слабые ссылки (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
  – Обычный public класс может использоваться в другом модуле, но не может быть унаследован.
– open класс можно наследовать и переопределять даже в других модулях.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Если все переменные в коде сделать
weak, объекты могут мгновенно удаляться из памяти, потому что никто не будет владеть ими (strong reference).  -
weak создает слабую ссылку – объект не увеличивает счетчик ссылок (retain count).  - Если нет других (strong) ссылок на объект, он удаляется (ARC освобождает память).
-
weak переменные всегда являются Optional, потому что объект может стать nil в любой момент.  class Person {
    weak var name: String? // ❌ Ошибка! Строки – это value type, weak нельзя
}Проблема, если
weak используется вездеclass Car {
    weak var model: String? // ❌ Ошибка (value type)
    weak var owner: Person? // ⚠️ Будет nil, если нет других strong ссылок
}
class Person {
    var car: Car?
}
var person: Person? = Person()
person?.car = Car()
person?.car?.owner = person // ❌ `owner` - weak, объект сразу удалится
print(person?.car?.owner) // nil, объект Person уничтоженНапример, между
delegate и ViewController   protocol SomeDelegate: AnyObject {
       func doSomething()
   }
   class ViewController {
       weak var delegate: SomeDelegate? // ✅ Prevent retain cycle
   }Например, ячейки в
UITableView не должны владеть ViewController.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  1. Удобен для координации задач, выполняемых параллельно.
2. Используется для уведомления, когда все задачи завершены.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  В iOS жизненный цикл
UIViewController определяет последовательность вызовов методов, происходящих во время создания, отображения, скрытия и уничтожения контроллера.  На этом этапе создаётся экземпляр
UIViewController, но его view ещё не загружено.  - Можно переопределить
init() или init(coder:), если контроллер создаётся из Storyboard.  - Можно передавать данные через инициализатор.
class MyViewController: UIViewController {
    var titleText: String
    
    init(titleText: String) {
        self.titleText = titleText
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}Когда контроллеру нужно отобразить свой
view, вызывается loadView() (если представление создаётся программно) и viewDidLoad() (если загружается из Storyboard или XIB).  loadView() – создаёт view программно (обычно не переопределяется).  viewDidLoad() – вызывается один раз после загрузки view.  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .white
    print("viewDidLoad - View загружено в память")
}Когда
UIViewController добавляется в иерархию UIWindow и становится видимым, вызываются следующие методы:  viewWillAppear(_:) – вызывается перед появлением на экране.  viewDidAppear(_:) – вызывается после появления на экране.  viewWillDisappear(_:) – вызывается перед скрытием.  viewDidDisappear(_:) – вызывается после скрытия.  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("viewWillAppear - View скоро появится на экране")
}
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    print("viewDidAppear - View уже на экране")
}Когда
UIViewController больше не нужен, вызывается deinit(), а его view может быть выгружено с вызовом viewDidUnload() (но сейчас это редко используется).  deinit {
    print("deinit - Контроллер удалён из памяти")
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Даже если циклы не вложены, общая временная сложность функции зависит от количества операций. Если два цикла идут последовательно по одному и тому же массиву, сложность будет O(n + n) = O(n). А если по разным — и их размеры разные — то, например, O(n + m).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  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
}Сохранение в
UserDefaultslet user = User(name: "Иван", age: 25)
let defaults = UserDefaults.standard
if let encoded = try? JSONEncoder().encode(user) {
defaults.set(encoded, forKey: "user")
}
Загрузка из
UserDefaultsif 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}]
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM
  👍1
  Fetched Property — это динамическая связь, основанная на предопределённом запросе (fetch request). В отличие от обычных связей (relationship), она:
- не кешируется;
- выполняет отдельный запрос каждый раз при доступе;
- может фильтровать или выбирать связанные объекты по более сложным правилам.
Это полезно в случаях, когда нужно получить связанные данные по определённым условиям, но нужно учитывать, что производительность ниже, чем у обычной связи.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
    VIEW IN TELEGRAM