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
⚡4
Сам себе Шерлок: 7 способов найти логи и поймать баг на iOS
Очередная база - лонгрид про логи⚙️
🖥 Статья описывает 7 проверенных способов сбора логов на iOS, включая использование .ips файлов,
❓ Логи делятся на креш-отчёты, диагностические и аналитические данные, которые помогают выявить причины сбоев и проблем с производительностью приложения.
❓ Для работы с логами могут потребоваться инструменты, такие как
👀 Логи помогают разработчикам и тестировщикам убедиться в вызове функций, отслеживать сетевые запросы и выявлять ошибки, которые не отображаются на UI.
⚠️ Рекомендуется собирать логи сразу после инцидента, так как старые .ips файлы автоматически удаляются системой.
Очередная база - лонгрид про логи
log collect CLI, Xcode и утилиты Console.Xcode, libimobiledevice и Apple Configurator, а также доступ к устройству по проводу или Wi-Fi.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
Testing Private Members in Swift with @_private(sourceFile:)
👀 Атрибут
❓ Ранее разработчики могли либо делать приватные члены внутренними, что нарушает инкапсуляцию, либо тестировать только через публичные API, что усложняет отладку.
⚙️ Для использования
⚠️ Рекомендуется использовать
@_private(sourceFile:) в Swift позволяет тестировать приватные члены классов, обходя контроль доступа, что полезно для написания более точных юнит-тестов.@_private необходимо включить приватные импорты в модуле с помощью флага -enable-private-imports и использовать условную компиляцию в тестах.@_private только в тестах, оборачивая его в условные флаги компиляции для обеспечения гибкости и возможности отключения при изменениях в Swift.Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥1❤1🔥1
На днях команда Swift выпустила…
Странный шаг, честно говоря.
KMP вроде бы не стал панацей, с чего вдруг это сработает в обратную сторону… Swift SDK для Android доступен для загрузки с установщика Windows или отдельно для Linux и macOS.Swift для Android.Swift Package Index уже совместимы с Android, что упрощает портирование существующих пакетов.Android разрабатывает документ видения, который определит приоритетные направления для будущей работы с Swift на Android.Please open Telegram to view this post
VIEW IN TELEGRAM
🤯7👍5❤🔥2
Thread-Safe Classes: GCD vs Actors
⚙️ Многопоточность и гонки данных являются распространенными проблемами в программировании, особенно при работе с общими ресурсами, такими как словари.
➡️ Использование конкурентной очереди и синхронных/асинхронных вызовов позволяет создать потокобезопасный кэш, предотвращая гонки данных и обеспечивая целостность состояния.
➡️ Лучшей практикой является использование барьеров для обеспечения эксклюзивного доступа к ресурсам при записи, что позволяет одновременно выполнять чтение.
➡️ Акторы обеспечивают безопасность параллелизма, позволяя только одной задаче одновременно получать доступ к изолированному состоянию, что упрощает синхронизацию.
✔️ Сравнение различных подходов к потокобезопасности показывает, что использование акторов является наиболее современным и безопасным методом для работы с многопоточностью в Swift.
Хорошая статья с кучей примеров, рекомендую к прочтению.👍
Хорошая статья с кучей примеров, рекомендую к прочтению.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤🔥2
Singletons with Swift Concurrency
🖥 Синглтоны представляют собой глобальное состояние, что делает их источником проблем в многопоточном окружении, так как они не являются потокобезопасными.
⚠️ Рекомендуется избегать использование синглтонов и вместо этого использовать паттерн корня компоновки или передавать аргументы в функции.
🔍 Аннотация
➡️ Среди альтернатив синглтонам рассматриваются кастомные актеры, использование блокировок и аннотация
😲 А вы знали, что у Apple есть тоже документация по синглтонам?
@MainActor позволяет гарантировать потокобезопасный доступ к синглтону, что упрощает аудит и выявление проблем в коде.@unchecked Sendable, но каждая из этих опций имеет свои недостатки.Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Understanding task cancellation and lifetimes in Swift concurrency
ℹ️ В Swift
➡️ Несструктурированные задачи, созданные с помощью
➡️ При работе с долгоживущими задачами, такими как
⚠️ Отмена задач в Swift не останавливает их немедленно, а устанавливает флаг отмены, который асинхронные операции могут проверять для корректного завершения.
structured concurrency связывает время жизни асинхронной работы с областью, в которой она была создана, автоматически отменяя задачи при завершении этой области.Task { ... }, работают независимо и требуют ручной отмены, в то время как Task.detached выполняется полностью независимо от контекста вызова.AsyncStream, важно управлять временем жизни задачи, чтобы избежать бесконечного выполнения.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Combine – швейцарский нож iOS-разработчика. Или нет?
ℹ️
⚙️ Основные компоненты Combine включают
➡️
⚠️ Важно помнить о сохранении подписок, так как их отсутствие может привести к потере данных, а также учитывать, что
❓ А вы пользуетесь
Combine — это фреймворк для работы с асинхронными событиями в декларативном стиле, который упрощает управление потоками данных и избавляет от сложностей, связанных с колбэками.Publisher, Subscriber и Subscription, которые взаимодействуют для передачи и обработки данных.Combine активно используется в SwiftUI через аннотации @Published и @ObservedObject, что позволяет автоматически обновлять интерфейс при изменении данных.@Published не сравнивает значения, что может вызвать лишние обновления.Combine?Please open Telegram to view this post
VIEW IN TELEGRAM
👍8👎2
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 не адаптированы к строгой проверке параллелизма
💡 Метод MainActor.assumeIsolated позволяет безопасно создавать
❌ Несмотря на попытки добавить аннотации
А вы применяли эту функцию, кроме как при отладке?🤔
Swift 6, что создает сложности для разработчиков при компиляции кода.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
👍6❤2🔥2
MainActorMessage & AsyncMessage: Concurrency-safe notifications
🆕 Apple представила новые протоколы
📣 Старый способ наблюдения за уведомлениями вызывает предупреждения о потокобезопасности, даже если они обрабатываются в главном потоке, из-за неявной изоляции.
ℹ️ Использование новых API позволяет избежать предупреждений о потокобезопасности и упрощает код, делая его более читаемым и безопасным.
ℹ️ Протокол
MainActorMessage и AsyncMessage, которые обеспечивают потокобезопасные уведомления, доступные с iOS и macOS 26+. 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
👍3❤2
How to perform a lightweight migration in Core Data
➡️ Легкая миграция в
🖥 Для выполнения легкой миграции необходимо: включить миграцию, создать новую версию модели и внести изменения в новую модель.
⚠️ При использовании
ℹ️ Создайте новую версию модели через Xcode, чтобы избежать ошибок несовместимости при изменении существующей модели.
ℹ️
Core Data позволяет автоматически переносить совместимые изменения в модели без потери данных.NSPersistentContainer легкая миграция активируется автоматически. Для ручной настройки используйте параметры NSMigratePersistentStoresAutomaticallyOption и NSInferMappingModelAutomaticallyOption.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
👍3❤2
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
❤🔥4❤1👍1