Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👾5😁2
Это архитектурный шаблон, который разделяет логику приложения на три компонента: Model, View и Presenter. Несмотря на то, что SwiftUI тесно интегрирован с архитектурой MVVM (Model-View-ViewModel), можно адаптировать его для использования с MVP. В этом примере я покажу, как можно реализовать MVP со SwiftUI.
- Models
- User.swift
- Views
- UserView.swift
- Presenters
- UserPresenter.swift
Модель представляет данные и бизнес-логику. В нашем примере это будет простая структура
User. struct User {
let name: String
let age: Int
}Презентер управляет логикой представления и взаимодействует с моделью. Он обновляет представление в ответ на изменения данных.
protocol UserPresenterProtocol {
var user: User? { get }
func fetchUser()
}
class UserPresenter: ObservableObject, UserPresenterProtocol {
@Published var user: User?
func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}Представление отвечает за отображение данных и взаимодействие с пользователем. В SwiftUI представление использует
@StateObject или @ObservedObject для наблюдения за изменениями данных в презентере. import SwiftUI
struct UserView: View {
@StateObject var presenter = UserPresenter()
var body: some View {
VStack {
if let user = presenter.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
presenter.fetchUser()
}
}
}
struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}
User.swift
struct User {
let name: String
let age: Int
}UserPresenter.swift
protocol UserPresenterProtocol {
var user: User? { get }
func fetchUser()
}
class UserPresenter: ObservableObject, UserPresenterProtocol {
@Published var user: User?
func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}UserView.swift
import SwiftUI
struct UserView: View {
@StateObject var presenter = UserPresenter()
var body: some View {
VStack {
if let user = presenter.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
presenter.fetchUser()
}
}
}
struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👀1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6🤯1
Synchronized в программировании используется для управления доступом к ресурсам в многопоточном окружении, чтобы предотвратить состояние гонки (race condition). В контексте iOS и Swift, Synchronized гарантирует, что только один поток может выполнять определенный блок кода в любой момент времени.В данном примере,
NSLock используется для синхронизации доступа к переменной internalState. Метод increment() увеличивает значение переменной на единицу, и блок lock/unlock гарантирует, что этот код выполнится атомарно, то есть только один поток сможет его выполнять в один момент времени. Тоже самое относится к методу getState(), который возвращает текущее значение переменной.class 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
}
}В этом примере
DispatchQueue с атрибутом sync используется для обеспечения того, что блок кода внутри будет выполнен синхронно, то есть только один поток сможет выполнить его в данный момент времени.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
}
}
}Здесь
objc_sync_enter(self) и objc_sync_exit(self) обеспечивают блокировку и разблокировку доступа к ресурсу.class 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
❤1
Статические инициализаторы (`static`) выполняются один раз при загрузке класса и инициализируют статические переменные.
Нестатические инициализаторы выполняются при создании каждого экземпляра класса и используются для инициализации нестатических переменных.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Использование наследования может привести к жесткой связности и сложностям в поддержке кода. Альтернативы наследованию: композиция, протоколы (интерфейсы), расширения (extensions) и делегирование. Эти подходы обеспечивают большую гибкость и модульность.
Композиция включает объекты других классов как поля и делегирует им работу, что позволяет гибко изменять поведение во время выполнения.
protocol Engine {
func start()
}
class Car {
private let engine: Engine
init(engine: Engine) {
self.engine = engine
}
func start() {
engine.start()
}
}
class ElectricEngine: Engine {
func start() {
print("Electric engine starting...")
}
}
class GasolineEngine: Engine {
func start() {
print("Gasoline engine starting...")
}
}
let electricCar = Car(engine: ElectricEngine())
let gasolineCar = Car(engine: GasolineEngine())
electricCar.start()
gasolineCar.start()Протоколы определяют набор методов и свойств, которые класс или структура должны реализовать, обеспечивая гибкость и переиспользуемость компонентов.
protocol Drawable {
func draw()
}
class Circle: Drawable {
func draw() {
print("Drawing a circle")
}
}
class Square: Drawable {
func draw() {
print("Drawing a square")
}
}
func render(drawable: Drawable) {
drawable.draw()
}
let shapes: [Drawable] = [Circle(), Square()]
shapes.forEach { render(drawable: $0) }Расширения добавляют новые методы и свойства к существующим классам, структурам или перечислениям без изменения исходного кода.
extension String {
func reverse() -> String {
return String(self.reversed())
}
}
let original = "hello"
let reversed = original.reverse()
print(reversed) // "olleh"Делегирование передает ответственность за выполнение задач другому объекту, создавая гибкие и переиспользуемые компоненты.
protocol PrinterDelegate: AnyObject {
func printerDidFinishPrinting(_ printer: Printer)
}
class Printer {
weak var delegate: PrinterDelegate?
func printDocument() {
print("Printing document...")
delegate?.printerDidFinishPrinting(self)
}
}
class PrintManager: PrinterDelegate {
func printerDidFinishPrinting(_ printer: Printer) {
print("Document printing completed.")
}
}
let printer = Printer()
let manager = PrintManager()
printer.delegate = manager
printer.printDocument()Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
Reference type (ссылочный тип) хранит ссылку на область памяти, где находятся данные, и при копировании копируется только ссылка, а не сами данные. Например, объекты классов разделяют одну и ту же память.
Разница проявляется при изменении данных: value type остаётся неизменным в копиях, а reference type отражает изменения во всех ссылках.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В объектно-ориентированном программировании классы могут выполнять различные роли в зависимости от их назначения и использования. Классы, условно названные
User и Data, могут иметь существенные различия в своей реализации и предназначении. Класс
User обычно представляет сущность пользователя в системе. Он может включать свойства и методы, специфичные для пользователя, такие как идентификатор, имя, адрес электронной почты и методы для управления этими данными.class User {
var id: Int
var name: String
var email: String
init(id: Int, name: String, email: String) {
self.id = id
self.name = name
self.email = email
}
func updateEmail(newEmail: String) {
self.email = newEmail
}
}Класс
Data чаще всего используется для представления необработанных данных или байтов. В Swift, например, Data — это структура из Foundation, которая предоставляет интерфейс для работы с бинарными данными.import Foundation
let string = "Hello, World!"
if let data = string.data(using: .utf8) {
// Преобразование строки в Data
print(data)
}
let jsonString = "{\"name\": \"John\", \"age\": 30}"
if let jsonData = jsonString.data(using: .utf8) {
// Преобразование JSON-строки в Data
do {
if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
print(jsonObject)
}
} catch {
print("Ошибка парсинга JSON: \(error)")
}
}
User: Представляет конкретную сущность пользователя в системе. Используется для управления и хранения данных о пользователе.
Data: Представляет необработанные данные или байты. Используется для операций с бинарными данными, таких как чтение и запись файлов, сетевые операции и сериализация.
User: Обычно содержит несколько свойств, специфичных для пользователя, и методы для управления этими данными.
Data: Является универсальным контейнером для байтов, предоставляя методы для работы с этими данными.
User: Включен в бизнес-логику, тесно связан с функциональностью приложения, связанной с пользователями.
Data: Используется для низкоуровневых операций с данными, часто не связан напрямую с бизнес-логикой.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1😁1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу Знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Приложения на Swift могут быть массивными из-за нескольких факторов:
Включает много функций и структур данных, что увеличивает размер бинарного файла.
Современные приложения часто используют множество внешних библиотек и фреймворков, добавляющих объем.
Компиляция для разных архитектур (например, arm64, x86_64) увеличивает размер исполняемого файла.
Большое количество изображений, видео и аудиофайлов увеличивают размер приложения.
Включение символов отладки для разработки и анализа сбоев добавляет объем.
Статические библиотеки увеличивают размер исполняемого файла по сравнению с динамическими.
Поддержка старых версий iOS требует включения дополнительных библиотек и кода.
Использование инструментов для удаления лишних архитектур из финальной сборки.
Сжатие изображений и видео, использование эффективных форматов.
Исключение символов отладки в релизной сборке.
Использование динамических библиотек для уменьшения размера основного исполняемого файла.
Удаление неиспользуемого кода и зависимостей.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
PO вызывает методы description или debugDescription, которые могут изменять состояние объекта.Тяжелые вычисления в методах
description или debugDescription могут замедлить отладку.Доступ к объекту в многопоточной среде может привести к состоянию гонки.
Ошибки в методах
description или debugDescription могут привести к сбоям при использовании PO.Методы, использующие блокировки, могут привести к зависанию отладчика.
Побочные эффекты
class DangerousObject {
var counter = 0
var description: String {
counter += 1 // Изменение состояния
return "Counter: \(counter)"
}
}Производительность
class HeavyObject {
var description: String {
let result = (0..<1_000_000).map { $0 * $0 }.reduce(0, +)
return "Result: \(result)"
}
}Проблемы с потоками
class ThreadUnsafeObject {
var data = [Int]()
var description: String {
return "Data count: \(data.count)"
}
}Краш приложения
class CrashObject {
var description: String {
fatalError("Should not be called")
}
}Зависания
class LockObject {
let lock = NSLock()
var description: String {
lock.lock()
defer { lock.unlock() }
return "Locked"
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это текстовый протокол для общения в реальном времени. Он позволяет пользователям обмениваться сообщениями в каналах (чат-румах) или через личные сообщения.
Объединяют пользователей для обсуждения общих тем.
Прямой обмен сообщениями между пользователями.
Поддерживают несколько каналов и управляют соединениями пользователей.
Программы, используемые для подключения к IRC-серверам и участия в чатах.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Механизм синхронизации
Synchronized под капотом обеспечивает контроль доступа к критическим секциям кода в многопоточных приложениях, предотвращая состояние гонки и гарантируя, что только один поток в данный момент времени имеет доступ к определенному ресурсу.Различные механизмы синхронизации реализуют
Synchronized по-разному, но общая идея заключается в использовании блокировок (локов), чтобы обеспечить эксклюзивный доступ к ресурсу.Это простая блокировка, предоставляемая Foundation framework в Swift:
class 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
}
}DispatchQueue позволяет организовать выполнение кода в синхронном или асинхронном режиме. 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
}
}
}Эти функции используются для синхронизации в Objective-C и могут быть использованы в Swift.
class 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
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Выделения в программировании касаются процессов управления памятью, когда память выделяется (аллоцируется) и освобождается (деаллоцируется) для использования программой. В современных языках программирования эти процессы могут быть управляемыми вручную или автоматически.
Статическая аллокация: Память выделяется во время компиляции и существует на протяжении всего времени выполнения программы. Используется для глобальных и статических переменных.
int globalVar = 10; // Статическая память
Стековая аллокация: Память выделяется при вызове функции и освобождается при выходе из функции. Используется для локальных переменных.
void function() {
int localVar = 20; // Стековая память
}Куча (динамическая аллокация): Память выделяется по запросу во время выполнения программы и освобождается вручную (в языках с ручным управлением памятью) или автоматически (в языках с автоматическим управлением памятью, например, через сборщик мусора).
int *ptr = (int*)malloc(sizeof(int) * 10); // Выделение памяти в куче
free(ptr); // Освобождение памяти
Вручную: Программист отвечает за освобождение памяти, выделенной в куче.
free(ptr);
Автоматически: Сборщик мусора (Garbage Collector) автоматически освобождает память, которая больше не используется.
// В Java нет необходимости освобождать память вручную.
C/C++ (ручное управление памятью):
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int*)malloc(sizeof(int) * 5); // Выделение памяти
if (arr == NULL) {
// Ошибка выделения памяти
return 1;
}
// Использование массива
for (int i = 0; i < 5; i++) {
arr[i] = i;
}
// Освобождение памяти
free(arr);
return 0;
}
Python (автоматическое управление памятью):
def create_list():
my_list = [i for i in range(5)] # Выделение памяти автоматически
return my_list # Память освобождается автоматически, когда объект больше не используется
my_list = create_list()
print(my_list)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1🤔1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
Это система документирования, которая используется для описания кода на языке JavaScript. Она позволяет разработчикам комментировать свой код специальными метками и описаниями, что облегчает его понимание и поддержку. Одной из самых популярных систем документирования в JavaScript является JSDoc.
JSDoc позволяет автоматически создавать HTML-документацию из аннотированных комментариев в коде.
JSDoc позволяет описывать типы данных параметров и возвращаемых значений функций.
JSDoc используется для документирования всех аспектов кода, включая функции, методы, классы и модули.
/**
* Adds two numbers together.
* @param {number} a - The first number.
* @param {number} b - The second number.
* @returns {number} The sum of the two numbers.
*/
function add(a, b) {
return a + b;
}
/**
* Represents a person.
* @class
*/
class Person {
/**
* Creates a person.
* @param {string} name - The name of the person.
* @param {number} age - The age of the person.
*/
constructor(name, age) {
this.name = name;
this.age = age;
}
/**
* Greets someone.
* @param {string} [greetName='Stranger'] - The name of the person to greet.
* @returns {string} The greeting message.
*/
greet(greetName = 'Stranger') {
return `Hello, ${greetName}! My name is ${this.name}.`;
}
}
@param — Описание параметров функции.@returns — Описание возвращаемого значения функции.@class — Описание класса.@constructor — Описание конструктора класса.@typedef — Описание типа данных.Комментарии JSDoc помогают другим разработчикам быстрее понять структуру и назначение кода.
Генерация документации упрощает поддержание актуальности документации и кода.
Некоторые инструменты могут использовать JSDoc для улучшения статического анализа кода, предоставляя более точные подсказки и проверки типов.
Для генерации документации с использованием JSDoc требуется установить и использовать инструмент командной строки JSDoc.
npm install -g jsdoc
jsdoc yourJavaScriptFile.js
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔4❤1