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

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

По всем вопросам обращаться к @itereznikov
Download Telegram
A deep dive into Collections, Sequences, and Iterators in Swift

⚙️ Sequence в Swift — это базовая единица итерации, которая требует от типа, чтобы он предоставлял новый итератор каждый раз при вызове makeIterator().

🔼 Collection расширяет Sequence, обеспечивая многократную итерацию, стабильный порядок и доступ к индексам, что позволяет оптимизировать производительность.

ℹ️ Цикл for … in фактически преобразуется в вызов makeIterator() и последующий вызов next() для получения элементов, что позволяет избежать ошибок при изменении коллекции во время итерации.

💡 Swift Concurrency вводит AsyncSequence и AsyncIteratorProtocol, позволяя использовать асинхронные итераторы с поддержкой приостановки и обработки ошибок.

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

struct Countdown: Sequence {
let start: Int

func makeIterator() -> Iterator {
Iterator(current: start)
}

struct Iterator: IteratorProtocol {
var current: Int

mutating func next() -> Int? {
guard current >= 0 else { return nil }
defer { current -= 1 }
return current
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Using MainActor.assumeIsolated to Solve Legacy API Compatibility Issues with Swift 6

😨 Многие устаревшие API Apple не адаптированы к строгой проверке параллелизма Swift 6, что создает сложности для разработчиков при компиляции кода.

💡 Метод MainActor.assumeIsolated позволяет безопасно создавать UIHostingController в синхронном контексте, что решает проблемы с компиляцией при использовании устаревших API в контексте примера из статьи.

public static func assumeIsolated<T>(_ operation: @MainActor () throws -> T, file: StaticString = #fileID, line: UInt = #line) rethrows -> T where T : Sendable


Несмотря на попытки добавить аннотации @MainActor, компилятор Swift 6 продолжает выдавать ошибки, если код не соответствует требованиям изоляции.

А вы применяли эту функцию, кроме как при отладке? 🤔
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Safer Swift: How ~Copyable Prevents Hidden Bugs

Протокол ~Copyable в Swift 5.9 предотвращает неявное копирование объектов, требуя явного управления владением данными.

⚠️ Копирование структуры, содержащей указатель на файл, может привести к ошибкам, когда оба экземпляра записывают в один и тот же файл.

✔️ Добавление ~Copyable к структуре предотвращает компиляцию кода, если происходит попытка использовать объект после его передачи.

🖥 Краткая справка по модификаторам: borrow (временный доступ для чтения), consume (полное владение) и inout (временный доступ для изменения).

struct FileHandleWrapper: ~Copyable {
let handle: UnsafeMutablePointer<FILE>

init(path: String, mode: String) {
guard let file = fopen(path, mode) else {
fatalError("Failed to open file")
}
self.handle = file
}

func write(_ text: String) {
fputs(text, handle)
}

deinit {
print("Closing file handle")
fclose(handle)
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Prompting users to review your app

🟢 Количество отзывов и их оценки критически важны для успеха вашего приложения в App Store, так как они влияют на алгоритмы рекомендаций и доверие пользователей.

✔️ Используйте RequestReviewAction из StoreKit 2, чтобы запрашивать отзывы у пользователей до трех раз в год, избегая прерывания их работы в приложении.

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

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

private func presentReview() {
guard ReviewPromptManager.shared.canRequestReview() else { return }

Task {
try? await Task.sleep(for: .seconds(2))
await requestReview()
ReviewPromptManager.shared.markReviewRequested()
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62🔥2
MainActorMessage & AsyncMessage: Concurrency-safe notifications

🆕 Apple представила новые протоколы MainActorMessage и AsyncMessage, которые обеспечивают потокобезопасные уведомления, доступные с iOS и macOS 26+.

📣 Старый способ наблюдения за уведомлениями вызывает предупреждения о потокобезопасности, даже если они обрабатываются в главном потоке, из-за неявной изоляции.

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

ℹ️ Протокол AsyncMessage позволяет отправлять уведомления асинхронно из любого контекста изоляции, что улучшает гибкость обработки уведомлений.

struct RecentBuildsChangedMessage: NotificationCenter.AsyncMessage {
typealias Subject = [RecentBuild]

let recentBuilds: Subject
}

extension NotificationCenter.MessageIdentifier where Self == NotificationCenter.BaseMessageIdentifier<RecentBuildsChangedMessage> {

static var recentBuildsChanged: NotificationCenter.BaseMessageIdentifier<RecentBuildsChangedMessage> {
.init()
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32
How to perform a lightweight migration in Core Data

➡️ Легкая миграция в Core Data позволяет автоматически переносить совместимые изменения в модели без потери данных.

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

⚠️ При использовании NSPersistentContainer легкая миграция активируется автоматически. Для ручной настройки используйте параметры NSMigratePersistentStoresAutomaticallyOption и NSInferMappingModelAutomaticallyOption.

ℹ️ Создайте новую версию модели через Xcode, чтобы избежать ошибок несовместимости при изменении существующей модели.

ℹ️Core Data поддерживает изменения, такие как добавление, переименование или удаление сущностей и атрибутов, а также изменение типов отношений.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
GSoC 2025 Showcase: Improved Code completion for Swift

🆕 Если вы вдруг пропустили - проект улучшает отображение документации во время автозаполнения кода в SourceKit-LSP, позволяя видеть полную документацию вместо кратких аннотаций.

🖥 Основная цель проекта - показать полную документацию для элементов автозаполнения и реализовать поддержку запроса помощи по сигнатурам, показывая доступные перегрузки и их документацию.

🔥 Успешно реализовано извлечение полной документации по запросу и значительная часть поддержки помощи по сигнатурам, что улучшает опыт работы в редакторах, таких как VS Code и Neovim.

Признавайтесь, а вы уже пишите под Swift на VS Code или планируете?
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Building Peer-to-Peer Sessions: Sending and Receiving Data with Multipeer Connectivity

Для начала работы с Multipeer Connectivity необходимо создать объект MCPeerID для идентификации устройства и MCSession для установления канала связи между устройствами.

➡️ Данные отправляются с помощью метода send(_:toPeers:with:), где строка сообщения преобразуется в формат Data с кодировкой UTF-8. Обработка ошибок обязательна для успешной передачи.

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

➡️ Метод session(_:didReceive:fromPeer:) используется для обработки полученных данных, которые преобразуются обратно в строку и добавляются в массив полученных сообщений.

Для приглашения другого устройства в сессию используется метод invitePeer(_:using:), который позволяет отправить приглашение на подключение.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Меня снова спросили за Optional

Очередная база 🤩

➡️Опционалы представляют собой перечисление с двумя кейсами: .none и .some(T), что позволяет создавать универсальные контейнеры для различных типов данных.

✔️ Для инициализации опционалов без использования кейсов необходимо подписать их под протоколы ExpressibleByNilLiteral и ExpressibleByIntegerLiteral, что позволяет использовать nil и литералы напрямую.

⚠️ Наиболее популярный способ распаковки опционалов — это оператор nil-coalescing (??), который позволяет подставить значение по умолчанию, если опционал пустой.

ℹ️ Для реализации сравнения опционалов необходимо сначала реализовать протокол Equatable, а затем Comparable, что позволяет использовать операторы равенства и сравнения.

enum MyOptional<T> {
case none
case some(T)
}

extension MyOptional: ExpressibleByIntegerLiteral where T == Int {
init(integerLiteral value: Int) {
self = .some(value)
}
}

extension MyOptional {

static func ?? (optional: MyOptional<T>, defaultValue: @autoclosure () -> T) -> T {
switch optional {
case .none:
return defaultValue()

case let .some(unwrappedValue):
return unwrappedValue
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
К какому компоненту отнести тот или иной класс? Мой опыт разделения функциональности между компонентами

🔥 Интересная статья про модулирование архитектуры, зависимостей и организацию проекта в целом.

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

Устойчивость компонента можно оценить с помощью метрики I, которая рассчитывается как Fan-out ÷ (Fan-in + Fan-out), где значение 0 указывает на максимальную устойчивость.

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

✔️ Принципы REP, CCP и CRP помогают определить, как компоненты должны быть связаны, чтобы обеспечить удобство сопровождения и повторного использования, избегая ненужных зависимостей.

На начальных этапах разработки важнее удобство сопровождения, тогда как на более зрелых стадиях акцент смещается на удобство повторного использования компонентов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32
Improving the approachability of data-race safety

🖥 Документ из Swift Evolution описывает видение по повышению удобства Swift 6 concurrency, фокусируясь на устранении ложных ошибок data-race safety в последовательном коде и упрощении миграции. Основные цели — сохранить безопасность памяти, сделать базовый concurrency простым и продвинутое — естественным, с тремя этапами: последовательный код, async без параллелизма, затем parallelism для производительности.

Модель Swift 6 предполагает конкурентность по умолчанию, что приводит к ложным срабатываниям ошибок в коде, который на самом деле является однопоточным.

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

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

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

ℹ️ Хоть документ и не новый, рекомендую с ним ознакомиться - сможете лучше понимать куда в целом движется развитие языка.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Bridging completion handlers to Swift's async/await

🔍 Если хотели провести миграцию с completion handlers на async/await - загляните в статью. Вот пару советов из нее.

✔️ Функция withCheckedContinuation позволяет создать асинхронную функцию, которая обрабатывает результат из API с обработчиком завершения, обеспечивая безопасное возобновление выполнения.

⚠️ Для API, которые могут возвращать ошибки, можно использовать withCheckedThrowingContinuation, что позволяет обрабатывать ошибки с помощью синтаксиса try await.

🛡 withCheckedContinuation и withCheckedThrowingContinuation обеспечивают проверку на наличие множественных вызовов resume, в то время как withUnsafeContinuation и withUnsafeThrowingContinuation не выполняют таких проверок, что делает их менее безопасными.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥41👍1