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

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

По всем вопросам обращаться к @itereznikov
Download Telegram
Не могу не поделиться важной и крутой инфой: мой друг выпустил 10 часовой бесплатный курс!!! про iOS разработку для начинающих 🔥

Если вы начали изучать Swift – обязательно к просмотру. И не забывайте делиться с теми, кто тож хочет начать этот увлекательный путь.

https://www.youtube.com/watch?v=SUKocLwjA5k
🔥8👍52
Как Swift Runtime влияет на производительность iOS-приложений

⚡️ Тут наши ребята рассказывают про производительность - супер объемный и полезный обзор. Вот лишь несколько моментов.

⚙️ Swift Runtime играет ключевую роль в производительности iOS-приложений, особенно в управлении памятью и проверке соответствия типов, что может значительно замедлить работу приложения.

‼️ Метод swift_conformsToProtocolMaybeInstantiateSuperclasses является узким местом производительности, так как он может занимать от 1 до 3 мс на каждом вызове, особенно при использовании операторов as? и as! или методов String(describing:) и String(reflecting:).

⚠️ Рекомендуется избегать использования String(describing:) и операторов as? и as!, а также минимизировать использование type-generic-constraint-ов для повышения производительности приложения.

🤫 Использование type-generic-constraint-ов может значительно замедлить приложение, так как каждый вызов метода swift_conformsToProtocolMaybeInstantiateSuperclasses требует проверки
соответствия для каждого протокола.

💯 Рекомендую к прочтению.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
Swift Default Value in String Interpolations

🔥 Swift 6.2 улучшает интерполяцию строк с опциональными значениями, позволяя использовать параметр значения по умолчанию.

При интерполяции строк с опционалами компилятор выдает предупреждение, если не указано значение по умолчанию.

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

// The count is not set
Text("The count is \(count, default: "not set")")
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Строки в Swift

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

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

🖥 Строки могут быть представлены в различных кодировках, таких как unicodeScalars, utf16 и utf8, каждая из которых имеет свои особенности и количество кодовых точек. Сами же строки используют оптимизацию Copy-on-Write, что позволяет эффективно управлять памятью и ускорять доступ к данным.

➡️ Строки Swift могут быть конвертированы в NSString и обратно, что позволяет использовать их в проектах, где смешиваются Swift и Objective-C.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Command tools, threads and QoS

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

macOS использует различные уровни QoS для распределения потоков по ядрам процессора, что влияет на производительность. QoS варьируется от 9 (background) до 33 (userInteractive).

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

🚩 Feature flags в Swift позволяют включать и отключать определенные функциональности. В статье автор приводит в пример в зависимости от конфигурации сборки, таких как Debug, TestFlight и App Store.

По умолчанию в Xcode есть две конфигурации: Debug и Release. Рекомендуется создавать дубликаты для App Store и TestFlight для управления функциональностью.

🔥 Создание перечисления Distribution и структуры FeatureFlags позволяет управлять доступом к функциям в зависимости от текущей конфигурации сборки.

ℹ️ Такой механизм следует рассматривать как временный инструмент и удалять флаги, когда функция готова. Рассмотрите возможность удаленной настройки для мгновенного включения или отключения функций. Крайне полезный инструмент.

public struct FeatureFlags: Sendable, Decodable {
public let requirePaywall: Bool
public let requireOnboarding: Bool
public let featureX: Bool

public init(distribution: Distribution) {
switch distribution {
case .debug:
self.requirePaywall = true
self.requireOnboarding = true
self.featureX = true
case .appstore:
self.requirePaywall = true
self.requireOnboarding = true
self.featureX = false
case .testflight:
self.requirePaywall = false
self.requireOnboarding = true
self.featureX = true
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
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
2
Сам себе Шерлок: 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👍4❤‍🔥1
Thread-Safe Classes: GCD vs Actors

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

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

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

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

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

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

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

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

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

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

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