В этом году App Intents получили значительные улучшения. Теперь можно глубже интегрировать контент приложения в iOS через Spotlight, Shortcuts и виджеты. Всет это работает через фреймворк App Intents. App Intents является основой для создания возможностей для Apple Intelligence. Новые API для индексирования объектов приложения в Spotlight:
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Мы часто ищем способы оптимизации кода, даже там где это не требуется. Но иногда все таки бывают случаи, когда приходится оптимизировать критическую секцию. В статье приводится пример использования формулы Гауса для такой оптимизации.
Карл Фридрих Гаусс предложил формулу для вычисления суммы чисел от 1 до n. Формула имеет постоянную сложность O(1), что делает её очень быстрой. Формула Гаусса работает в 10 625 000 раз быстрее, чем методы loop и reduce. В игровом приложении для отображения таблицы лидеров используется формула Гаусса. Так же можно использовать для поиска пропущенных чисел в последовательности.
Не совсем про Swift, зато полезно
Please open Telegram to view this post
VIEW IN TELEGRAM
❤18👍5🤔1
Начнем год с прозрачных советов вокруг непрозрачных типов Swift. Протоколы с требованиями
associatedtype
или Self
создают проблемы при использовании в качестве параметров или возвращаемых типов. Исторически разработчики использовали дженерики для обхода этих ограничений, что усложняло код:protocol Store {
associatedtype Item
func persist(item: Item)
}
Протокол Store имеет связанный тип Item. Функция
persist
требует конкретный тип Item
.Использование протокола Store в качестве параметра или возвращаемого типа приведет к ошибке компиляции:
// Error: Protocol 'Store' can only be used as a generic constraint because it has Self or associated type requirements.
func cleanup(store: Store) {}
Определение функции как "дженерик" позволяет обойти проблему:
func cleanup<T: Store>(store: T) {
}
Поддержка такого кода становится сложнее. Непрозрачные же типы упрощают использование протоколов с associatedtype. Функция может быть определена как функция с параметром
some Store
:func cleanup(store: some Store) {
// Simplified function declaration.
}
В этом случае компилятор автоматически подставляет конкретный тип параметра при компиляции.
Непрозрачные типы являются синтаксическим сахаром для универсального кода. Они упрощают взаимодействие с протоколами с associatedtype
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤2
Метод жизненного цикла
onAppear
в SwiftUI важен для внедрения ключевой логики при отображении View. Со времен использования UIKit мы привыкли что вызовов методов жизненного цикла всегда предсказуем и последователен. В SwiftUI же, в некоторых сценариях, onAppear
может быть вызван неожиданно и без необходимости, что снижает производительность или даже вызывает неконтролируемые изменения состояния приложения. В статье рассматриваются две проблемы, связанные с вызовом onAppear
в SwiftUI, и предлагаются временные контрмеры:NavigationStack
находится внутри условной ветви, после того как пользователь переходит на новую страницу, а затем меняет состояние ветви (переключается на ветвь, не включающую NavigationStack
), все вызовы onAppear
в корневом View замыкания NavigationStack
(если их несколько) срабатывают ненормально (последняя ссылка onAppear
не должна появляться)NavigationStack
, все вызовы onAppear в представлении Tab AA
срабатывают ненормально, независимо от того, находятся ли они внутри или снаружи контейнера навигации.Причины и последствия
Проблема возникает из-за того, что навигационный контейнер находится внутри условной ветви и выполняет определенные операции. Так работает как минимум до iOS 15. Такие лишние вызовы могут привести к непредсказуемым изменениям в состоянии приложения, особенно при изменении глобального состояния.
Решения:
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡3
В статье автор делится не самым удачным опытом разделения приложения на мелкие модули для улучшения производительности компиляции. Несмотря на то что Xcode эффективно параллелит компиляцию отдельных не связанных модулей, при переходе на Xcode 16 этот подход стал «играть против» времени сборки, т.к. каждый модуль компилятор дополнительно начал проверять.
Конфигурация проекта: 36 отдельных фреймворков, 33 из них статические. Все статические фреймворки бандлятся в один динамический фреймвок.
Если профилировать компиляцию (
Product > Perform Action > Build with Timing Summary
), можно заметить что львиную часть времени занимает процесс верификации. Согласно документации, верификация позволяет выявлять и устранять проблемы с модулем фреймворка перед его распространением. Вот некоторые примеры таких проблем:""
в import вместо <>
@import
в ваших публичных и частных заголовкахC
импортамиКак можно понять, не каждое приложение все еще имеет совместную кодовую базу Swift и Obj-C в каждом фреймворком, и уж точно работа с чистым C не является популярной.
Таким образом, можно отключить эту проверку через флаг
ENABLE_MODULE_VERIFIER
для DEBUG сборок и сократить время компиляции. В случае автора получился значительный буст, время компиляции сократилось с 3.5 минут до 52 секундPlease open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍3❤1
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🤔1
This media is not supported in your browser
VIEW IN TELEGRAM
XCTest использует простые комментарии для добавления контекста в тестовые примеры. Swift Testing предоставляет специальный признак
bug
для передачи краткого описания ошибки. Ключевым преимуществом является видимость названия ошибки в результатах тестирования и в интерфейсе Xcode. Особенно удобно, если вы придерживаетесь TDD, предоставляя доказательства устранения ошибки своими тестами. В статье приводится сравнение с XCTest, скорее, для того чтобы показать что именно заменяет новый синтаксис. Врядли кто-то осознанно выберет XCTest для нового проекта
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2⚡1
Очень полезная статья для новичков с пошаговым разбором хороших практик по обеспечению параллелизма со Swift Concurrency. Реальные приложения записывают данные в локальное хранилище, удалённые сервисы и, как правило, используют изменяемое состояние. В статье создают SwiftUI приложение, которое работает с состоянием, размещённым в (придуманной) удалённой сетевой службе.
Новичкам я бы не советовал "просто" повторять все что приводится в статье, а скорее вдумчиво прочитать и повторить в своем pet-проекте подглядывая в статью
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9