Основные способы передачи данных в iOS
class DetailViewController: UIViewController {
var data: String
init(data: String) {
self.data = data
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail",
let detailVC = segue.destination as? DetailViewController {
detailVC.data = "Hello, World!"
}
}
protocol DataDelegate: AnyObject {
func didReceiveData(_ data: String)
}
class Sender {
weak var delegate: DataDelegate?
func sendData() {
delegate?.didReceiveData("Hello, World!")
}
}
class Receiver: DataDelegate {
func didReceiveData(_ data: String) {
print(data)
}
}
let sender = Sender()
let receiver = Receiver()
sender.delegate = receiver
sender.sendData() // Output: Hello, World!
func fetchData(completion: @escaping (String) -> Void) {
let data = "Hello, World!"
completion(data)
}
fetchData { data in
print(data) // Output: Hello, World!
}
NotificationCenter.default.post(name: .didReceiveData, object: nil, userInfo: ["data": "Hello, World!"])
NotificationCenter.default.addObserver(forName: .didReceiveData, object: nil, queue: .main) { notification in
if let data = notification.userInfo?["data"] as? String {
print(data) // Output: Hello, World!
}
}
UserDefaults.standard.set("Hello, World!", forKey: "data")
if let data = UserDefaults.standard.string(forKey: "data") {
print(data) // Output: Hello, World!
}
let keychain = Keychain(service: "com.example.myapp")
keychain["data"] = "Hello, World!"
if let data = keychain["data"] {
print(data) // Output: Hello, World!
}
class DataManager {
static let shared = DataManager()
var data: String?
}
DataManager.shared.data = "Hello, World!"
print(DataManager.shared.data ?? "") // Output: Hello, World!
В iOS можно передавать данные через инициализаторы, сегвей, делегаты, замыкания, нотификации, UserDefaults, Keychain и общие ресурсы. Выбор метода зависит от конкретных требований.
В двух фразах: Данные в iOS можно передавать разными способами, включая инициализаторы, сегвей, делегаты, замыкания, нотификации, UserDefaults, Keychain и общие ресурсы. Каждый метод имеет свои применения и подходит для разных сценариев.
Please open Telegram to view this post
VIEW IN TELEGRAM
Anonymous Quiz
75%
Enumerations
2%
Classes
8%
Structures
15%
Tuples
Если убрать опционалы из Swift, это приведет к значительным изменениям в языке и его поведении, что окажет влияние на несколько ключевых аспектов программирования:
nil). Это помогает избежать неожиданных ошибок и делает код более безопасным. var name: String? = nil
if let unwrappedName = name {
print("Name is \(unwrappedName)")
} else {
print("Name is nil")
}
var name: String = "" // Значение по умолчанию
if name.isEmpty {
print("Name is nil")
} else {
print("Name is \(name)")
}
nil.?, !, if let и guard let.nil в случае неудачи. func findUser(byID id: Int) -> User? {
// Возвращает nil, если пользователь не найден
}
func findUser(byID id: Int) -> User {
// Возвращает пустого пользователя или значение по умолчанию
return User()
}
nil.nil.Удаление опционалов из Swift приведет к необходимости использования значений по умолчанию, ручной обработки отсутствующих значений и ошибок, что увеличит вероятность ошибок и сделает код менее безопасным и устойчивым. Опционалы помогают явно указывать на возможность отсутствия значения и обеспечивают более безопасное и надежное программирование.
В двух фразах: Удаление опционалов сделает код менее безопасным и устойчивым, увеличивая вероятность ошибок из-за отсутствующих значений. Опционалы важны для явного указания на возможность
nil и для повышения надежности кода.Please open Telegram to view this post
VIEW IN TELEGRAM
Anonymous Quiz
9%
`!`
54%
`?`
33%
`??`
5%
`->`
Мьютекс (от англ. "mutex" - mutual exclusion, взаимное исключение) — это механизм синхронизации, используемый в многопоточном программировании для предотвращения одновременного доступа нескольких потоков к общим ресурсам, таким как переменные, структуры данных или файлы. Он помогает избежать состояния гонки (race condition), когда результат выполнения программы зависит от неопределённого порядка доступа потоков к ресурсу.
В Swift можно использовать класс
NSLock для создания мьютексов:import Foundation
class SafeCounter {
private var value = 0
private let lock = NSLock()
func increment() {
lock.lock() // Захват мьютекса
value += 1
lock.unlock() // Освобождение мьютекса
}
func getValue() -> Int {
lock.lock() // Захват мьютекса
let currentValue = value
lock.unlock() // Освобождение мьютекса
return currentValue
}
}
let counter = SafeCounter()
DispatchQueue.global().async {
for _ in 0..<1000 {
counter.increment()
}
}
DispatchQueue.global().async {
for _ in 0..<1000 {
counter.increment()
}
}
// Подождём немного, чтобы дать потокам закончить работу
Thread.sleep(forTimeInterval: 1)
print("Final counter value: \(counter.getValue())")
Недостатки использования мьютексов
Мьютекс — это важный механизм для синхронизации доступа к общим ресурсам в многопоточном программировании. Он предотвращает одновременный доступ к ресурсам, обеспечивая их целостность и стабильность программы, но требует осторожного использования для избежания мёртвых блокировок и снижения производительности.
В двух фразах: Мьютекс позволяет предотвратить одновременный доступ нескольких потоков к общим ресурсам, обеспечивая безопасность данных. Это делает код более предсказуемым, но требует аккуратного использования для предотвращения мёртвых блокировок и снижения производительности.
Please open Telegram to view this post
VIEW IN TELEGRAM
Anonymous Quiz
7%
var
2%
const
84%
let
8%
fix
Оптимизация выполнения кода в Swift может быть достигнута различными методами, начиная с улучшения структуры кода и заканчивая использованием эффективных алгоритмов и данных. Вот несколько ключевых методов для оптимизации:
Set, для пар ключ-значение — Dictionary. var array = [1, 2, 3, 4, 5]
var set: Set = [1, 2, 3, 4, 5]
var dictionary = ["one": 1, "two": 2, "three": 3]
var name: String? = "John"
if let unwrappedName = name {
print("Name is \(unwrappedName)")
}
inout параметры для избежания копирования при передаче значений в функции. func increment(value: inout Int) {
value += 1
}
var number = 1
increment(value: &number)
OperationQueue для выполнения задач в фоновом режиме. DispatchQueue.global(qos: .background).async {
// Фоновая задача
DispatchQueue.main.async {
// Обновление UI на главном потоке
}
}
class MyClass {
lazy var expensiveObject: ExpensiveObject = {
return ExpensiveObject()
}()
}
var cache = [Int: Int]()
func fibonacci(_ n: Int) -> Int {
if let result = cache[n] {
return result
}
if n <= 1 { return n }
let result = fibonacci(n - 1) + fibonacci(n - 2)
cache[n] = result
return result
}
for i in 0..<1000 {
// Оптимизированный код
}
struct Point {
var x: Int
var y: Int
}
Оптимизация выполнения кода в Swift включает в себя выбор правильных структур данных, минимизацию использования опционалов, избежание ненужного копирования, использование асинхронности и параллелизма, ленивую загрузку, кэширование результатов, оптимизацию циклов и использование value types. Профилирование и анализ узких мест также играют ключевую роль в оптимизации.
В двух фразах: Оптимизировать выполнение кода в Swift можно с помощью правильного выбора структур данных, асинхронного выполнения задач, ленивой загрузки и кэширования результатов. Профилирование помогает выявить и устранить узкие места в производительности.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
Anonymous Quiz
9%
Асинхронное выполнение кода
4%
Создание новой очереди
86%
Синхронное выполнение кода
1%
Управление памятью
В Swift автоматически генерируемый memberwise инициализатор доступен только для структур (structs), но не для классов (classes). Это связано с рядом различий между этими двумя типами и некоторыми особенностями их поведения.
class BaseClass {
var baseProperty: String
init(baseProperty: String) {
self.baseProperty = baseProperty
}
}
class SubClass: BaseClass {
var subProperty: Int
init(baseProperty: String, subProperty: Int) {
self.subProperty = subProperty
super.init(baseProperty: baseProperty)
}
}
class ResourceHandler {
var resource: Resource
init(resource: Resource) {
self.resource = resource
// Дополнительные действия по настройке ресурса
}
deinit {
// Освобождение ресурса
}
}
class Node {
var value: Int
var next: Node?
init(value: Int, next: Node?) {
self.value = value
self.next = next
}
}
class User {
var name: String
var age: Int
init(name: String, age: Int) {
guard age > 0 else {
fatalError("Возраст должен быть положительным")
}
self.name = name
self.age = age
}
}
Автоматическая генерация memberwise инициализатора для классов в Swift отсутствует из-за сложности, связанной с наследованием, управлением памятью, пользовательскими требованиями к инициализации и необходимостью учитывать сложные правила инициализации и деинициализации. Эти особенности требуют явного определения инициализаторов разработчиком для обеспечения правильной и безопасной работы классов.
В двух фразах: Swift не генерирует memberwise инициализаторы для классов из-за сложности, связанной с наследованием и управлением памятью, а также необходимости учитывать специфические требования к инициализации. Разработчики должны явно определять инициализаторы для обеспечения корректной работы классов.
Please open Telegram to view this post
VIEW IN TELEGRAM
Anonymous Quiz
36%
private
15%
fileprivate
46%
internal
3%
public
RunLoop — это фундаментальный механизм в iOS и macOS, который управляет циклом обработки событий в приложении. Он отслеживает и обрабатывает входящие события, такие как нажатия клавиш, касания экрана, таймеры и сетевые запросы, и поддерживает приложение в активном состоянии, пока оно не завершится.RunLoop постоянно выполняет цикл, ожидая входящие события и обрабатывая их по мере поступления. Этот цикл состоит из нескольких этапов: ожидание события, обработка события и повтор цикла.RunLoop может работать в разных режимах, которые определяют, какие источники событий будут отслеживаться и обрабатываться. Основные режимы включают default и tracking (для событий отслеживания, таких как прокрутка). В каждой итерации RunLoop обрабатывает события только для текущего режима.RunLoop.current.run(mode: .default, before: Date.distantFuture)
RunLoop может отслеживать различные источники событий, такие как таймеры (Timer), порты (Port), ввод пользователей (такие как касания экрана и клики мыши), а также пользовательские источники (Input Source).RunLoop может управлять таймерами, которые выполняют задачи через определенные интервалы времени. let timer = Timer(timeInterval: 1.0, repeats: true) { _ in
print("Timer fired!")
}
RunLoop.current.add(timer, forMode: .default)
RunLoop используется для обработки событий в основном потоке (main thread) приложения. Это особенно важно для поддержания отзывчивости пользовательского интерфейса, поскольку все взаимодействия с UI происходят в основном потоке.import Foundation
class Example {
var timer: Timer?
func startRunLoop() {
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
RunLoop.current.run()
}
@objc func timerFired() {
print("Timer fired!")
}
}
let example = Example()
example.startRunLoop()
RunLoop — это ключевой компонент в iOS и macOS, обеспечивающий цикл обработки событий в приложении. Он управляет различными источниками событий и таймерами, обеспечивая поддержку активного состояния приложения и отзывчивость пользовательского интерфейса.В двух фразах:
RunLoop управляет циклом обработки событий в приложении, отслеживая и обрабатывая входящие события. Это позволяет поддерживать активное состояние приложения и обеспечивает отзывчивость пользовательского интерфейса.Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Anonymous Quiz
1%
Увеличивает производительность
2%
Отключает ARC
94%
Делает замыкание сохраняемым после выхода функции
3%
Обеспечивает доступ к приватным данным
RSI может обозначать разные вещи в зависимости от контекста, но наиболее часто эта аббревиатура используется в следующих двух областях:Relative Strength Index (RSI) — это технический индикатор, используемый в анализе финансовых рынков для оценки силы и скорости изменения цен актива. RSI помогает определить перекупленность или перепроданность актива, что может указывать на возможность коррекции цены или разворота тренда.
\[
RSI = 100 - \left(\frac{100}{1 + RS}\right)
\]
где RS (Relative Strength) = среднее значение закрытия вверх / среднее значение закрытия вниз.
import Foundation
// Пример функции для расчета RSI на Swift
func calculateRSI(prices: [Double]) -> Double? {
guard prices.count >= 14 else { return nil }
let averageGain = prices[1..<14].filter { $0 >= 0 }.reduce(0, +) / 14
let averageLoss = prices[1..<14].filter { $0 < 0 }.reduce(0, +).magnitude / 14
guard averageLoss != 0 else { return 100 }
let rs = averageGain / averageLoss
let rsi = 100 - (100 / (1 + rs))
return rsi
}
let prices = [1.1, 1.2, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, 1.55, 1.6, 1.65, 1.7]
if let rsi = calculateRSI(prices: prices) {
print("RSI: \(rsi)")
}
Repetitive Strain Injury (RSI) — это медицинский термин, обозначающий травмы, возникающие в результате повторяющихся движений или чрезмерного использования определенных частей тела, обычно рук и кистей. RSI часто встречается у людей, работающих за компьютером, музыкантов, спортсменов и тех, кто выполняет повторяющиеся физические задачи.
RSI может означать как технический индикатор Relative Strength Index в финансах, так и медицинское состояние Repetitive Strain Injury. В финансах RSI помогает анализировать состояние рынка, в то время как в медицине RSI относится к травмам, вызванным повторяющимися движениями.
В двух фразах: В финансах RSI — это индикатор силы цены актива, показывающий перекупленность или перепроданность. В медицине RSI — это травмы от повторяющихся движений, требующие профилактики и лечения.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯8👀3
Anonymous Quiz
62%
?
4%
!
32%
??
1%
@
😁20🤯1
Словарь (dictionary) в программировании — это структура данных, которая хранит пары ключ-значение. В Swift словарь представлен типом
Dictionary<K, V>, где K — это тип ключей, а V — тип значений. Словари широко используются из-за их эффективности и удобства. Вот основные причины и примеры использования словарей:var phoneBook: [String: String] = ["Alice": "123-4567", "Bob": "987-6543"]
if let number = phoneBook["Alice"] {
print("Alice's phone number is \(number)")
}
var inventory: [String: Int] = ["Apples": 10, "Bananas": 5]
inventory["Apples"] = 15 // Обновление количества яблок
struct Person {
let name: String
let age: Int
}
var people: [String: Person] = ["Alice": Person(name: "Alice", age: 30), "Bob": Person(name: "Bob", age: 25)]
if let person = people["Alice"] {
print("\(person.name) is \(person.age) years old")
}
var studentGrades: [String: [String: Double]] = [
"Alice": ["Math": 95, "Science": 90],
"Bob": ["Math": 85, "Science": 80]
]
if let aliceGrades = studentGrades["Alice"] {
print("Alice's Math grade is \(aliceGrades["Math"] ?? 0)")
}
Словари часто используются в алгоритмах для эффективного хранения и поиска данных, а также в реализации более сложных структур данных, таких как графы и хеш-таблицы.
Хранение данных о студентах
var students: [Int: String] = [101: "Alice", 102: "Bob", 103: "Charlie"]
if let student = students[102] {
print("Student with ID 102 is \(student)")
}
Подсчет частоты элементов
let words = ["apple", "banana", "apple", "orange", "banana", "apple"]
var wordCount: [String: Int] = [:]
for word in words {
wordCount[word, default: 0] += 1
}
print(wordCount) // ["apple": 3, "banana": 2, "orange": 1]
var settings: [String: Any] = ["theme": "dark", "notificationsEnabled": true]
if let theme = settings["theme"] as? String {
print("Current theme is \(theme)")
}
Словари в Swift предоставляют эффективный и удобный способ хранения и управления данными, обеспечивая быстрый доступ, уникальные ключи, гибкость в типах данных и возможность группировки связанных данных. Они широко используются в различных приложениях для решения множества задач.
В двух фразах: Словари позволяют эффективно хранить и управлять данными, предоставляя быстрый доступ к значениям по уникальным ключам. Они гибки и удобны для различных приложений, от простого хранения до сложных алгоритмов.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
Anonymous Quiz
85%
Изменяет свойства типа
8%
Создает копию объекта
0%
Удаляет объект из памяти
7%
Добавляет новое свойство
🤔2
В Swift,
final — это ключевое слово, используемое для предотвращения наследования от класса или переопределения его методов и свойств. Когда вы объявляете класс или его члены с помощью final, вы говорите компилятору, что этот класс или члены не должны быть изменены или расширены.final, его нельзя использовать в качестве базового класса для создания подклассов.final class Animal {
var name: String
init(name: String) {
self.name = name
}
}
// Попытка создать подкласс от final-класса вызовет ошибку компиляции
// class Dog: Animal { }final, не могут быть переопределены в подклассах. class Vehicle {
final func startEngine() {
print("Engine started")
}
}
class Car: Vehicle {
// Попытка переопределить метод вызовет ошибку компиляции
// override func startEngine() {
// print("Car engine started")
// }
}
final, не могут быть переопределены в подклассах. class Building {
final var numberOfFloors: Int {
return 5
}
}
class Skyscraper: Building {
// Попытка переопределить свойство вызовет ошибку компиляции
// override var numberOfFloors: Int {
// return 100
// }
}
final, могут быть оптимизированы компилятором, так как нет необходимости учитывать возможность их переопределения или наследования. Это может привести к более эффективному выполнению кода.final помогает избежать случайного переопределения методов или наследования классов, что может предотвратить потенциальные ошибки и нежелательные изменения в поведении программы.final делает код более понятным, так как ясно указывает, что эти элементы не предназначены для изменения или расширения. Это может улучшить читаемость и поддерживаемость кода.Ключевое слово
final в Swift используется для предотвращения наследования классов и переопределения методов и свойств. Это улучшает производительность, безопасность кода и делает намерения разработчика более явными.В двух фразах:
final предотвращает наследование классов и переопределение методов и свойств, улучшая производительность и безопасность кода. Это делает код более предсказуемым и понятным.Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Anonymous Quiz
3%
Инициализирует объект
95%
Уничтожает объект
2%
Обновляет объект
0%
Клонирует объект
В iOS и macOS приложениях, разработанных с использованием Swift или Objective-C,
UIView и CALayer играют ключевые роли в управлении и отображении пользовательского интерфейса. Несмотря на то, что они тесно связаны, между ними есть важные различия. Давайте рассмотрим их подробнее.UIView — это базовый класс для всех элементов пользовательского интерфейса в iOS. Он представляет собой прямоугольную область на экране, которая может отображать контент и реагировать на события пользователя, такие как нажатия, жесты и касания.UIView предоставляет множество свойств и методов для управления внешним видом, положением и поведением представления. Примеры включают frame, bounds, center, backgroundColor, alpha, isHidden, и subviews.UIView также поддерживает анимации, автолэйаут и работу с событийной системой.UIView обрабатывает пользовательские события, такие как касания и жесты. Он предоставляет методы, такие как touchesBegan, touchesMoved, и touchesEnded, для обработки этих событий.let myView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
myView.backgroundColor = .blue
view.addSubview(myView)
CALayer — это базовый класс для всех графических слоев, используемых в Core Animation. Он обеспечивает низкоуровневую поддержку для рендеринга, анимации и композиции графики.CALayer предоставляет свойства для управления внешним видом, такими как backgroundColor, borderWidth, cornerRadius, shadowOpacity, contents (для отображения изображений), и transform.CALayer также поддерживает анимации, используя ключевые кадры и основные анимации.CALayer не обрабатывает пользовательские события напрямую. Эти задачи оставлены на UIView, который может содержать один или несколько слоев.let myLayer = CALayer()
myLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
myLayer.backgroundColor = UIColor.blue.cgColor
view.layer.addSublayer(myLayer)
1️⃣ По уровеню абстракции:
UIView — это более высокий уровень абстракции, предназначенный для работы с пользовательским интерфейсом и обработкой событий.CALayer — более низкоуровневый элемент, который фокусируется на рендеринге и анимации графики.2️⃣ Реакция на события:
UIView обрабатывает события пользовательского интерфейса.CALayer не обрабатывает события, но предоставляет возможности для рендеринга и анимации.UIView может содержать другие представления (subviews) и управлять их иерархией.CALayer может содержать другие слои (sublayers) и управлять их иерархией.UIView использует UIView.animate для создания анимаций, которые высокоуровневые и просты в использовании.CALayer использует CAAnimation и его подклассы для создания анимаций, которые более гибкие и мощные, но требуют большего количества кода.UIView и CALayer служат разным целям в системе отображения и анимации iOS. UIView предназначен для работы с пользовательским интерфейсом и обработкой событий, тогда как CALayer обеспечивает низкоуровневую поддержку для рендеринга и анимации. UIView содержит CALayer в качестве своего основного слоя, что позволяет совместно использовать возможности обоих классов.В двух фразах:
UIView — это основной класс для элементов пользовательского интерфейса, который может обрабатывать события и управлять дочерними представлениями. CALayer — это низкоуровневый элемент, используемый для рендеринга и анимации графики, не обрабатывающий события напрямую.Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
В Swift, типы значений (value types) обычно хранятся в стеке, что обеспечивает их высокую производительность и простоту управления памятью. Однако в некоторых случаях типы значений могут храниться в куче (heap). Это может происходить в следующих ситуациях:
Когда значение типа (например, структура или перечисление) захватывается замыканием, оно может быть перемещено в кучу для обеспечения корректного управления памятью и жизненного цикла.
Пример:
struct MyStruct {
var value: Int
}
func createClosure() -> () -> Int {
let myStruct = MyStruct(value: 42)
return { myStruct.value }
}
let closure = createClosure()
print(closure()) // Output: 42В этом примере
myStruct захватывается замыканием, что приводит к его размещению в куче.Иногда для хранения типов значений в куче используется техника "boxing". Это означает, что значение типа заворачивается в объект класса, который хранится в куче.
Пример:
class Box<T> {
var value: T
init(_ value: T) {
self.value = value
}
}
struct MyStruct {
var value: Int
}
let boxedStruct = Box(MyStruct(value: 42))
print(boxedStruct.value.value) // Output: 42Здесь структура
MyStruct обернута в объект класса Box, что приводит к её размещению в куче.Когда тип значения используется в качестве свойства класса, оно будет храниться в куче вместе с экземпляром класса.
Пример:
struct MyStruct {
var value: Int
}
class MyClass {
var myStruct: MyStruct
init(myStruct: MyStruct) {
self.myStruct = myStruct
}
}
let instance = MyClass(myStruct: MyStruct(value: 42))
// instance.myStruct хранится в кучеВ этом примере структура
MyStruct является свойством класса MyClass, поэтому её экземпляры хранятся в куче вместе с экземплярами MyClass.Коллекции, такие как массивы, словари и множества, хранящие типы значений, могут размещать эти значения в куче, если коллекция становится слишком большой.
Пример:
struct MyStruct {
var value: Int
}
let array = [MyStruct(value: 1), MyStruct(value: 2), MyStruct(value: 3)]
// Элементы массива могут быть размещены в кучеКогда массив содержит много элементов, память для них может быть выделена в куче для управления их жизненным циклом.
Типы значений в Swift могут храниться в куче, когда они захватываются замыканиями, оборачиваются в классы, являются свойствами классов или хранятся в больших коллекциях. Это необходимо для управления памятью и жизненным циклом данных в более сложных сценариях.
В двух фразах: Типы значений в Swift могут храниться в куче, когда они захватываются замыканиями, оборачиваются в классы, являются свойствами классов или хранятся в больших коллекциях. Это помогает управлять памятью и жизненным циклом данных в сложных сценариях.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍1