State of in-app subscriptions 2025
Раньше меня очень вдохновляла возможность создавать свои личные приложения и зарабатывать на них. Я не могу назвать себя трушным и успешным инди разработчиком, который достиг невероятных высот, но веху $1k MRR я пробил.
Одна из самых сложных задач при создании продукта: монетизация, если вы не планируете играть в альтруизм. Ребята, которые делают крутой сервис – Adapty, берущий на себя почти все сложности с монетизацией, выпустили крутой отчет, который закрывает кучу вопросов:
⁃ какую длительность подписки выбрать
⁃ нужен ли триал и что он дает
⁃ на какие страны целиться
⁃ и как сделать лучший пейволл
P.S. Сейчас крутое время, чтобы попробовать создать свой пет-продукт: AI тулы и инструменты, как Adapty, сильно упрощают этот путь. Но конкуренция, конечно же, будет жесткая.
Раньше меня очень вдохновляла возможность создавать свои личные приложения и зарабатывать на них. Я не могу назвать себя трушным и успешным инди разработчиком, который достиг невероятных высот, но веху $1k MRR я пробил.
Одна из самых сложных задач при создании продукта: монетизация, если вы не планируете играть в альтруизм. Ребята, которые делают крутой сервис – Adapty, берущий на себя почти все сложности с монетизацией, выпустили крутой отчет, который закрывает кучу вопросов:
⁃ какую длительность подписки выбрать
⁃ нужен ли триал и что он дает
⁃ на какие страны целиться
⁃ и как сделать лучший пейволл
P.S. Сейчас крутое время, чтобы попробовать создать свой пет-продукт: AI тулы и инструменты, как Adapty, сильно упрощают этот путь. Но конкуренция, конечно же, будет жесткая.
👍8🔥2🙏2❤1
The Anatomy of a LiquidGlass Button in iOS 26
😱 Кнопка
⚙️ Для создания круглой кнопки необходимо обрезать форму кнопки, чтобы эффект стекла правильно отображался при нажатии.
❓ Рекомендуется использовать стиль
⚠️ При изменении цвета кнопки в светлом режиме возникают проблемы, где кнопка не отображает выбранный цвет, оставаясь прежней.
LiquidGlass
в iOS 26
имеет стильный эффект стекла, который можно настроить с помощью модификаторов .glass
и .glassProminent
. borderProminent
с эффектом стекла для лучшего отображения в темном режиме, хотя это все еще может быть немного багованным.Please open Telegram to view this post
VIEW IN TELEGRAM
👎3👍2
Using defer in Swift to manage state cleanup
Раз новое не заходит, вспомним старое🥲
⚡️ В
💡 Использование
❓
➡️ Пример использования defer включает управление индикатором загрузки, который показывается во время выполнения асинхронной операции и скрывается по завершении, что предотвращает пропуск очистки состояния:
Раз новое не заходит, вспомним старое
Swift
оператор defer
позволяет гарантировать выполнение кода очистки при выходе из текущей области видимости, независимо от того, завершилась ли функция успешно или с ошибкой.defer
уменьшает вероятность ошибок в коде, особенно в больших функциях, где могут быть добавлены новые возвраты или отмены задач.Defer
гарантирует выполнение кода очистки в различных сценариях: нормальное завершение функции, выброс ошибки, ранний возврат или отмена задачи во время ожидания.func fetch() async {
isLoading = true
defer { isLoading = false }
do {
articles = try await service.fetchArticles()
} catch {
self.error = error.localizedDescription
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Memory Efficiency in iOS: Reducing footprint and beyond
🧠 Работа с памятью в приложениях - сложная тема. Правильное управление памятью в мобильных приложениях — это то, что помогает им не зависать и не съедать весь телефон. Если об этом не думать, приложение может тормозить или вовсе вылетать.
❓ Существует два основных подхода к управлению памятью: реактивный, когда проблемы решаются по мере их возникновения, и проактивный, который включает в себя заранее продуманные меры по снижению потребления памяти.
💡 Для снижения потребления памяти важно загружать изображения, соответствующие размеру отображения, и использовать такие инструменты, как
✔️ Правильное использование кэширования, например, с помощью
📊 Утечки памяти могут привести к тому, что объекты остаются в памяти, даже когда они больше не нужны. Используйте инструменты, такие как
⚠️ Для приложений с высокими требованиями к памяти можно запросить расширение виртуального адресного пространства с помощью специальных прав, что может улучшить производительность на поддерживаемых устройствах.
Image I/O
для создания миниатюр и асинхронной загрузки изображений.NSCache
, может значительно улучшить производительность, но важно следить за жизненным циклом кэша и избегать сильных ссылок на большие объекты.Memory Graph Debugger
, для выявления и устранения таких проблем.Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Caching in Swift
✏️ Давно хотел написать про использование кеша. Почему-то его благополучно забывают, когда нужно временное хранилище, а ведь это отличный вариант.
❓ NSCache автоматически управляет памятью, удаляя объекты при нехватке ресурсов, но требует обертки для работы с типами, не основанными на NSObject.
➡️ Создание обертки вокруг NSCache позволяет использовать любые типы ключей и значений, включая структуры, что делает API более гибким.
⚠️ Важно добавлять условия для недействительных кэшированных данных, например, устанавливать срок действия для записей, чтобы избежать отображения устаревшей информации.
⚙️ Кэширование на диске позволяет сохранять данные между запусками приложения, что полезно для доступа к загруженным данным в оффлайн-режиме.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
The Swift Method Dispatch Deep Dive
Если у вас были споры с коллегами относительно использования final для применения другого типа диспатчеризации у класса - дайте им эту статью🧠
🔴 В Swift существуют два основных типа диспетчеризации: статическая (быстрая, но менее гибкая) и динамическая (медленная, но более гибкая), каждая из которых имеет свои подтипы.
❓ Динамическая диспетчеризация может негативно сказаться на производительности из-за потери возможности оптимизации и увеличения вероятности кэш-промахов.
❗️ Понимание того, когда компилятор может определить адрес функции во время компиляции, помогает разработчикам предсказать, как будет происходить диспетчеризация в их коде.
Если у вас были споры с коллегами относительно использования final для применения другого типа диспатчеризации у класса - дайте им эту статью
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Рисуем чайник в Metal
🤘 Если вы давно мечтали погрузиться в метал - эта статья для вас. Тут вы будете рисовать чайник - почти как
✏️ Для примера используется модель чайника в формате
ℹ️ Работайте с четырьмя системами координат:
⚙️ Создайте экземпляры
🟢 Разработаете вершинный и фрагментный шейдеры, которые обрабатывают данные о вершинах и вычисляют цвет фрагментов на основе нормалей.
👀 Включите
hello world,
только в мире графики..obj
, загружаемая с помощью фреймворка Model I/O
, который создает представление модели и необходимые буферы.Local space
, World space
, View space
и Clip space
, используя матрицы трансформации для перемещения модели.MTLDevice
, MTLCommandQueue
и MTLCommandBuffer
, а также настраиваете MTLRenderPipelineDescriptor
для указания шейдеров и форматов буферов.depth testing
для улучшения реалистичности изображения, позволяя скрывать фрагменты, которые не видны из-за других объектов.Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤🔥3
Uncertain⟨T⟩
❓ Статья обсуждает важность учета неопределенности в программировании, особенно в контексте работы с GPS-данными и вероятностным программированием.
➡️ Предложена система типов
🖥 Код на Swift демонстрирует, как использовать
✏️ Статья объясняет, как метод Монте-Карло может быть использован для оценки вероятностей, например, в азартных играх, позволяя моделировать результаты с помощью случайных выборок.
💡 Рекомендуется поэтапно внедрять неопределенные вычисления в существующий код, начиная с тех функций, где ошибки GPS вызывают наибольшее количество жалоб от пользователей.
Uncertain<T>
, которая позволяет моделировать неопределенные данные, используя вероятностные распределения, что делает код более умным и точным.Uncertain<T>
для работы с GPS-данными, вычислениями скорости и сопротивления воздуха, учитывая неопределенности.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Assembler for Swift developers
Статья про ассемблер для разработчиков на Swift. Вы спросите: зачем❓
💡 В целом сейчас вы не будете это применять (с вероятностью 98%). Однако понимание самого процесса может оказаться весьма полезным для последующей работы, например, для разбора багов перформанса с не очень читаемым стектрейсом.
1️⃣ Это первая из трёх статей, посвящённых разбору процесса взаимодействия высокоуровневых языков с ассемблером.
👀 В этой части вы разберёте
Статья про ассемблер для разработчиков на Swift. Вы спросите: зачем
Hello, Assembly!
под macOS
на C
, узнаете про используемые регистры на Apple Silicon (Arm64)
и посмотрите на системные вызовы.Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
How to use the @available attribute in Swift
⚠️ Атрибут
✏️ Первый аргумент указывает платформу, а остальные могут включать
⚙️ Для выполнения кода на старых версиях можно использовать проверку
ℹ️ Если используется только аргумент
@available
позволяет определять доступность функций и типов на конкретных платформах или версиях Swift, что полезно при устаревании API или изменении методов.unavailable
, introduced, deprecated, obsoleted, message
и renamed
для управления доступностью кода.if #available
, чтобы условно выполнять код в зависимости от версии платформы.introduced
, можно применять сокращенный синтаксис, что упрощает запись атрибутов доступности.if #available(iOS 17.0, *) {
// Content is available here
} else {
// Fallback to some other code
}
@available(swift 5.10)
@available(iOS 17.0)
struct Content {
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2
Streaming changes with Observations
Вы до сих пор используете Combine? Тогда мы идем к вам 🫵
Ну а если без шуток - речь про фреймворк Observation, который, по сути, заменяет Combine.
👀 Тип
🔗 Этот тип группирует обновления, что позволяет избежать избыточных эмиссий при изменении нескольких свойств одновременно.
⚙️ Автор представляет расширение для протокола
Вы до сих пор используете Combine? Тогда мы идем к вам 🫵
Ну а если без шуток - речь про фреймворк Observation, который, по сути, заменяет Combine.
Observations
соответствует протоколу AsyncSequence
, что позволяет использовать его в асинхронных циклах for-await
, упрощая работу с изменениями состояния.Observable
, позволяющее легко создавать асинхронные последовательности для определенных ключевых путей.extension Observable {
func stream<Value: Sendable>(
of keyPath: KeyPath<Self, Value>
) -> any AsyncSequence<Value, Never> {
Observations {
self[keyPath: keyPath]
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Swift 6: Sendable, @unchecked Sendable, @Sendable, sending and nonsending
Прочитав заголовок, кто-то может задаться вопросом: wtf?😐
Но это реалии Swift 6. А в статье автор пытается разобраться со всем этим - в конце даже отличная таблица сравнение.
Вот несколько моментов:
➡️
➡️
➡️
➡️
➡️
Прочитав заголовок, кто-то может задаться вопросом: wtf?
Но это реалии Swift 6. А в статье автор пытается разобраться со всем этим - в конце даже отличная таблица сравнение.
Вот несколько моментов:
Sendable
— это протокол, который позволяет компилятору проверять, может ли тип безопасно передаваться между изоляционными доменами, с автоматическим выводом соответствия для простых типов. @unchecked Sendable -
Используется для типов, безопасность которых была обеспечена другими механизмами, позволяя разработчикам обойти проверки компилятора, но требует осторожности, чтобы не злоупотреблять этой возможностью.@Sendable -
для замыканий указывает, что замыкание может безопасно передаваться между изоляционными доменами, с проверкой безопасности на этапе компиляции.sending -
позволяет передавать объекты без проверки на Sendable
, но гарантирует, что переданный объект не будет использоваться повторно после передачи.nonsending
- используется с nonisolated
для указания, что асинхронный метод должен наследовать изоляцию вызывающего контекста, а не выходить за его пределы.Please open Telegram to view this post
VIEW IN TELEGRAM
👍1👎1
Default Actor Isolation: New Problems from Good Intentions
🆕 Swift 6.2 приносит долгожданное улучшение —
Основные идеи и эффекты нового механизма:
➡️ До Swift 6.2 неаннотированный код считался nonisolated, что приводило к множеству предупреждений и ошибок при строгой проверке конкурентности, особенно когда код на самом деле всегда выполнялся на главном потоке.
➡️
➡️ В Xcode 26 новые проекты получают эту настройку по умолчанию, а для старых нужно включать ее вручную в настройках компилятора или в Swift Package Manager через
➡️
➡️ Важно аккуратно использовать nonisolated и
❓ Новый подход снижает шум ошибок при миграции на Swift 6 и стимулирует более корректное использование модульного дизайна и конкурентного программирования.
Default Actor Isolation
, которое меняет подход к конкурентности в Swift. Теперь по умолчанию весь код таргета изолируется на @MainActor
, если явно не указано иное. Это снижает количество boilerplate-кода с аннотациями @MainActor
и Sendable
, упрощая жизнь разработчикам в UI-ориентированных проектах.Основные идеи и эффекты нового механизма:
Default Actor Isolation
меняет это поведение: теперь такой код автоматически считается изолированным на @MainActor
.defaultIsolation(MainActor.self)
nonisolated
сохраняется как способ явного выхода из изоляции, но меняет семантику — асинхронные nonisolated
функции уже не “сбрасывают” изоляцию, а наследуют ее от вызывающего контекста. @concurrent
, особенно в сложных многопоточных сценариях.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2
What's New in UIKit
Принес вам супер лонг рид про нововведение в UIKit в 26 iOS. 64 минуты на чтение - самое то на выходных🍷
Вот основные моменты и темы, освещённые в статье:
➡️ Обновления
➡️ Новые визуальные эффекты и компоненты: введён новый класс
➡️ Поддержка HDR-цветов: в
➡️ Расширена система меню с новыми методами для тонкой настройки главного меню iPadOS и контекстных меню, а также поддержкой фокусного выбора меню.
➡️ новые свойства для
➡️ новый класс
Принес вам супер лонг рид про нововведение в UIKit в 26 iOS. 64 минуты на чтение - самое то на выходных
Вот основные моменты и темы, освещённые в статье:
UIAction
и UIApplicationDelegate
: добавлены новые идентификаторы действий и происходит постепенный отход от UIApplicationDelegate
в пользу более современных UISceneDelegate
и UIWindowSceneDelegate
UIGlassEffect
с эффектами Liquid Glass
, новые API для сглаживания углов в виде UICornerConfiguration
и UICornerRadius
. Также есть новые опции для кнопок (UIButton.Configuration
и элементов навигационной панели UIBarButtonItem
, включая новые стили, бейджи иконок и поведение.UIColor
и связанных компонентах появляются конструкторы и свойства для работы с HDR, а в UIColorPickerViewController
добавлен HDR-лайтбокс.UINavigationItem
позволяют задавать комплексные атрибуты титулов и подзаголовков, улучшена работа жестов для интерактивного закрытия экранов и размещения поисковых панелей.UIScrollEdgeEffect
позволяет контролировать эффекты на краях скроллов, а появилось также взаимодействие UIScrollEdgeElementContainerInteraction
для кастомных элементов.Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Getting access to the user’s calendar
🗓 Для работы с календарем и напоминаниями пользователей используется фреймворк
🔴 Перед доступом к календарю необходимо получить разрешение от пользователя, используя ключи конфиденциальности в настройках проекта:
🖥 Для запроса доступа к событиям и напоминаниям используются методы
⚠️ Текущий статус авторизации можно проверить с помощью метода
➡️ Рекомендуется создать отдельный класс, например
EventKitt
, который предоставляет все необходимые инструменты для создания и получения событий.Privacy - Calendars Full Access Usage Description
и Privacy - Reminders Full Access Usage Description
.requestFullAccessToEvents
и requestFullAccessToReminders
, а также requestWriteOnlyAccessToEvents
для приложений, которые не требуют чтения календаря.authorizationStatus(for:)
, который возвращает значения EKAuthorizationStatus
, такие как fullAccess
, writeOnly
, denied
, notDetermined
и restricted
.CalendarPermissionsViewModel
, для управления статусом доступа к календарю и напоминаниям, а также для обработки запросов на доступ.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Inspect & optimize Image Decoding timing in iOS
⌛ Декодирование изображений в iOS происходит в основном потоке во время фазы коммита
⚙️ Используйте методы UIKit, такие как
➡️ Старайтесь использовать
⚠️ Использование API
Core Animation
, что может вызывать зависания приложения при работе с большими изображениями.prepareForDisplay
и prepareThumbnail
, для предварительной обработки изображений в фоновом режиме, чтобы избежать задержек в основном потоке.ImageIO
для создания уменьшенных изображений перед дальнейшей обработкой и избегайте копирования изображений между основной и графической памятью для повышения производительности.UIImageReader
в iOS 17 может привести к утечкам памяти, которые были исправлены в iOS 18.Getting HDR UIImage in iOS 17 and display it in a UIImageView will result in major memory leak internally. Apple have fixed this issue on iOS 18
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
High Level Anatomy of a Camera Capturing Session
❓ Камера или микрофон служат источником для захвата видео, фото или аудио, включая заднюю и фронтальную камеры.
ℹ️ Выход может быть в виде фото или видео, которые сохраняются на диске или обрабатываются для распознавания лиц и применения фильтров.
➡️
❓ Метод
➡️
AVCaptureSession
является центральным контроллером, который управляет входами, выходами и предварительными слоями для захвата медиа.capturePhoto
асинхронный, что означает, что захват фото занимает время из-за фокусировки и экспозиции.AVCapturePhoto
- это необработанный вывод, PHAsset
- ссылка на изображение в библиотеке, CGImage
- это битовая карта, а Image
в SwiftUI
- визуальное представление.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Certificate Pinning on iOS in Practice
Статья про то, что такое
⚠️ Основная цель реализации
🖥 Certificate pining включает в себя проверку цепочки сертификатов, состоящей из корневого, промежуточного и конечного сертификатов, с акцентом на конечный сертификат для обеспечения безопасности соединения.
ℹ️ Можно пиннить как весь сертификат, так и его отпечаток или открытый ключ, что дает гибкость в управлении сертификатами, особенно при их обновлении.
❗️ Обновление сертификатов может быть неудобным, так как требует обновления приложения. Рекомендуется использовать пиннинг открытого ключа или удаленные обновления сертификатов через такие решения, как
⚙️ Для реализации
Статья про то, что такое
certificate pining
и как его настроить.certificate pining
— защита от атак типа человек посередине
, которые могут позволить злоумышленникам перехватывать данные пользователей и тестировать уязвимости API.CloudKit
.certificate pining
в iOS необходимо использовать URLSessionDelegate
для обработки аутентификационных вызовов и проверки доверенных сертификатов.Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Swift Computed Property: Code Examples
Вдруг вы не знаете, что такое вычисляемое свойство - эта статья для вас🙂
ℹ️ Вычисляемое свойство в Swift предоставляет геттер и необязательный сеттер для косвенного доступа к другим свойствам и значениям, позволяя создавать новые значения на основе существующих.
❓
⚠️ Вычисляемые свойства выполняют свои операции каждый раз при доступе, что может привести к снижению производительности при тяжелых вычислениях. Рекомендуется использовать сохраненные значения, если вычисления статичны.
➡️
Такие свойства не принимают аргументы, поэтому для логики, требующей динамических входных параметров или тяжелых вычислений, лучше использовать методы для повышения читаемости и управления производительностью.
❓ Вычисляемые свойства могут иметь асинхронные геттеры, позволяя использовать
Вдруг вы не знаете, что такое вычисляемое свойство - эта статья для вас
Computed properties
могут использоваться для создания значений, таких как имя файла, основанное на других свойствах, или для управления доступом к внутренним объектам через публичные интерфейсы.Такие свойства не принимают аргументы, поэтому для логики, требующей динамических входных параметров или тяжелых вычислений, лучше использовать методы для повышения читаемости и управления производительностью.
await
для выполнения операций, таких как валидация данных перед возвратом значения.struct Content {
enum ContentError: Error {
case emptyFileExtension
}
let name: String
let fileExtension: String
/// A computed property to generate a filename.
/// Throws an error when the file extension is empty.
var filename: String {
get throws(ContentError) {
guard !fileExtension.isEmpty else {
throw .emptyFileExtension
}
return name + "." + fileExtension
}
}
}
/// We now need to use the `try` keyword when accessing:
print(try content.filename) // Prints: "swiftlee-banner.png"
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Overview on Accessibility Nutrition Labels for iOS development
ℹ️ На WWDC25 Apple представила метки доступности, которые отображаются в App Store и информируют пользователей о поддерживаемых функциях доступности приложений.
🖥 Разработчики могут заявить о поддержке таких функций, как
🔈
🔍 Поддержка
➡️ Поддержка достаточной контрастности помогает пользователям с низким зрением; разработчики могут использовать инструмент
➡️ Субтитры обеспечивают текстовую альтернативу для пользователей с нарушениями слуха, а аудиодескрипции предоставляют устное описание визуального контента для пользователей с нарушениями зрения.
VoiceOver, Voice Control, Dynamic Type, Dark Mode
, и других, чтобы улучшить доступность своих приложений.VoiceOver
- это экранный диктор, который помогает пользователям навигировать по приложению без визуального контакта, требуя от разработчиков ручной настройки для улучшения опыта.Dynamic Type
позволяет пользователям увеличивать размер текста на устройствах iOS, что делает текст более читаемым и удобным.Color Contrast Calculator в Xcode
для проверки соответствия.Please open Telegram to view this post
VIEW IN TELEGRAM
👍2