Kodeco выпустили свежий туториал по observability в iOS.
Ребята показали, как использовать OpenTelemetry на мобильных устройствах:
Инструмент мощный — в умелых руках можно построить полную картину поведения приложения, почти как на сервере.
DX, конечно, в Senty гораздо выше, и продукт мощнее, но за это надо платить.
У инструментов разные акценты:
👉 OpenTelemetry — открытый стандарт, гибкость, но больше ручной настройки.
👉 Sentry — готовая экосистема, но с ограничениями по лицензии и стоимости.
И в итоге вопрос не в “что выбрать”, а зачем вообще наблюдаемость нужна.
Даже базовый уровень метрик и логов, как в туториале, даёт огромный потенциал для роста — понимания производительности, стабильности и пользовательского опыта.
📈 Наблюдаемость — ключ к зрелой мобильной разработке.
Это то, что помогает не просто чинить баги, а понимать продукт изнутри.
#L #iOS #observability #OpenTelemetry #Sentry #MetricKit #performance #mobileengineering
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4💋2
Казалось бы, тема пройдена вдоль и поперек, однако на технических интервью я периодически встречаю недопонимание принципов работы ARC даже у опытных разработчиков
⚡️Самый важный момент:
ARC "живет" только при компиляции
Он не отслеживает объекты в рантайме, не решает, когда освобождать память. Его задача - вставить в скомпилированный код вызовы функций, которые при MRC в Objective-C разработчик расставляет самостоятельно:
👉 objc_retain(ptr) - увеличивает счетчик ссылок объекта
👉 objc_release(ptr) - уменьшает счетчик
👉 objc_autorelease(ptr) - отложенное уменьшение счетчика, сегодня редкий кейс, об этом чуть ниже
Роль рантайма же - слепое исполнение инструкций. Если счётчик достигает нуля, объект немедленно деаллоцируется: вызывается deinit, освобождаются stored-свойства, память возвращается в кучу.
Что до счётчика ссылок - он хранится в заголовке объекта в куче и создаётся при аллокации объекта. Из Swift-кода доступа туда не получить
Используется редко, но стоит упомянуть в контексте autoreleasepool. ARC вставляет autorelease только тогда, когда на этапе компиляции не может точно определить момент окончания владения объектом:
👉 Границы Swift ↔ Objective-C
👉 Объекты с атрибутом
@autorelease
Важный момент: autorelease не откладывает деаллокацию. Он откладывает выполнение release в конце блока autoreleasepool, итерации runloop'а или при завершении потока
Именно поэтому autoreleasepool внутри циклов так важен для управления памятью. Без него множество больших объектов будут накапливаться в пуле до конца итерации runloop'а, вызывая скачок потребления памяти
Итоговая модель выглядит так:
1️⃣ Swift-код
2️⃣ ARC на этапе компиляции вставляет вызовы retain/release/autorelease
3️⃣ Рантайм аллоцирует объект с заголовком
4️⃣ Retain → увеличивает счётчик. Autorelease → добавляет объект в пул (счётчик не меняется)
5️⃣ Пул завешается → выполняются release для всех объектов в пуле
6️⃣ Если счётчик == 0 → немедленная деаллокация.
💫 Надеюсь, сегодня мне удалось повысить понимание этого процесса: что решает компилятор, что слепо исполняет рантайм и где ответственность переходит к разработчику
📎 Что почитать?
Постарше
Посвежее
Очень старая дока по ObjC, но многое актуально и для Swift
#iOS #Swift #ARC #MemoryManagement #Performance
Please open Telegram to view this post
VIEW IN TELEGRAM
Medium
Understanding Autorelease Pool in Swift for iOS Development
What is an Autorelease Pool?
❤5🔥3 2 1
some View и AnyView в SwiftUI. Тема не новая, но споры о правильном использовании периодически возвращаются.Коротко:
some View сохраняет конкретный тип View на этапе компиляции.AnyView стирает тип и оставляет только «какой-то View» на этапе выполнения.Когда мы пишем:
var body: some View {
Text("Cowabunga")
}Мы говорим компилятору:
тип конкретный и известен, но имя типа скрыто.
SwiftUI при этом:
- строит статическое дерево типов
- может оптимизировать diff
- лучше отслеживает identity View
- эффективнее обновляет UI
А с
AnyView:AnyView(Text("Cowabunga"))Мы теряем информацию о реальном типе и часть работы переносится в runtime.
SwiftUI больше не знает:
- какая структура View внутри
- как оптимизировать обновления
🍕 Классический пример
func content(isLoggedIn: Bool) -> some View {
if isLoggedIn {
return HomeView()
} else {
return LoginView()
}
}Компилятор ругается, потому что возвращаются разные типы.
Можно быстро пофиксить так:
func content(isLoggedIn: Bool) -> AnyView {
if isLoggedIn {
return AnyView(HomeView())
} else {
return AnyView(LoginView())
}
}Работает, но ухудшает оптимизации SwiftUI, да и ревью вряд ли пройдет.
ViewBuilder.@ViewBuilder
func content(isLoggedIn: Bool) -> some View {
if isLoggedIn {
HomeView()
} else {
LoginView()
}
}
SwiftUI создаёт:
ConditionalContent<HomeView, LoginView>
И сохраняет типовую информацию для оптимизаций.
Когда
AnyView действительно нужен:- массив разных View
- runtime injection View
- API, где нельзя использовать generics
Например:
let cells: [AnyView] = [
AnyView(ProfileHeaderView()),
AnyView(SettingsRow(...))
]
Если SwiftUI может знать тип на этапе компиляции → используем
some View.Если тип появляется только во время выполнения → используем
AnyView.AnyView не зло, но его легко начать использовать как костыль. Поэтому имеет смысл ограничивать использование или подсвечивать его линтером.#R #SwiftUI #Performance #Architecture
Please open Telegram to view this post
VIEW IN TELEGRAM