iOS App Launch Optimization: How Cityflo Achieved 2.22x Faster Load Times
Запуск приложения кажется незаметным, пока не становится долгим. И чем больше логики тем сложнее это оптимизировать.
В статье автор поделился опытом ускорения запуска приложения с рассмотрением всех моментов, на которые они сделали упор после анализа времени запуска: оптимизацию библиотек, ленивая инициализация, рефакторинг AppDelegate, удаление избыточной логики и оптимизация последовательности вызовов API.
Запуск приложения кажется незаметным, пока не становится долгим. И чем больше логики тем сложнее это оптимизировать.
В статье автор поделился опытом ускорения запуска приложения с рассмотрением всех моментов, на которые они сделали упор после анализа времени запуска: оптимизацию библиотек, ленивая инициализация, рефакторинг AppDelegate, удаление избыточной логики и оптимизация последовательности вызовов API.
Medium
iOS App Launch Optimization: How Cityflo Achieved 2.22x Faster Load Times
In the fast-paced world of mobile apps, first impressions matter. And what’s the first thing users experience when they open your app? The…
👍3❤2
Streamlining NotificationCenter Usage in Swift
Автор описывает интересный подход использования NotificationCenter у себя в проекте: создание протокола с расширением, содержащим некоторые реализации функций. Это позволяет поддерживать чистоту в коде, а также дает возможность проводить тестирование такой функциональности.
Автор описывает интересный подход использования NotificationCenter у себя в проекте: создание протокола с расширением, содержащим некоторые реализации функций. Это позволяет поддерживать чистоту в коде, а также дает возможность проводить тестирование такой функциональности.
Medium
Streamlining NotificationCenter Usage in Swift
If you’re a Swift developer, NotificationCenter is probably no stranger to you, right? We often use this syntax to trigger functions in our…
❤🔥2
Как вернуть контроль над состоянием данных с 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