Swift | Вопросы собесов
2.13K subscribers
28 photos
948 links
Download Telegram
🤔 Что такое ритейн релиз?

Ретейн-релиз (retain-release) — это модель управления памятью, которая использовалась в Objective-C до появления автоматического подсчета ссылок (Automatic Reference Counting, ARC). В этой модели разработчик вручную контролирует время жизни объектов, используя методы retain, release и autorelease. В Swift эта модель заменена ARC, но понимание ретейн-релиз важно для работы с устаревшим кодом и интеграции с Objective-C.

🚩Основные концепции ретейн-релиз

🟠Счётчик ссылок (Reference Count):
Каждый объект в памяти имеет счётчик ссылок, который отслеживает количество сильных ссылок на этот объект. Когда создается новая сильная ссылка на объект, счётчик ссылок увеличивается. Когда сильная ссылка удаляется, счётчик ссылок уменьшается.

🟠Методы управления памятью:
retain: Увеличивает счётчик ссылок на объект.
release: Уменьшает счётчик ссылок на объект. Когда счётчик достигает нуля, объект освобождается из памяти.
autorelease: Помещает объект в autorelease pool, который отправляет сообщение release объектам при спуске (drain) пула.

Autorelease Pool
Это механизм для управления временными объектами, который автоматически освобождает их память после завершения текущего цикла событий. Autorelease pool используется для временного хранения объектов, которым нужно отправить сообщение release позже.

@autoreleasepool {
NSString *tempString = [[NSString alloc] initWithFormat:@"Hello, %@", @"World"];
[tempString autorelease];
// tempString будет автоматически освобождена в конце блока autoreleasepool
}


🟠ARC (Automatic Reference Counting)
В Swift управление памятью автоматизировано с помощью ARC, который выполняет те же действия, что и ретейн-релиз, но автоматически. Разработчик больше не должен явно вызывать retain и release, это делает компилятор.
class MyClass {
var value: Int

init(value: Int) {
self.value = value
print("Object initialized")
}

deinit {
print("Object deinitialized")
}
}

var obj: MyClass? = MyClass(value: 10) // Счётчик ссылок: 1
obj = nil // Счётчик ссылок: 0, объект освобождается из памяти


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
3
🤔 Какое ключевое слово используется для предотвращения наследования класса в Swift?
Anonymous Quiz
3%
sealed
90%
final
4%
static
4%
private
1
🤔 Есть ли у unowned ссылок счетчик?

Unowned ссылки в Swift не увеличивают счётчик ссылок на объект. Это означает, что unowned ссылка не удерживает объект в памяти, и объект может быть освобожден, даже если на него существуют unowned ссылки.

🚩Основные концепции `unowned` ссылок

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

🟠Использование `unowned` ссылок:
Unowned ссылки полезны, когда объект, на который ссылаются, гарантированно будет существовать до тех пор, пока существует сама ссылка. В отличие от слабых ссылок (weak), unowned ссылки не обнуляются автоматически, когда объект освобождается. Это означает, что использование unowned ссылки на освобожденный объект приведет к ошибке времени выполнения (runtime error).
class Customer {
var name: String
var card: CreditCard?

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

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

class CreditCard {
var number: Int
unowned let customer: Customer

init(number: Int, customer: Customer) {
self.number = number
self.customer = customer
}

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

var john: Customer? = Customer(name: "John")
john!.card = CreditCard(number: 1234, customer: john!)

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


Customer и CreditCard ссылаются друг на друга. Customer имеет сильную ссылку на CreditCard, а CreditCard имеет unowned ссылку на Customer. Когда объект john устанавливается в nil, оба объекта освобождаются из памяти.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Какой механизм позволяет структурам и классам в Swift адаптироваться к изменениям интерфейсов без изменения их кода?
Anonymous Quiz
61%
Extensions
23%
Protocols
13%
Generics
3%
Inheritance
👍1
🤔 Для чего нужен volatile?

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

🚩Использование `volatile` в контексте Swift

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

Здесь переменная flag объявлена с модификатором volatile, чтобы компилятор не оптимизировал чтение её значения внутри цикла, предполагая, что оно не изменится. Без volatile, компилятор мог бы оптимизировать код так, что цикл стал бы бесконечным.
volatile int flag = 0;

void someFunction() {
while (flag == 0) {
// ждем изменения флага
}
// флаг изменен, продолжаем выполнение
}


🚩Аналоги в Swift

Для достижения аналогичного эффекта в Swift можно использовать атомарные операции или объекты синхронизации, чтобы управлять доступом к переменным из разных потоков. Здесь используется атомарная переменная ManagedAtomic, чтобы гарантировать корректное чтение и запись флага в многопоточном окружении. В Swift можно использовать библиотеку Atomic из Swift Atomics для безопасного управления доступом к переменным:
import Atomics

class ThreadSafeFlag {
private var flag = ManagedAtomic(0)

func setFlag(_ value: Int) {
flag.store(value, ordering: .relaxed)
}

func waitForFlag() {
while flag.load(ordering: .relaxed) == 0 {
// ждем изменения флага
}
// флаг изменен, продолжаем выполнение
}
}


🚩Пример с использованием `DispatchQueue`

Здесь DispatchQueue гарантирует, что чтение и запись флага будут выполнены атомарно. Другой подход - использование DispatchQueue для управления доступом к ресурсу:
class ThreadSafeFlag {
private var flag = 0
private let queue = DispatchQueue(label: "com.example.threadSafeQueue")

func setFlag(_ value: Int) {
queue.sync {
flag = value
}
}

func waitForFlag() {
var currentFlag = 0
while true {
queue.sync {
currentFlag = flag
}
if currentFlag != 0 {
break
}
}
// флаг изменен, продолжаем выполнение
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51
🤔 Какой механизм используется для управления памятью в Swift, обеспечивающий автоматическое управление временем жизни объектов?
Anonymous Quiz
3%
Garbage Collection
1%
Memory Pool
3%
Reference Counting
93%
Automatic Reference Counting (ARC)
1
🤔 В чём отличие Anound'а и Strong'а?

Weak и Strong ссылки - это ключевые концепции управления памятью в Swift, которые используются для предотвращения циклов удержания (retain cycles) и для правильного управления временем жизни объектов. Однако, термин Anound не является стандартным термином в Swift или других языках программирования.

🚩Отличия

🟠Strong Reference (Сильная ссылка)
Сильная ссылка (по умолчанию) увеличивает счетчик ссылок (reference count) объекта на единицу. Объект, на который имеются сильные ссылки, не будет освобожден до тех пор, пока хотя бы одна сильная ссылка на него существует.
class Person {
var name: String

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

var person1: Person? = Person(name: "John")
var person2 = person1 // Strong reference
person1 = nil
// person2 все еще удерживает объект, объект не будет освобожден


🟠Weak Reference (Слабая ссылка)
Слабая ссылка не увеличивает счетчик ссылок объекта. Слабые ссылки всегда объявляются как опциональные (optional) типа, так как объект может быть освобожден, и слабая ссылка станет nil.
class Person {
var name: String

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

class Company {
var employee: Person?
}

var person: Person? = Person(name: "John")
var company = Company()
company.employee = person // Strong reference

weak var weakPerson = person // Weak reference
person = nil
// weakPerson становится nil, объект освобожден


🟠Unowned Reference (Невладеющая ссылка)
Невладеющая ссылка, как и слабая, не увеличивает счетчик ссылок объекта. Однако, в отличие от слабой ссылки, невладеющая ссылка не является опциональной. Она предполагает, что объект всегда будет существовать во время использования ссылки. Использование невладеющей ссылки на уже освобожденный объект приведет к ошибке выполнения.
class Person {
var name: String

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

class Company {
unowned var employee: Person

init(employee: Person) {
self.employee = employee
}
}

var person: Person? = Person(name: "John")
var company = Company(employee: person!) // Unowned reference

person = nil
// Доступ к company.employee приведет к ошибке выполнения, так как person уже освобожден


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯3👾3
🤔 Какое ключевое слово используется для объявления метода, который выполняется асинхронно?
Anonymous Quiz
92%
async
5%
await
1%
defer
2%
dispatch
1
🤔 Зачем сделан сайт тейбл?

Сайт UITableView (Table View) в iOS используется для отображения списков данных в виде таблицы. Это один из наиболее часто используемых компонентов пользовательского интерфейса в приложениях iOS, так как позволяет организовывать и представлять большие объемы информации в удобном для пользователя формате.

🚩Плюсы

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

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

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

Разделение данных на секции:
UITableView поддерживает разделение данных на секции с заголовками и подзаголовками, что упрощает организацию и навигацию по спискам данных.

🚩Основные компоненты `UITableView`

🟠Ячейки (Cells):
Основной элемент, используемый для отображения строки данных. Ячейки могут быть стандартными или кастомными.

🟠Секции (Sections):
UITableView может содержать несколько секций, каждая из которых может содержать несколько строк. Секции могут иметь заголовки и подзаголовки.

🟠Перезагрузка данных (Reloading Data):
UITableView предоставляет методы для обновления данных, такие как reloadData(), которые перезагружают всю таблицу, и методы для обновления отдельных строк или секций с анимацией.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
😁5🤔32🤯1
🤔 Какое ключевое слово используется в Swift для создания замыканий с последующим выполнением кода после завершения выполнения текущей функции?
Anonymous Quiz
6%
finally
59%
defer
3%
ensure
32%
closure
2
🤔 Наличие контекста в эскейсе хорошо или плохо?

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

🚩Плюсы

Удобство:
Замыкания могут захватывать переменные и константы из окружающего контекста, что делает их мощным инструментом для создания компактного и выразительного кода.
func makeIncrementer(incrementAmount: Int) -> () -> Int {
var total = 0
let incrementer: () -> Int = {
total += incrementAmount
return total
}
return incrementer
}

let incrementByTwo = makeIncrementer(incrementAmount: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4


Локальное состояние:
Замыкания позволяют сохранить состояние между вызовами, что может быть полезно в некоторых сценариях, как показано в примере выше.

Функциональный стиль программирования:
Захват контекста позволяет создавать функции высшего порядка и применять функциональные подходы, такие как каррирование и композиция функций.

🚩Минусы

Утечки памяти (Retain Cycles):
Замыкания могут захватывать ссылки на объекты, что приводит к циклам удержания, когда объекты удерживают друг друга и никогда не освобождаются. В этом примере, если не использовать weak или unowned ссылки, замыкание захватит self, создавая цикл удержания.
class MyClass {
var value: Int = 0
lazy var incrementer: () -> Void = {
self.value += 1
}
}

let instance = MyClass()
instance.incrementer()


Сложность отладки:
Замыкания, захватывающие контекст, могут усложнять отладку и понимание кода, особенно когда контекст изменяется или когда замыкание выполняется асинхронно.

Непредсказуемость поведения:
Если замыкание захватывает изменяемое состояние, это может привести к трудноуловимым ошибкам, связанным с изменением состояния в неожиданных местах.

🚩Как избежать проблем с захватом контекста

🟠Использование [weak self] и [unowned self]:
Для предотвращения циклов удержания используйте слабые или невладеющие ссылки на self внутри замыканий.
class MyClass {
var value: Int = 0
lazy var incrementer: () -> Void = { [weak self] in
self?.value += 1
}
}


🟠Избегайте захвата ненужных переменных:
Захватывайте только те переменные, которые действительно необходимы в замыкании.

🟠Отладка и анализ:
Используйте инструменты отладки и анализаторы утечек памяти, такие как Xcode Instruments, чтобы выявлять и исправлять потенциальные проблемы.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
🤔 В чем суть оптимизации copy on write?

Copy on Write (COW) — это оптимизация, которая откладывает копирование данных до тех пор, пока они не будут изменены. В Swift, структуры и коллекции используют эту технику, чтобы избежать ненужных копий, если данные остаются неизменными. Когда структура или коллекция копируется, реальное копирование происходит только при попытке изменить данные, что снижает накладные расходы. Это помогает улучшить производительность и снизить использование памяти.

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

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

🚩Проблемы

🟠Утечки памяти (Retain Cycles)
Одной из самых распространенных проблем является утечка памяти из-за циклов удержания (retain cycles). Это происходит, когда два или более объекта удерживают ссылки друг на друга, препятствуя освобождению памяти. В этом примере closure захватывает self, что создает цикл удержания: MyClass держит сильную ссылку на closure, а closure держит сильную ссылку на self.
class MyClass {
var value: Int = 0
var closure: (() -> Void)?

func setupClosure() {
closure = {
self.value += 1
}
}
}

let instance = MyClass()
instance.setupClosure()


🟠Непредсказуемое поведение и условия гонки (Race Conditions)
Когда замыкания захватывают изменяемый контекст, это может привести к условиям гонки и непредсказуемому поведению, особенно при работе в многопоточном окружении. Если метод increment вызывается из разных потоков, это может привести к условиям гонки и некорректному изменению значения count.
class Counter {
var count = 0

func increment() {
DispatchQueue.global().async {
self.count += 1
}
}
}

let counter = Counter()
counter.increment()


🟠Задержки в освобождении ресурсов
Если замыкания захватывают тяжелые ресурсы (например, файлы, сети), это может привести к задержкам в их освобождении, что может негативно сказаться на производительности приложения. Если FileHandler освобождается, но замыкание все еще захватывает file, это может привести к задержке в освобождении файлового дескриптора.
class FileHandler {
var file: File?

func processFile() {
DispatchQueue.global().async {
self.file?.read()
}
}
}


🟠Потеря захваченных данных
Когда используется слабая ссылка (weak), замыкание может обнаружить, что захваченный объект освобожден, что приводит к тому, что слабая ссылка становится nil. Это требует дополнительных проверок и обработки.
class MyClass {
var value: Int = 0
var closure: (() -> Void)?

func setupClosure() {
closure = { [weak self] in
guard let strongSelf = self else { return }
strongSelf.value += 1
}
}
}


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

SOLID — это пять принципов объектно-ориентированного проектирования, которые помогают создавать гибкие и легко поддерживаемые программы. Принципы включают: Single Responsibility (единственная ответственность), Open/Closed (открытость для расширения, закрытость для изменений), Liskov Substitution (замещение Лисков), Interface Segregation (разделение интерфейсов) и Dependency Inversion (инверсия зависимостей). Применение SOLID делает код более устойчивым к изменениям и легко расширяемым. Эти принципы повышают качество проектирования программного обеспечения.

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

В iOS разработке классы, представляющие пользовательский интерфейс, такие как UIView, реализуют протокол UIViewRepresentable. Однако, если вы имеете в виду протоколы, которые непосредственно реализует UIView, то вот основные протоколы:

🚩Основные протоколы, реализуемые `UIView`

🟠NSObjectProtocol
UIView наследуется от NSObject, поэтому реализует протокол NSObjectProtocol. Этот протокол предоставляет базовые методы, которые должны быть реализованы всеми объектами в Objective-C, такие как управление памятью и динамическое разрешение методов.

🟠UIAppearance
Протокол UIAppearance позволяет настраивать внешний вид всех экземпляров определенного типа (например, все кнопки или все метки) в приложении.
UIButton.appearance().tintColor = .blue  


🟠UIAccessibility
Протокол UIAccessibility предоставляет поддержку для обеспечения доступности представлений. Это позволяет экранным ридерам и другим вспомогательным технологиям взаимодействовать с приложением.
view.isAccessibilityElement = true
view.accessibilityLabel = "Описание элемента"


🟠Примеры использования `UIViewRepresentable`
Если вы работаете со SwiftUI и хотите использовать представление UIView в SwiftUI, используется протокол UIViewRepresentable. Вот пример, как это делается:
import SwiftUI
import UIKit

struct MyUIView: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.backgroundColor = .red
return view
}

func updateUIView(_ uiView: UIView, context: Context) {
// Обновление состояния представления, если необходимо
}
}

struct ContentView: View {
var body: some View {
MyUIView()
.frame(width: 100, height: 100)
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2
🤔 "Weak" и "Unowned" в чем разница?

Weak и Unowned в Swift используются для предотвращения циклов сильных ссылок в случае управления памятью через ARC. Weak ссылки могут становиться nil, если объект, на который они ссылаются, освобождается, и используются, когда возможна утечка памяти. Unowned ссылки, напротив, не могут становиться nil, и если объект освобожден, доступ к unowned ссылке приведет к ошибке. Weak обычно используется для объектов, которые могут быть удалены, а Unowned — когда объект должен существовать всегда.

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

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

🚩Инициализаторы выполняют следующие функции:

🟠Выделение памяти:
Обеспечивают выделение памяти для нового объекта.
🟠Установка начальных значений свойств:
Устанавливают начальные значения для всех свойств объекта.
🟠Выполнение начальной настройки:
Выполняют любую дополнительную настройку, необходимую для объекта.

🚩Типы инициализаторов

🟠Назначенные инициализаторы (Designated Initializers):
Основные инициализаторы, которые обеспечивают полную инициализацию всех свойств объекта.
🟠Удобные инициализаторы (Convenience Initializers):
Вспомогательные инициализаторы, которые вызывают другой инициализатор для выполнения части работы и могут добавлять дополнительную настройку.
🟠Инициализаторы без параметров (Default Initializers):
Предоставляются автоматически для структур и классов, если все их свойства имеют начальные значения и не определены другие инициализаторы.
🟠Инициализаторы с параметрами (Parameter Initializers):
Принимают параметры, которые используются для установки начальных значений свойств объекта.
class Car {
var color: String
var model: String
var year: Int

// Назначенный инициализатор
init(color: String, model: String, year: Int) {
self.color = color
self.model = model
self.year = year
}

// Удобный инициализатор
convenience init(model: String) {
self.init(color: "White", model: model, year: 2020)
}
}

// Использование назначенного инициализатора
let myCar = Car(color: "Red", model: "Toyota", year: 2020)

// Использование удобного инициализатора
let defaultCar = Car(model: "Honda")


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

Известные проблемы с многопоточностью включают гонки данных, блокировки и взаимоблокировки (deadlocks). Гонки данных происходят, когда несколько потоков одновременно пытаются изменить одни и те же данные без должной синхронизации. Блокировки возникают, когда потоки ждут освобождения ресурсов друг от друга, что замедляет работу программы. Взаимоблокировки случаются, когда два потока захватывают ресурсы и не могут завершить работу из-за зависимостей.

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

Метод lazy используется для отложенной (ленивой) инициализации свойств. Это означает, что значение ленивого свойства не вычисляется до первого обращения к нему. Ленивые свойства особенно полезны, когда вычисление значения свойства требует значительных ресурсов или зависит от внешних факторов, которые могут измениться в будущем.

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

🟠Отложенная инициализация:
Свойство с модификатором lazy инициализируется только при первом доступе к нему. До этого момента память для свойства не выделяется и код инициализатора не выполняется.

🟠Требования:
Ленивое свойство всегда должно быть объявлено как переменная (var), так как его значение может измениться после инициализации.

🟠Использование:
Ленивые свойства полезны, когда инициализация значения свойства требует больших затрат ресурсов или сложных вычислений, и нет необходимости выполнять их до первого обращения к свойству.
class DataProcessor {
lazy var expensiveData: [String] = {
// Симуляция затратной операции
print("Инициализация expensiveData")
return ["Data1", "Data2", "Data3"]
}()

init() {
print("DataProcessor инициализирован")
}
}

let processor = DataProcessor()
// expensiveData еще не инициализировано

print("Перед доступом к expensiveData")
print(processor.expensiveData) // Инициализация происходит здесь
print("После доступа к expensiveData")


Вывод
DataProcessor инициализирован
Перед доступом к expensiveData
Инициализация expensiveData
["Data1", "Data2", "Data3"]
После доступа к expensiveData

🚩Плюсы

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

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

Упрощение инициализаторов:
Ленивые свойства могут упростить инициализаторы классов и структур, позволяя избежать сложных вычислений или загрузок данных в момент создания объекта.

🚩Важные моменты

🟠Ленивые свойства и многопоточность:
Будьте осторожны при использовании ленивых свойств в многопоточных приложениях, так как одновременный доступ к ленивому свойству из разных потоков может привести к некорректному поведению или состоянию гонки.

🟠Свойства только для чтения:
Если ленивое свойство должно быть только для чтения, его можно объявить как приватную переменную с ленивой инициализацией и предоставить публичное свойство только для чтения.
class DataProcessor {
private lazy var _expensiveData: [String] = {
print("Инициализация expensiveData")
return ["Data1", "Data2", "Data3"]
}()

var expensiveData: [String] {
return _expensiveData
}
}

let processor = DataProcessor()
print(processor.expensiveData) // Инициализация происходит здесь


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

Основное различие между структурами и классами в Swift заключается в том, что структуры являются типами-значениями, а классы — типами-ссылками. Структуры копируются при передаче в функции или при присваивании, а классы передаются по ссылке. Классы поддерживают наследование, в то время как структуры нет. Структуры также автоматически предоставляют конструкторы, и их использование чаще предпочтительно для простых контейнеров данных.

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