Swift | Вопросы собесов
2.13K subscribers
28 photos
949 links
Download Telegram
🤔 Может быть асинхронность без многопоточности?

Да, это два разных концепта, и асинхронные операции могут быть выполнены без использования многопоточности.

🚩Асинхронность

Относится к возможности выполнения операций, не блокируя выполнение других операций. В асинхронном программировании вы можете начать операцию, которая выполняется в фоновом режиме, и продолжить выполнение других задач, не дожидаясь завершения этой операции.

🚩Многопоточность

Предполагает выполнение нескольких потоков параллельно. Поток (thread) — это наименьшая единица обработки, которую операционная система может управлять независимо. Многопоточность используется для выполнения нескольких операций одновременно, что может улучшить производительность на многоядерных процессорах.

🚩Асинхронность без многопоточности

Операции могут быть реализованы без создания дополнительных потоков. Вместо этого, они могут использовать механизм, называемый кооперативной многозадачностью, где выполнение задач управляется посредством событийного цикла (event loop).

🟠JavaScript и Node.js
JavaScript в браузере и Node.js используют одно поточный событийный цикл для управления асинхронными операциями. Операции, такие как сетевые запросы или таймеры, выполняются асинхронно, но они не требуют создания дополнительных потоков.
console.log("Start");

setTimeout(() => {
console.log("Timeout callback");
}, 1000);

console.log("End");

// Output:
// Start
// End
// Timeout callback (после 1 секунды)


🟠Dispatch Queues в GCD (Grand Central Dispatch)
В iOS, DispatchQueue.main.async позволяет выполнять код асинхронно на главной очереди без создания нового потока. Это часто используется для обновления пользовательского интерфейса.
DispatchQueue.main.async {
// Этот код выполняется асинхронно на главной очереди
print("Async task on main queue")
}


🚩Как работает

Асинхронные операции могут быть выполнены с использованием событийного цикла (event loop), который непрерывно проверяет наличие событий (таких как завершение асинхронных задач) и вызывает соответствующие обработчики событий. В этом случае, хотя операции выполняются асинхронно, они обрабатываются последовательно в контексте одного потока.

🚩Плюсы и минусы

Меньшая сложность
Нет необходимости в управлении несколькими потоками и синхронизации доступа к общим ресурсам.
Меньшие накладные расходы
Отсутствие переключения контекста между потоками может улучшить производительность.
Ограниченная параллелизация
Только одна операция может выполняться в каждый момент времени в одном потоке, что может быть ограничением на многоядерных системах.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
3
🤔 Какие типы коллекций существуют в Swift?

В Swift есть три основных типа коллекций: массивы (Array), множества (Set) и словари (Dictionary). Массивы хранят элементы в порядке вставки и поддерживают доступ по индексу. Множества — это неупорядоченные коллекции уникальных элементов. Словари — это коллекции, которые хранят пары ключ-значение, где каждый ключ уникален, а значения могут быть любыми типами. Все эти коллекции в Swift поддерживают обобщённые типы, что делает их гибкими для работы с любыми данными.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Обязательно ли асинхронность и многопоточность следуют друг за другом или это раздельные понятия?

Это раздельные понятия, хотя их можно использовать вместе. Асинхронность связана с выполнением задач без блокировки основного потока, когда результат операции может быть обработан позже, что особенно полезно при работе с вводом-выводом. Многопоточность же подразумевает параллельное выполнение задач в нескольких потоках, что позволяет использовать ресурсы процессора более эффективно. Асинхронные операции могут выполняться в одном потоке, тогда как многопоточность обычно задействует несколько потоков одновременно.

🚩Асинхронность

Относится к выполнению операций, которые позволяют программе продолжать работать, не дожидаясь завершения этих операций. Асинхронные операции могут быть выполнены без блокировки основного потока, что повышает отзывчивость приложения.
Пример: Отправка сетевого запроса и ожидание ответа. Программа может продолжить выполнение других задач, пока ждет ответа от сервера.

🚩Многопоточность

Многопоточность предполагает выполнение нескольких потоков параллельно. Это позволяет использовать несколько ядер процессора для выполнения задач одновременно, что может повысить производительность.
Пример: Распараллеливание вычислений для ускорения обработки данных.

🚩Взаимосвязь и независимость

🟠Асинхронность без многопоточности
Асинхронные операции могут быть выполнены без создания дополнительных потоков. Например, JavaScript и Node.js используют одно поточный событийный цикл для управления асинхронными операциями. В этом примере setTimeout выполняет асинхронную операцию в одном потоке.
console.log("Start");

setTimeout(() => {
console.log("Timeout callback");
}, 1000);

console.log("End");


🟠Многопоточность без асинхронности
Многопоточность может использоваться для выполнения нескольких задач параллельно без необходимости в асинхронности. Например, выполнение вычислительных задач в нескольких потоках без ожидания завершения других задач. В этом примере два потока выполняются параллельно, но операции не являются асинхронными.
let queue1 = DispatchQueue(label: "queue1", qos: .userInitiated)
let queue2 = DispatchQueue(label: "queue2", qos: .userInitiated)

queue1.sync {
for i in 0..<5 {
print("Task 1 - \(i)")
}
}

queue2.sync {
for i in 0..<5 {
print("Task 2 - \(i)")
}
}


🟠Асинхронность с многопоточностью
Асинхронные операции могут быть выполнены в разных потоках для повышения производительности. Например, асинхронная загрузка данных в фоновом потоке, чтобы не блокировать основной поток пользовательского интерфейса. В этом примере данные загружаются асинхронно в фоновом потоке, а затем результат обновляется в основном потоке.
DispatchQueue.global(qos: .background).async {
// Выполнение фоновой задачи
let data = loadData()
DispatchQueue.main.async {
// Обновление UI после завершения фоновой задачи
updateUI(with: data)
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🤔 Что такое асинхронная задача?

Асинхронная задача (async task) в Swift — это операция, которая выполняется в фоновом режиме, не блокируя основной поток исполнения. Асинхронные задачи позволяют продолжать выполнение программы, пока задача выполняется, и обрабатывать результат позже. В Swift 5.5 и позже используется ключевое слово `async/await` для упрощения работы с асинхронными операциями, что делает код более читаемым и управляемым. Асинхронные задачи полезны для операций, таких как сетевые запросы или работа с файлами.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Почему Viper это "боль"?

Это архитектурный шаблон для iOS-приложений, который обещает улучшить разбиение кода на модули и упростить тестирование. Однако, несмотря на свои преимущества, VIPER может быть воспринят как "боль" по ряду причин.

🟠Сложность структуры и разбиение на множество компонентов
VIPER разделяет логику приложения на пять отдельных компонентов, что может привести к значительному увеличению количества файлов и сложности структуры проекта. Для одного экрана в приложении могут понадобиться следующие файлы: View, Interactor, Presenter, Entity, Router.
Это значит, что для каждого экрана нужно создавать и поддерживать пять отдельных файлов, что может быстро привести к перегрузке проекта большим количеством файлов.

🟠Повышенные требования к пониманию шаблона
VIPER требует глубокого понимания каждого из компонентов и их ролей. Новичкам или разработчикам, не знакомым с этим шаблоном, может потребоваться значительное время, чтобы понять и эффективно использовать VIPER.

🟠Большой объем шаблонного кода
VIPER требует написания большого количества шаблонного кода, особенно для создания связей между компонентами. Это может привести к усталости разработчика и увеличению времени разработки. Этот шаблонный код нужно будет повторять для каждого модуля, что может быть утомительным и трудоемким.
protocol SomeModuleViewProtocol: AnyObject {
var presenter: SomeModulePresenterProtocol? { get set }
}

protocol SomeModuleInteractorProtocol: AnyObject {
var presenter: SomeModulePresenterProtocol? { get set }
}

protocol SomeModulePresenterProtocol: AnyObject {
var view: SomeModuleViewProtocol? { get set }
var interactor: SomeModuleInteractorProtocol? { get set }
var router: SomeModuleRouterProtocol? { get set }
}

protocol SomeModuleRouterProtocol: AnyObject {
static func createModule() -> SomeModuleViewProtocol
}


🟠Сложность в навигации и связи между компонентами
Так как компоненты VIPER сильно разделены, это может усложнить навигацию и отладку кода. Переход от одного компонента к другому может потребовать больше времени и усилий.

🟠Перегруженность проекта
Когда проект растет, количество VIPER-модулей может стать огромным. Это может сделать проект перегруженным и сложным для управления, особенно в крупных командах.

🚩Плюсы

Разделение ответственности
Каждый компонент имеет свою четко определенную роль.
Тестируемость
Модули VIPER легко тестировать из-за их четкой структуры и разделения.
Модульность
Легче переиспользовать и обновлять компоненты.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Что такое диспетчеризация?

Диспетчеризация (dispatch) в Swift — это механизм, который управляет выполнением задач в многопоточном окружении, распределяя задачи между различными потоками. В Swift используется Grand Central Dispatch (GCD) для асинхронного и синхронного выполнения задач на разных очередях. Диспетчеризация позволяет эффективно управлять ресурсами процессора и улучшать производительность программ. Она также обеспечивает простоту в работе с многопоточностью, минимизируя возможность ошибок при синхронизации.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯6
🤔 Можно как то выполнить одновременные задачи?

Да, есть несколько способов для выполнения задач параллельно или одновременно. Это может повысить производительность вашего приложения, особенно если вы выполняете независимые задачи, такие как загрузка данных, обработка изображений или выполнение сетевых запросов.

🚩Методы

🟠Grand Central Dispatch (GCD)
Предоставляет низкоуровневый интерфейс для управления параллельными задачами, используя глобальные или пользовательские конкурентные очереди.
DispatchQueue.global(qos: .userInitiated).async {
// Первая задача
performFirstTask()
}

DispatchQueue.global(qos: .userInitiated).async {
// Вторая задача
performSecondTask()
}


🟠OperationQueue
Это более высокоуровневый интерфейс для управления параллельными задачами с возможностью задания зависимостей и приоритетов.
let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 2 // Устанавливаем количество одновременно выполняемых задач

let operation1 = BlockOperation {
performFirstTask()
}

let operation2 = BlockOperation {
performSecondTask()
}

operationQueue.addOperations([operation1, operation2], waitUntilFinished: false)


🟠Dispatch Group
Позволяет группировать несколько асинхронных задач и уведомлять, когда все задачи в группе завершены.
let dispatchGroup = DispatchGroup()

DispatchQueue.global(qos: .userInitiated).async(group: dispatchGroup) {
// Первая задача
performFirstTask()
}

DispatchQueue.global(qos: .userInitiated).async(group: dispatchGroup) {
// Вторая задача
performSecondTask()
}

dispatchGroup.notify(queue: .main) {
// Все задачи завершены
updateUI()
}


🟠Combine
Это фреймворк для реактивного программирования, который позволяет работать с асинхронными потоками данных и выполнять задачи параллельно.
import Combine

let publisher1 = Just("Task 1").delay(for: 2.0, scheduler: DispatchQueue.global())
let publisher2 = Just("Task 2").delay(for: 2.0, scheduler: DispatchQueue.global())

Publishers.Zip(publisher1, publisher2)
.receive(on: DispatchQueue.main)
.sink { task1, task2 in
print("Both tasks completed: \(task1), \(task2)")
}
.store(in: &cancellables)


🟠URLSession для параллельных сетевых запросов
Автоматически управляет параллельным выполнением сетевых запросов.
let url1 = URL(string: "https://example.com/data1")!
let url2 = URL(string: "https://example.com/data2")!

let task1 = URLSession.shared.dataTask(with: url1) { data, response, error in
// Обработка первого ответа
}

let task2 = URLSession.shared.dataTask(with: url2) { data, response, error in
// Обработка второго ответа
}

task1.resume()
task2.resume()


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Что такое ассоциированный тип (associated type)?

Ассоциированный тип (associated type) в Swift используется в протоколах для определения типа, который должен быть конкретизирован при реализации протокола. Это позволяет создавать протоколы, которые могут работать с разными типами данных, сохраняя при этом гибкость. Ассоциированные типы играют важную роль при создании обобщённых протоколов. Это позволяет писать код, который может адаптироваться под различные типы, не привязываясь к конкретной реализации.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2
🤔 Зачем делить код?

🟠Улучшение читаемости и поддерживаемости кода
Разделение кода на модули позволяет разработчикам легче понимать и навигировать по коду. Когда код структурирован и разбит на логически связанные части, его проще читать и поддерживать.

🚩Пример

🟠Разделение функций в отдельные файлы и классы
View: Отвечает за отображение данных и взаимодействие с пользователем.
Model: Содержит бизнес-логику и данные.
Controller/Presenter/Interactor: Управляет взаимодействием между View и Model.

🟠Повышение модульности и переиспользования кода
Когда код разбит на отдельные модули, каждый модуль может быть использован повторно в разных частях приложения или даже в разных проектах. Это способствует созданию более модульных и переиспользуемых компонентов.

🟠Облегчение тестирования
Разделение кода на модули упрощает написание и проведение тестов. Модульный код легче тестировать изолированно, что позволяет находить и исправлять ошибки быстрее и эффективнее.

Модульный код
class DataService {
func fetchData() -> [String] {
// Логика получения данных
}
}

class ViewModel {
let dataService: DataService

init(dataService: DataService) {
self.dataService = dataService
}

func getData() -> [String] {
return dataService.fetchData()
}
}


Тест
func testFetchData() {
let dataService = MockDataService()
let viewModel = ViewModel(dataService: dataService)
let data = viewModel.getData()
XCTAssertEqual(data, ["MockData1", "MockData2"])
}


🟠Упрощение работы в команде
Когда код структурирован и разбит на модули, разные члены команды могут работать над разными частями проекта одновременно, не мешая друг другу. Это способствует параллельной разработке и уменьшает конфликты слияния (merge conflicts).

🟠Снижение сложности
Разделение кода на более мелкие, управляемые части помогает снизить общую сложность системы. Каждый модуль решает одну конкретную задачу, что делает систему более понятной и управляемой.

🟠Принципы SOLID
Разделение кода помогает следовать принципам SOLID:
S ingle Responsibility Principle (Принцип единственной ответственности): Каждый модуль отвечает за одну конкретную задачу.
O pen/Closed Principle (Принцип открытости/закрытости): Модули открыты для расширения, но закрыты для модификации.
L iskov Substitution Principle (Принцип подстановки Лисков): Модули можно заменить другими, не нарушая работу системы.
I nterface Segregation Principle (Принцип разделения интерфейсов): Избегайте создания "толстых" интерфейсов; предпочтительно иметь несколько специализированных интерфейсов.
D ependency Inversion Principle (Принцип инверсии зависимостей): Модули зависят от абстракций, а не от конкретных реализаций.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Что такое "Опционалы"?

Опционалы в Swift — это тип данных, который позволяет переменной содержать либо значение, либо `nil`, указывающее на отсутствие значения. Опционалы объявляются с использованием знака вопроса (`?`), и для безопасного извлечения значения из опционала нужно его "развернуть" с помощью оператора `!` или безопасно использовать через условное приведение (`if let` или `guard let`). Опционалы помогают избежать ошибок, связанных с доступом к переменным, которые не содержат значений, и делают код безопаснее.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Какую проблему решает реактивное программирование?

🟠Управление асинхронностью
Реактивное программирование упрощает координацию асинхронных операций, избегая "callback hell".
До:
fetchData { data in
process(data) { processedData in
save(processedData) { success in
print("Data saved: \(success)")
}
}
}


После:
fetchData()
.flatMap { process($0) }
.flatMap { save($0) }
.subscribe(onNext: { success in
print("Data saved: \(success)")
})


🟠Обработка событий и управление состоянием
Обеспечивает простое и автоматическое обновление UI при изменении данных.
data.asObservable()
.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { index, model, cell in
cell.textLabel?.text = model
}
.disposed(by: disposeBag)


🟠Композиция и повторное использование кода
Позволяет легко объединять данные из разных источников.
Observable.zip(loadUser(), loadPosts())
.subscribe(onNext: { user, posts in
display(posts)
})


🟠Управление ошибками
Централизованная обработка ошибок в асинхронных цепочках.
fetchData()
.flatMap { process($0) }
.flatMap { save($0) }
.subscribe(onNext: { success in
print("Data saved: \(success)")
}, onError: { error in
print("Error: \(error)")
})


🟠Реактивные пользовательские интерфейсы
Автоматическая привязка данных к элементам UI.
usernameObservable
.bind(to: usernameLabel.rx.text)
.disposed(by: disposeBag)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Что такое многопоточность?

Многопоточность — это возможность выполнения нескольких задач одновременно в разных потоках, что позволяет программам эффективно использовать ресурсы процессора. В Swift многопоточность реализуется с помощью GCD (Grand Central Dispatch) и NSOperationQueue, которые позволяют управлять параллельным выполнением задач. Многопоточность используется для разделения вычислительно затратных операций на несколько потоков, чтобы не блокировать основной поток интерфейса пользователя. Это улучшает производительность и отзывчивость приложений.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Почему плохо загружать главный поток и какие есть способы этого не делать?

Главный поток отвечает за обновление пользовательского интерфейса (UI) и обработку взаимодействия с пользователем. Если этот поток блокируется, приложение может стать неотзывчивым, что вызывает задержки в интерфейсе или даже его полную заморозку.

🚩Проблемы при загрузке

🟠Замораживание интерфейса
Если главный поток занят выполнением длительных операций, UI не будет обновляться, что приведет к замораживанию или задержке интерфейса.
🟠Плохой пользовательский опыт
Задержки и лаги при взаимодействии с приложением вызывают неудовлетворенность пользователей и могут привести к негативным отзывам.
🟠Возможные аварийные завершения
Длительная блокировка главного потока может привести к тому, что система iOS решит завершить приложение, считая его неотзывчивым.

🚩Способы предотвращения загрузки

🟠Использование Grand Central Dispatch (GCD)
GCD предоставляет простой способ выполнения асинхронных задач в фоновом режиме.
DispatchQueue.global(qos: .background).async {
// Длительная задача
let result = performHeavyComputation()

DispatchQueue.main.async {
// Обновление UI с результатом
updateUI(with: result)
}
}


🟠OperationQueue
OperationQueue предлагает более высокоуровневый интерфейс для управления асинхронными задачами с возможностью задания приоритетов и зависимостей.
let backgroundQueue = OperationQueue()
backgroundQueue.addOperation {
// Длительная задача
let result = performHeavyComputation()

OperationQueue.main.addOperation {
// Обновление UI с результатом
updateUI(with: result)
}
}


🟠URLSession для сетевых запросов
URLSession автоматически выполняет сетевые запросы в фоновом режиме.
let url = URL(string: "https://example.com/data")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
// Обработка данных

DispatchQueue.main.async {
// Обновление UI
updateUI(with: data)
}
}
task.resume()


🟠Core Data
Для выполнения запросов к базе данных можно использовать фоновые контексты (background contexts).
let backgroundContext = persistentContainer.newBackgroundContext()
backgroundContext.perform {
let fetchRequest: NSFetchRequest<Entity> = Entity.fetchRequest()
let results = try? backgroundContext.fetch(fetchRequest)

DispatchQueue.main.async {
// Обновление UI с результатами
updateUI(with: results)
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как решить проблему race condition?

Race condition — это ошибка, возникающая при одновременном доступе нескольких потоков к одним и тем же данным без должной синхронизации. Для решения проблемы race condition в Swift используются механизмы синхронизации, такие как блокировки (locks), семафоры или серийные очереди GCD. Эти инструменты позволяют ограничить доступ к общим ресурсам, чтобы только один поток мог их изменять в любой момент времени. Это предотвращает непредсказуемое поведение программы и ошибки при многопоточном доступе к данным.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Почему нельзя записать пример ячейки?

Может быть сложным для реализации из-за необходимости создания множества компонентов даже для простых задач.

🚩Пример реализации ячейки

Создание пользовательской ячейки
import UIKit

class CustomTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!

func configure(with text: String) {
titleLabel.text = text
}
}


View
import UIKit

protocol TableViewProtocol: AnyObject {
func updateTableView()
}

class TableViewController: UIViewController, TableViewProtocol {
@IBOutlet weak var tableView: UITableView!
var presenter: TableViewPresenterProtocol?

override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
presenter?.viewDidLoad()
}

func updateTableView() {
tableView.reloadData()
}
}

extension TableViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return presenter?.numberOfRows() ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
if let text = presenter?.textForRow(at: indexPath) {
cell.configure(with: text)
}
return cell
}
}


Presenter
protocol TableViewPresenterProtocol: AnyObject {
func viewDidLoad()
func numberOfRows() -> Int
func textForRow(at indexPath: IndexPath) -> String
}

class TableViewPresenter: TableViewPresenterProtocol {
weak var view: TableViewProtocol?
var interactor: TableViewInteractorProtocol?

func viewDidLoad() {
interactor?.fetchData()
}

func numberOfRows() -> Int {
return interactor?.data.count ?? 0
}

func textForRow(at indexPath: IndexPath) -> String {
return interactor?.data[indexPath.row] ?? ""
}
}


Interactor
protocol TableViewInteractorProtocol: AnyObject {
var data: [String] { get }
func fetchData()
}

class TableViewInteractor: TableViewInteractorProtocol {
var data: [String] = []

func fetchData() {
data = ["Item 1", "Item 2", "Item 3"]
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔3
🤔 Расскажи про RC?

RC (Reference Counting) в Swift — это механизм управления памятью, который автоматически отслеживает количество ссылок на объекты в памяти. Когда количество ссылок на объект достигает нуля, объект освобождается, и его память становится доступной для повторного использования. ARC (Automatic Reference Counting) управляет ссылками на объекты в фоновом режиме, что позволяет избежать утечек памяти. Однако при работе с циклическими ссылками может потребоваться использовать слабые (`weak`) или необладания (`unowned`) ссылки, чтобы избежать утечек памяти.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Есть ли в функциях моменты, когда используется свойство класса?

Да, в функциях часто используются свойства класса. Функции, методы и замыкания могут взаимодействовать со свойствами класса или структуры, чтобы получить доступ к данным или изменить их.

🚩Примеры использования

🟠Методы класса
Могут использовать свойства класса для чтения или изменения данных. В этом примере метод celebrateBirthday использует свойства name и age для обновления возраста и печати сообщения.
class Person {
var name: String
var age: Int

init(name: String, age: Int) {
self.name = name
self.age = age
}

func celebrateBirthday() {
age += 1
print("Happy Birthday, \(name)! You are now \(age) years old.")
}
}

let person = Person(name: "Alice", age: 30)
person.celebrateBirthday()
// Output: "Happy Birthday, Alice! You are now 31 years old."


🟠Инициализаторы
Используют свойства класса для установки начальных значений при создании экземпляра класса.
class Car {
var model: String
var year: Int

init(model: String, year: Int) {
self.model = model
self.year = year
}

func displayInfo() {
print("Car model: \(model), year: \(year)")
}
}

let car = Car(model: "Toyota", year: 2022)
car.displayInfo()
// Output: "Car model: Toyota, year: 2022"


🟠Замыкания (closures)
Могут захватывать и использовать свойства класса. Это часто используется в асинхронных операциях, таких как сетевые запросы.
class Downloader {
var url: String

init(url: String) {
self.url = url
}

func download(completion: @escaping () -> Void) {
print("Downloading from \(url)...")
DispatchQueue.global().async {
// Симуляция загрузки
sleep(2)
DispatchQueue.main.async {
completion()
}
}
}
}

let downloader = Downloader(url: "https://example.com/file")
downloader.download {
print("Download completed.")
}
// Output:
// "Downloading from https://example.com/file..."
// (2 секунды спустя)
// "Download completed."


🟠Статические свойства и методы
Используются для данных или функций, которые относятся ко всему классу, а не к конкретному экземпляру. В этом примере статическое свойство count используется для отслеживания количества созданных экземпляров класса.
class Counter {
static var count = 0

init() {
Counter.count += 1
}

static func displayCount() {
print("Number of instances: \(count)")
}
}

let counter1 = Counter()
let counter2 = Counter()
Counter.displayCount()
// Output: "Number of instances: 2"


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Что такое Stack и куча?

Стек (Stack) — это область памяти, которая используется для хранения локальных переменных и вызовов функций. Он организован по принципу LIFO (Last In, First Out), и данные в стеке автоматически освобождаются при завершении вызова функции. Куча (Heap) — это область памяти, используемая для динамического выделения памяти, где объекты хранятся до тех пор, пока на них существуют ссылки. В Swift объекты классов размещаются в куче, а структуры и примитивные типы — в стеке, что влияет на производительность и управление памятью.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1
🤔 Может ли быть в языке Swift, что существует сильная ссылка на объект и при этом его не существует?

Объект может быть освобожден из памяти, даже если на него существует сильная ссылка, при использовании ключевого слова unowned в некоторых специфических обстоятельствах.

🚩Unowned References

Неустранимые ссылки (unowned) не увеличивают счетчик ссылок на объект, к которому они относятся. В отличие от слабых ссылок (weak), unowned ссылки не обнуляются автоматически, когда объект освобождается. Это означает, что если вы попытаетесь обратиться к объекту через unowned ссылку после его освобождения, это приведет к аварийному завершению программы (runtime crash).Если бы вы попытались обратиться к owner после освобождения john, это привело бы к аварийному завершению программы, так как unowned ссылка не обнуляется и остается указателем на освобожденный объект.
class Person {
var name: String
var creditCard: CreditCard?

init(name: String) {
self.name = name
}

deinit {
print("\(name) is being deinitialized")
}
}

class CreditCard {
var number: Int
unowned var owner: Person

init(number: Int, owner: Person) {
self.number = number
self.owner = owner
}

deinit {
print("CreditCard #\(number) is being deinitialized")
}
}

var john: Person? = Person(name: "John")
john!.creditCard = CreditCard(number: 1234, owner: john!)

john = nil
// Output:
// John is being deinitialized
// CreditCard #1234 is being deinitialized


1⃣Создается объект Person с именем "John" и сильной ссылкой john.
2⃣Создается объект CreditCard, который имеет неустранимую ссылку owner на john.
3⃣Когда john освобождается (при установке john в nil), также освобождается и объект CreditCard.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 В чем разница между синхронными и асинхронными запросами?

Синхронные запросы блокируют выполнение программы до получения ответа, что может замедлить работу приложения, особенно если запрос занимает длительное время. Асинхронные запросы, напротив, не блокируют основной поток и позволяют программе продолжать выполнение других задач, пока ожидается ответ от сервера или другой операции. Асинхронные запросы часто используются для работы с сетью или файловой системой, чтобы улучшить отзывчивость и производительность программ. В Swift асинхронные операции реализуются через GCD или `async/await`.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1