EasySwift iOS🍏
2.99K subscribers
272 photos
8 videos
425 links
Все самое интересное в мире iOS разработки 🧑🏻‍💻

Предложить статью или новость: @EasySwiftBot

По всем вопросам обращаться к @itereznikov
Download Telegram
How to unwrap [weak self] in Swift Concurrency Tasks?

🔍 В Swift, использование [weak self] в замыканиях помогает избежать циклов удержания, но не всегда необходимо, особенно для не-escaping замыканий.

Создание неструктурированного Task может привести к утечкам памяти, если [weak self] используется неправильно, так как Task начинает выполняться сразу после его создания.

Task { [weak self] in
guard let self else { return } // это не решает проблему

let data = await loadData()
let models = await processData(data)
}


✔️ Для предотвращения сильного удержания self в Task, рекомендуется проверять наличие self внутри тела цикла или использовать self? для избежания распаковки.

При выполнении длительных задач, таких как загрузка нескольких страниц, перемещение guard let self внутрь цикла позволяет избежать удержания self дольше, чем это необходимо.

Task { [weak self] in
let data = await loadData()
guard self != nil else { return }

guard let models = await self?.processData(data) else {
return
}

// use models
}
Please open Telegram to view this post
VIEW IN TELEGRAM
4👎2🔥1
Derived Data: 5 Things iOS Developers Do Wrong

😐 Многие разработчики iOS не понимают, для чего предназначена папка Derived Data, что может привести к неэффективному использованию её возможностей.

Удаление всей папки Derived Data может замедлить процесс сборки, так как каждый проект имеет свою собственную папку, и удаление её требует повторной компиляции всех зависимостей.

ℹ️ Инструменты, такие как RocketSim, могут помочь командам отслеживать время сборки и выявлять узкие места, что может значительно повысить производительность.

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

🖥 Xcode предоставляет простой способ доступа к папке Derived Data через настройки, что облегчает её использование.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Массивы в Swift

🟢 Принес очередную базу.

ℹ️ Массивы в Swift - это структуры данных, которые хранят коллекции элементов одного типа и поддерживают доступ по индексу за O(1).

Добавление элементов в массив происходит за амортизированное константное время, однако при расширении массива может потребоваться больше времени из-за копирования элементов.

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

👀 Они представляют собой обертку над буфером, который хранит данные в куче. В зависимости от наличия Objective-C runtime, используются разные типы буферов.

Swift реализует механизм Copy-on-Write, который позволяет избежать ненужного копирования данных до момента их изменения.

ArraySlice позволяет работать с подмножеством элементов массива без их копирования, что экономит память и время.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51
Разбираемся с existential container в Swift

Existential container — это структура данных в Swift, которая хранит значения типов, скрытых за протоколами, и используется для динамического вызова методов и управления жизненным циклом значений.

⚙️ Existential container для non class-constrained типов занимает 5 машинных слов (40 байт) и состоит из 24 байт данных, указателя на метаданные типа и указателя на таблицу свидетельств протокола.

Value witness table (VWT) описывает операции с конкретными типами, включая инициализацию, копирование и уничтожение значений, что позволяет компилятору генерировать соответствующий код для этих операций.

❗️ В отличие от дженериков, которые используют статическую диспетчеризацию, existential container применяет динамическую диспетчеризацию, что требует выделения памяти в куче для значений больше 3 байт.

✔️ Рекомендуется использовать дженерики по умолчанию, если нет необходимости в динамическом определении типа, чтобы избежать излишнего использования памяти и увеличения размера бинарного файла.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5😁1
How to Use OptionSet in Swift with code samples

ℹ️ OptionSet — это протокол в Swift, который представляет опции в виде битов, позволяя комбинировать несколько значений и выполнять операции, такие как объединение и пересечение.

🖥 В примере кода создается структура TasksListOptions, которая использует OptionSet для определения опций отображения задач, таких как фильтр, поиск и сортировка.

struct TasksListOptions: OptionSet {
let rawValue: Int

static let showFilter = TasksListOptions(rawValue: 1 << 0)
static let showSearch = TasksListOptions(rawValue: 1 << 1)
static let showSort = TasksListOptions(rawValue: 1 << 2)
static let showLayoutSelector = TasksListOptions(rawValue: 1 << 3)
}


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

✔️ OptionSet является предпочтительным инструментом для конфигурации функций, стилей или разрешений в Swift, обеспечивая компактность и производительность.
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Using Observations to observe @Observable model properties

🆕 С Xcode 26 и Swift 6.2 появилась возможность использовать объект Observations для наблюдения за свойствами моделей @Observable, что упрощает процесс наблюдения вне SwiftUI.

🔍 Объект Observations позволяет создать AsyncSequence, который будет эмитировать значения при изменении наблюдаемых свойств, таких как count в модели Counter.

❗️ Важно использовать [weak self] в замыкании Observations, чтобы избежать циклов удержания, что может привести к утечкам памяти.

⚠️ При использовании Observations можно пропустить значения, если они производятся быстрее, чем вы их обрабатываете, поэтому рекомендуется реализовать собственное буферизование.

➡️ Новая система Observations предлагает did set semantics, в отличие от withObservationTracking, который использует will set semantics, что улучшает реакцию на изменения.

@Observable 
class Counter {
var count: Int
}

class CounterObserver {
let counter: Counter

init(counter: Counter) {
self.counter = counter
}

func observe() {
Task { [weak self] in
let values = Observations { [weak self] in
guard let self else { return 0 }
return self.counter.count
}

for await value in values {
guard let self else { break }
print("counter.count: \(value)")
}
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Detecting Text Language with NLLanguageRecognizer in Swift

ℹ️ Для определения доминирующего языка текста используется структура LanguageDetector, которая инициализирует NLLanguageRecognizer, обрабатывает строку и возвращает код языка в формате ISO 639-1.

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

⚙️ Можно добавить возможность возвращать оценки уверенности в предсказании языка и использовать языковые подсказки для повышения точности распознавания в многоязычных приложениях.

✔️ NLLanguageRecognizer — это мощный API, который позволяет интегрировать определение языка в приложение без необходимости в серверных вызовах и задержках.

import NaturalLanguage

struct LanguageDetector {
static func languageCode(for text: String) -> String? {
let recognizer = NLLanguageRecognizer()
recognizer.processString(text)
if let language = recognizer.dominantLanguage {
return language.rawValue // "en", "ru", "de", etc.
}
return nil
}
}

static func detectLanguage(for text: String) -> (code: String, confidence: Double)? {
let recognizer = NLLanguageRecognizer()
recognizer.processString(text)
guard let language = recognizer.dominantLanguage else { return nil }
let hypotheses = recognizer.languageHypotheses(withMaximum: 1)
let confidence = hypotheses[language] ?? 0
return (language.rawValue, confidence)
}
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Сам себе Шерлок: 7 способов найти логи и поймать баг на iOS

Очередная база - лонгрид про логи ⚙️

🖥 Статья описывает 7 проверенных способов сбора логов на iOS, включая использование .ips файлов, log collect CLI, Xcode и утилиты Console.

Логи делятся на креш-отчёты, диагностические и аналитические данные, которые помогают выявить причины сбоев и проблем с производительностью приложения.

Для работы с логами могут потребоваться инструменты, такие как Xcode, libimobiledevice и Apple Configurator, а также доступ к устройству по проводу или Wi-Fi.

👀Логи помогают разработчикам и тестировщикам убедиться в вызове функций, отслеживать сетевые запросы и выявлять ошибки, которые не отображаются на UI.

⚠️ Рекомендуется собирать логи сразу после инцидента, так как старые .ips файлы автоматически удаляются системой.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
Testing Private Members in Swift with @_private(sourceFile:)

👀 Атрибут @_private(sourceFile:) в Swift позволяет тестировать приватные члены классов, обходя контроль доступа, что полезно для написания более точных юнит-тестов.

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

⚙️ Для использования @_private необходимо включить приватные импорты в модуле с помощью флага -enable-private-imports и использовать условную компиляцию в тестах.

⚠️ Рекомендуется использовать @_private только в тестах, оборачивая его в условные флаги компиляции для обеспечения гибкости и возможности отключения при изменениях в Swift.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥11🔥1
⚡️ Срочно!

На днях команда Swift выпустила…новый инструмент управления многопоточностью Swift SDK для Android 🤔

Странный шаг, честно говоря. KMP вроде бы не стал панацей, с чего вдруг это сработает в обратную сторону…

ℹ️ Но если серьезно, то Swift SDK для Android доступен для загрузки с установщика Windows или отдельно для Linux и macOS.

➡️ Опубликовано руководство по началу работы, которое поможет разработчикам настроить свой первый код на Swift для Android.

➡️ Более 25% пакетов в Swift Package Index уже совместимы с Android, что упрощает портирование существующих пакетов.

➡️ Рабочая группа по Android разрабатывает документ видения, который определит приоритетные направления для будущей работы с Swift на Android.

Скажите честно, ждали?
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯7👍5❤‍🔥1
Thread-Safe Classes: GCD vs Actors

⚙️ Многопоточность и гонки данных являются распространенными проблемами в программировании, особенно при работе с общими ресурсами, такими как словари.

➡️ Использование конкурентной очереди и синхронных/асинхронных вызовов позволяет создать потокобезопасный кэш, предотвращая гонки данных и обеспечивая целостность состояния.

➡️ Лучшей практикой является использование барьеров для обеспечения эксклюзивного доступа к ресурсам при записи, что позволяет одновременно выполнять чтение.

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

✔️ Сравнение различных подходов к потокобезопасности показывает, что использование акторов является наиболее современным и безопасным методом для работы с многопоточностью в Swift.

Хорошая статья с кучей примеров, рекомендую к прочтению. 👍
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤‍🔥1
Singletons with Swift Concurrency

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

⚠️ Рекомендуется избегать использование синглтонов и вместо этого использовать паттерн корня компоновки или передавать аргументы в функции.

🔍 Аннотация @MainActor позволяет гарантировать потокобезопасный доступ к синглтону, что упрощает аудит и выявление проблем в коде.

➡️ Среди альтернатив синглтонам рассматриваются кастомные актеры, использование блокировок и аннотация @unchecked Sendable, но каждая из этих опций имеет свои недостатки.

😲 А вы знали, что у Apple есть тоже документация по синглтонам?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Understanding task cancellation and lifetimes in Swift concurrency

ℹ️ В Swift structured concurrency связывает время жизни асинхронной работы с областью, в которой она была создана, автоматически отменяя задачи при завершении этой области.

➡️ Несструктурированные задачи, созданные с помощью Task { ... }, работают независимо и требуют ручной отмены, в то время как Task.detached выполняется полностью независимо от контекста вызова.

➡️ При работе с долгоживущими задачами, такими как AsyncStream, важно управлять временем жизни задачи, чтобы избежать бесконечного выполнения.

⚠️ Отмена задач в Swift не останавливает их немедленно, а устанавливает флаг отмены, который асинхронные операции могут проверять для корректного завершения.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3