Как вернуть контроль над состоянием данных с RemoteResult
Автор предлагает расширить Result, чтобы сделать его более удобным и преварить его в:
Это позволит лучше управлять состоянием данных и реагирововать на состояние загрузки и «простоя». RemoteResult может быть адаптирован для использования в архитектурах программирования, таких как The Composable Architecture, путем внесения простых изменений для совместимости с логикой сравнения состояний.
Автор предлагает расширить Result, чтобы сделать его более удобным и преварить его в:
enum RemoteResult<Success, Failure: Error> {
case idle
case loading
case success(Success)
case failure(Failure)
}
Это позволит лучше управлять состоянием данных и реагирововать на состояние загрузки и «простоя». RemoteResult может быть адаптирован для использования в архитектурах программирования, таких как The Composable Architecture, путем внесения простых изменений для совместимости с логикой сравнения состояний.
NOP::Nuances of programming
Как вернуть контроль над состоянием данных с RemoteResult
Построим на основе Result универсальный способ обозначать состояния ресурса, чтобы из представлений SwiftUI реагировать на его изменения. Рассмотрим реальное применение этого перечисления и адаптируем его для архитектуры TCA.
❤3👍1😁1
Recursive enums in Swift
Рекурсивные перечисления в Swift позволяют создавать структуры данных, включающие в себя экземпляры самого себя, что полезно для моделирования вложенных или рекурсивных данных.
Рассматривается на примере рекурсивной функции для подсчета общего количества элементов в папке, включая элементы во вложенных папках и через символические ссылки.
Рекурсивные перечисления в Swift позволяют создавать структуры данных, включающие в себя экземпляры самого себя, что полезно для моделирования вложенных или рекурсивных данных.
Рассматривается на примере рекурсивной функции для подсчета общего количества элементов в папке, включая элементы во вложенных папках и через символические ссылки.
enum FileSystemItem {
case file(name: String)
case folder(name: String, items: [FileSystemItem])
indirect case alias(name: String, to: FileSystemItem)
}
Nil Coalescing
Recursive enums in Swift
This post explains how to use recursive enums in Swift, including the indirect keyword, to effectively model and manage complex, hierarchical data structures.
👍5
Subtitle Shenanigans in SwiftUI’s Menu
Компонент Menu из SwiftUI – невероятно сложный API с точки зрения сложности поддерживаемых им взаимодействий. В статье рассматриваются неочевидные способы его настройки и обсуждаются распространенные проблемы, с которыми сталкиваются разработчики при использовании HStack и VStack и предлагаются практические решения для их преодоления.
Статья еще интересна с точки зрения того, как можно разбирать документированные API и находить в них несоответствия, а также искать способы решения.
Компонент Menu из SwiftUI – невероятно сложный API с точки зрения сложности поддерживаемых им взаимодействий. В статье рассматриваются неочевидные способы его настройки и обсуждаются распространенные проблемы, с которыми сталкиваются разработчики при использовании HStack и VStack и предлагаются практические решения для их преодоления.
Статья еще интересна с точки зрения того, как можно разбирать документированные API и находить в них несоответствия, а также искать способы решения.
Jeffverkoeyen
Subtitle Shenanigans in SwiftUI’s Menu — featherless software design
👍3
viewIsAppearing
Некоторые могли пропустить, но на WWDC 2023 было представлено важное дополнение про жизненный цикл контроллера.
Этот метод вызывается после вызова viewWillAppear и перед вызовом viewWillLayoutSubviews. Отлично подходит для fine-tune'а динамического интерфейса или самой презентации контроллера.
Некоторые могли пропустить, но на WWDC 2023 было представлено важное дополнение про жизненный цикл контроллера.
Этот метод вызывается после вызова viewWillAppear и перед вызовом viewWillLayoutSubviews. Отлично подходит для fine-tune'а динамического интерфейса или самой презентации контроллера.
Apple Developer Documentation
viewIsAppearing(_:) | Apple Developer Documentation
Notifies the view controller that the system is adding the view controller’s view to a view hierarchy.
❤🔥9
Typed throws in Swift
В Swift 6.0 изменили привычный подход работы с выбрасываемыми ошибками: в прошлых версиях нельзя было указать конкретный тип. Теперь компилятор будет понимать какую именно ошибку мы будем выбрасывать.
В месте использования нам теперь не нужно лишнее приведение типов.
В Swift 6.0 изменили привычный подход работы с выбрасываемыми ошибками: в прошлых версиях нельзя было указать конкретный тип. Теперь компилятор будет понимать какую именно ошибку мы будем выбрасывать.
enum FooError: Error {
case tooBig
case tooSmall
}
func foo() throws(FooError) -> Int {
let value = Int.random(in: 1...100)
guard value < 60 else {
throw FooError.tooBig
}
guard value > 20 else {
throw FooError.tooSmall
}
return value
}
В месте использования нам теперь не нужно лишнее приведение типов.
func boo() {
do {
let value = try foo()
print(value)
} catch {
switch error {
case .tooBig:
print("Too big...")
case .tooSmall: print("Too small...")
}
}
}
⚡27
Performance Testing для iOS
Для тестирования производительности iOS приложений существуют различные способы, включая использование Xcode Organizer, MetricKit и TestFlight для анализа показателей запуска, отзывчивости интерфейса, потребления памяти и других аспектов.
В статье разобраны различные способы сбора метрик, в том числе использование блока measure для измерения производительности кода, создание signpost'ов, а также запись данных и последующий анализ результатов для определения трендов.
Для тестирования производительности iOS приложений существуют различные способы, включая использование Xcode Organizer, MetricKit и TestFlight для анализа показателей запуска, отзывчивости интерфейса, потребления памяти и других аспектов.
В статье разобраны различные способы сбора метрик, в том числе использование блока measure для измерения производительности кода, создание signpost'ов, а также запись данных и последующий анализ результатов для определения трендов.
Хабр
Performance Testing для iOS
Все мы любим, когда приложение, которым пользуемся, работает отзывчиво, быстро, а также те операции, которые мы хотим совершить, происходили максимально быстро: буть то банковское приложение или...
⚡7❤2
Upload iOS App to TestFlight with GitHub Actions and Fastlane Match
Если вы проводите деплой приложения руками и вас это достало, то это статья для вас. Автор рассказывает, как провести настройку деплоя используя fastlane, связке с GitHub Secrets для хранения ключей и GitHub actions для построения полноценного workflow.
Неплохая статья для понимания того, как работает Continuous Deployment.
Если вы проводите деплой приложения руками и вас это достало, то это статья для вас. Автор рассказывает, как провести настройку деплоя используя fastlane, связке с GitHub Secrets для хранения ключей и GitHub actions для построения полноценного workflow.
Неплохая статья для понимания того, как работает Continuous Deployment.
Bright Inventions
Upload iOS App to TestFlight with GitHub Actions and Fastlane Match – 2025 Tutorial with Example
In previous parts of a tutorial we were building app and running tests locally with fastlane and building app and running tests with usage…
⚡3🔥2
Marking Swift Properties Available by iOS Version
В текущих версиях Swift мы можем пометить структуры, классы и расширения доступными для определенных версий ОС.
Но не можем так поступить со свойствами. В статье предлагается способ сделать это с помощью старого доброго NSObject и вычисляемого свойства, для достижения такого же результата.
В текущих версиях Swift мы можем пометить структуры, классы и расширения доступными для определенных версий ОС.
@available(iOS 18.0, *)
struct GetQuoteControlWidget: ControlWidget {
// code
}
Но не можем так поступить со свойствами. В статье предлагается способ сделать это с помощью старого доброго NSObject и вычисляемого свойства, для достижения такого же результата.
private var _customTool: NSObject? = nil
@available(iOS 18.0, *)
private var customToolWrapper: PKToolPickerCustomItem {
if _customTool == nil {
let tool = PKToolPickerCustomItem(configuration: .init(identifier: someID, name: someName))
_customTool = tool
}
return _customTool as! PKToolPickerCustomItem
}
⚡7
SWIFT BUILD TIMES AND MODULE VERIFICATION
После расширения кодовой базы и рефакторинга, автор разбил приложение на множество модулей и стал замечать просадки в сборке проекта. После исследования он обнаружил, что флаг
Но стоит понимать, что этот флаг не панацея и он лишь экономит время сборки, пропуская один из этапов и перед отправкой релизной сборки его все же стоит включить обратно.
После расширения кодовой базы и рефакторинга, автор разбил приложение на множество модулей и стал замечать просадки в сборке проекта. После исследования он обнаружил, что флаг
ENABLE_MODULE_VERIFIER
был установлен в YES
. Сам флаг отвечает за верификацию модулей на этапе сборки. Автор выключил этот флаг для дебаг сборок и уменьшил время с 3,5 минут до 52 секунд.Но стоит понимать, что этот флаг не панацея и он лишь экономит время сборки, пропуская один из этапов и перед отправкой релизной сборки его все же стоит включить обратно.
pfandrade.me
Swift Build Times and Module Verification…
It’s been a while since I’ve written anything here… I guess that’s mainly because I was focusing on building Secrets 4 and did not want to write about it before it launched. Then, I lost the habit of actually writing stuff here. Let’s see if I can change…
⚡5
Benchmark Package
Не так давно был представлен новый пакет Benchmark. Его основная цель – измерение производительности. Количество метрик из коробки большое: 27.
Так же можно добавлять свои метрики.
На выходе будем получать таблицу с измерениями. Но можно сохранять данные и в других форматах.
Выглядит круто и работоспособно.
Не так давно был представлен новый пакет Benchmark. Его основная цель – измерение производительности. Количество метрик из коробки большое: 27.
Так же можно добавлять свои метрики.
На выходе будем получать таблицу с измерениями. Но можно сохранять данные и в других форматах.
Выглядит круто и работоспособно.
⚡5
Борьба с утечками памяти: от задачи до победы
Классное видео с мобиуса про борьбу с утечками памяти: тут и про работу с Memory Graph, про который не так много документации и примеры про автоматизацию поиска утечек через UI тесты.
Классное видео с мобиуса про борьбу с утечками памяти: тут и про работу с Memory Graph, про который не так много документации и примеры про автоматизацию поиска утечек через UI тесты.
⚡10
Антимат в чате на iOS: как я мешаю пользователям сквернословить
Автор делится опытом, как в чате мешал пользователям сквернословить с помощью локальных регулярных выражений. Как итог: получилось хорошо и понятно как можно дальше улучшать, но все равно, если пользователь захочет написать запрещенное слово, то он найдет способ это сделать с помощью комбинаций букв и цифр, юникод символы и прочих хитростей.
Как MVP точно пойдет и не факт, что продуктово имеет смысл делать что-то лучше.
Автор делится опытом, как в чате мешал пользователям сквернословить с помощью локальных регулярных выражений. Как итог: получилось хорошо и понятно как можно дальше улучшать, но все равно, если пользователь захочет написать запрещенное слово, то он найдет способ это сделать с помощью комбинаций букв и цифр, юникод символы и прочих хитростей.
Как MVP точно пойдет и не факт, что продуктово имеет смысл делать что-то лучше.
Хабр
Антимат в чате на iOS: как я мешаю пользователям сквернословить
Привет, Хабр! На связи снова Александр Пиманов (по-прежнему iOS-разработчик МТС Диджитал). Сегодня поделюсь своим опытом в одной интересной нишевой теме: фильтрации нецензурной лексики в приложении...
⚡4
Morphology in Swift
Проблемы с морфологией в программировании могут привести к неправильному склонению слов и неправильному грамматическому согласованию в предложениях.
С iOS 15 Foundation предлагает решение этой проблемы, позволяя автоматически обрабатывать такие ситуации и термины обращения в локализованных строках.
Для более точного управления в Swift можно использовать структуру Morphology, позволяющую выполнять ручное согласование грамматики во время выполнения.
Проблемы с морфологией в программировании могут привести к неправильному склонению слов и неправильному грамматическому согласованию в предложениях.
С iOS 15 Foundation предлагает решение этой проблемы, позволяя автоматически обрабатывать такие ситуации и термины обращения в локализованных строках.
Text("She will receive ^[\(count) games](inflect: true).")
Для более точного управления в Swift можно использовать структуру Morphology, позволяющую выполнять ручное согласование грамматики во время выполнения.
Swiftjective-C
Morphology in Swift
Morphology, or for mere humans - the study of the many forms of words, is ripe with interesting programming applications. Let's take a look at a few of them.
⚡5
Wrapping async-await with a completion handler in Swift
Статья про то, как обернуть async-await кода в completion handler. Вы столкнетесь с таким, например, если используете сторонние библиотеки, которые принимают только хендлеры, а ваша кодовая база на основе Swift Concurrency.
Статья про то, как обернуть async-await кода в completion handler. Вы столкнетесь с таким, например, если используете сторонние библиотеки, которые принимают только хендлеры, а ваша кодовая база на основе Swift Concurrency.
extension Task {
@discardableResult
init<T>(
priority: TaskPriority? = nil,
operation: @escaping () async throws -> T,
queue: DispatchQueue = .main,
completion: @escaping (Result<T, Failure>) -> Void
) where Success == Void, Failure == any Error {
self.init(priority: priority) {
do {
let value = try await operation()
queue.async {
completion(.success(value))
}
} catch {
queue.async {
completion(.failure(error))
}
}
}
}
}
⚡2
The Memory Leak: An Xcode Detective Story
История о том, как инженер пытался отладить простой по описанию баг и как глубоко он зашел. Если очень коротко, то проблема была в неправильном использовании
Понимание механизмов работы с памятью помогает избегать таких ситуаций.
История о том, как инженер пытался отладить простой по описанию баг и как глубоко он зашел. Если очень коротко, то проблема была в неправильном использовании
[weak self]
в кложуре 🫠Понимание механизмов работы с памятью помогает избегать таких ситуаций.
Emergetools
Emerge Tools Blog | The Memory Leak: An Xcode Detective Story
A deep-dive into debugging on iOS
❤4🔥2⚡1
Announcing Swift 6
Анонсировали релиз Swift 6 🥳 и нас ждет очень много изменений, вот небольшой список:
- поддержка 128-битных целых чисел
- новая библиотека синхронизации, которая включает примитивы, такие как mutex
- новый подход к выбрасыванию ошибок
- владение некопируемых типов
- расширение интеропа с C++
- новый макрос для отображения информации в LLDB @DebugDescription
- фреймворк для тестирования Swift Testing
Анонсировали релиз Swift 6 🥳 и нас ждет очень много изменений, вот небольшой список:
- поддержка 128-битных целых чисел
- новая библиотека синхронизации, которая включает примитивы, такие как mutex
- новый подход к выбрасыванию ошибок
- владение некопируемых типов
- расширение интеропа с C++
- новый макрос для отображения информации в LLDB @DebugDescription
- фреймворк для тестирования Swift Testing
Swift.org
Announcing Swift 6
We’re delighted to announce the general availability of Swift 6. This is a major new release that expands Swift to more platforms and domains.
🔥10
AVAudioSourceNode, AVAudioSinkNode: Low-Level Audio In Swift
AVAudioSourceNode – узлы AVAudio, предоставляющие способ обработки входных и выходных аудиоданных. Для работы с аудио в режиме реального времени, придется выйти на уровень работы с указателями через UnsafeMutableAudioBufferListPointer и UnsafeMutableBufferPointer. Стоит помнить, что в таком случае управление памятью ложиться на плечи разработчика.
Если вам интересна работа со звуком на низком уровне – эта статья точно для вас.
AVAudioSourceNode – узлы AVAudio, предоставляющие способ обработки входных и выходных аудиоданных. Для работы с аудио в режиме реального времени, придется выйти на уровень работы с указателями через UnsafeMutableAudioBufferListPointer и UnsafeMutableBufferPointer. Стоит помнить, что в таком случае управление памятью ложиться на плечи разработчика.
Если вам интересна работа со звуком на низком уровне – эта статья точно для вас.
Orestis Papadopoulos
AVAudioSourceNode, AVAudioSinkNode: Low-Level Audio In Swift
I'm Orestis Papadopoulos. I work as a software developer. This is my blog, I write about software, sounds and Swift.
🔥3
How to keep Date’s microseconds precision in Swift
DateFormatter в Swift теряет точность микросекунд при конвертации даты и времени, что может привести к потенциальным проблемам, например неправильной сортировке данных.
Автор предлагает использовать расширение ISO8601DateFormatter для ручного извлечения микросекунд из строки даты и добавления их к сконвертированному значению Date.
DateFormatter в Swift теряет точность микросекунд при конвертации даты и времени, что может привести к потенциальным проблемам, например неправильной сортировке данных.
Автор предлагает использовать расширение ISO8601DateFormatter для ручного извлечения микросекунд из строки даты и добавления их к сконвертированному значению Date.
extension ISO8601DateFormatter {
func microsecondsDate(from dateString: String) -> Date? {
guard let millisecondsDate = date(from: dateString) else { return nil }
guard let fractionIndex = dateString.lastIndex(of: ".") else { return millisecondsDate }
guard let tzIndex = dateString.lastIndex(of: "Z") else { return millisecondsDate }
guard let startIndex = dateString.index(fractionIndex, offsetBy: 4, limitedBy: tzIndex) else { return millisecondsDate }
// Pad the missing zeros at the end and cut off nanoseconds
let microsecondsString = dateString[startIndex..<tzIndex].padding(toLength: 3, withPad: "0", startingAt: 0)
guard let microseconds = TimeInterval(microsecondsString) else { return millisecondsDate }
return Date(timeIntervalSince1970: millisecondsDate.timeIntervalSince1970 + microseconds / 1_000_000.0)
}
}
⚡2👍2
Псевдоним типа в Swift
Ключевое слово typealias в Swift позволяет создавать удобный для восприятия код, например:
В статье больше примеров с разборами и пояснениями.
Ключевое слово typealias в Swift позволяет создавать удобный для восприятия код, например:
// Повысить восприятие кода
typealias StringDictionary<T> = Dictionary<String, T>
// Упростить сигнатуры сложных типов и кортежей
typealias CompletionHandler = (Result<String, Error>) -> Void
typealias GridPoint = (x: Int, y: Int)
// Указать ограничения
typealias StringArrayDictionary = Dictionary<String, [String]>
В статье больше примеров с разборами и пояснениями.
🔥11
Как встроить распознавание звуков в ваше iOS приложение на Swift с использованием SoundAnalysis
Если вы хотели попробовать реализовать приложения для распознавания звуков – это статья для вас.
Автор разбирает базовые концепции работы с фреймворком SoundAnalysis. При этом вы можете воспользоваться моделями из коробки, они позволяют распознавать до 300 различных звуков, либо натренировать свою модель через CreateML.
Если вы хотели попробовать реализовать приложения для распознавания звуков – это статья для вас.
Автор разбирает базовые концепции работы с фреймворком SoundAnalysis. При этом вы можете воспользоваться моделями из коробки, они позволяют распознавать до 300 различных звуков, либо натренировать свою модель через CreateML.
Хабр
Как встроить распознавание звуков в ваше iOS приложение на Swift с использованием SoundAnalysis
Введение В мире, где ваш телефон умеет угадывать настроение по плейлисту, почему бы не научить его распознавать звуки вокруг? С помощью фреймворка SoundAnalysis это проще, чем кажется. Мы расскажем,...
🔥5