Мобильный трудоголик
1.4K subscribers
61 photos
9 videos
269 links
👨‍💻 Пишу простым языком об iOS разработке на Swift и мобильной разработке в целом.
🔹 Вошел в IT задолго до того как это стало мейнстримом.
---
‍Обо мне: https://t.me/hardworkerIT/3
Чат: @hardworkerChatIT
Канал про разработку и жизнь в ИТ: @itDenisov
Download Telegram
🔢 Swift Collections: Секретное оружие для эффективного кода.

Часто в повседневной работе нам кажется, что массивы, словари и множества покрывают все задачи, но есть инструменты, которые могут сделать ваш код эффективнее, чище и надежнее. Сегодня разберем несколько структур из библиотеки swift-collections, которые решат проблемы, о которых вы могли не подозревать.


Deque.

Deque - это оптимизированная версия массива, которая позволяет добавлять и удалять элементы с начала и конца за O(1). В то время как Array тратит O(n) на вставку в начало.

Пример:

Например, код из фоторедактора с функцией отмены последних действий.


import Collections

final class ActionHistory<Action> {
private var history: Deque<Action> = []
private let capacity: Int

init(capacity: Int = 50) {
self.capacity = capacity
}

func addAction(_ action: Action) {
if history.count >= capacity {
history.removeFirst() // Удаляем самое старое действие
}
history.append(action)
}

func undo() -> Action? {
history.popLast()
}
}


При частом изменении начала коллекции Deque работает значительно быстрее Array.


Heap.

Heap автоматически сортирует элементы по приоритету. Например, идеально для обработки задач с разной срочностью.

Пример:

Система уведомлений, где сообщения от администратора должны показываться первыми.


struct Notification: Comparable {
let message: String
let priority: Int

static func < (lhs: Notification, rhs: Notification) -> Bool {
lhs.priority < rhs.priority
}
}

var notifications = Heap<Notification>()
notifications.insert(Notification(message: "Обновление системы", priority: 1))
notifications.insert(Notification(message: "Новое сообщение", priority: 3))

// Сначала получим уведомление с priority = 3
let nextNotification = notifications.popMax()



OrderedSet.

OrderedSet - это гибрид Array и Set, который сохраняет порядок элементов и гарантирует их уникальность.

Пример:

Список недавно просмотренных товаров в маркетплейсе, где важно и избежать дублей, и сохранить порядок.


var recentProducts = OrderedSet<String>()
recentProducts.append("iPhone 17")
recentProducts.append("iPad Pro")
recentProducts.append("iPhone 17") // Не добавится

print(recentProducts) // ["iPhone 17", "iPad Pro"]



OrderedDictionary.

OrderedDictionary - это словарь, который запоминает порядок добавления элементов.

Пример:

Кэширование данных для экрана списка, где порядок элементов важен.


var userCache = OrderedDictionary<String, User>()
userCache["user_1"] = User(name: "Анна")
userCache["user_2"] = User(name: "Иван")

// Порядок сохраняется при обходе
for (id, user) in userCache {
print("\(id): \(user.name)") // user_1: Анна, user_2: Иван
}



Зачем это все нужно:

🔹 Производительность: правильные структуры данных экономят ресурсы.
🔹 Читаемость: код становится проще для понимания.
🔹 Надежность: меньше шансов допустить ошибку в реализации.


🔗 Ссылка на подробную статью


💡 Вывод:

Разработка - это не только о написании работающего кода, но и о выборе оптимальных инструментов. Постепенно расширяя свой арсенал, вы не просто пишете код, а создаете эффективные и масштабируемые решения.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2315🙏8🔥221
🔢 Swift Configuration: новая библиотека для работы с настройками от Apple.

Друзья, привет! Apple выпустила долгожданную библиотеку Swift Configuration - универсальное решение для управления настройками в Swift-проектах. Расскажу, чем она полезна и как начать ее использовать.


Что такое Swift Configuration:

Данная библиотека предоставляет единый интерфейс для чтения настроек из различных источников. Больше не нужно писать разный код для работы с переменными окружения, JSON-файлами и аргументами командной строки.


Основные возможности:

🔹 Единый API: одинаковый код для всех источников настроек.
🔹 Горячее обновление: изменения применяются без перезапуска приложения.
🔹 Поддержка вложенности: работа со сложными структурами настроек.
🔹 Приоритеты источников: четкая иерархия важности настроек.


Пример:


import Configuration

// Настройка чтения из разных источников
let config = ConfigReader(providers: [
EnvironmentVariablesProvider(), // Переменные окружения
CommandLineArgumentsProvider(), // Аргументы командной строки
try await JSONProvider(filePath: "/app/config.json") // JSON-файл
])

// Чтение значения (ищет в порядке приоритета)
let timeout = config.int(forKey: "http.timeout", default: 30)
let host = config.string(forKey: "database.host", default: "localhost")



Как это работает в реальном проекте:

Представьте, у вас есть базовые настройки в JSON:


{
"database": {
"host": "localhost",
"port": 5432
}
}


Но для production вы можете переопределить их через переменные окружения:


export DATABASE_HOST=production_db.test.ru


Библиотека автоматически выберет значение из переменной окружения как более приоритетное.


Преимущества:

🔹 Снижение количества шаблонного кода: больше не нужно писать парсеры для каждого типа конфигов.
🔹 Упрощение тестирования: легко подменять настройки в тестах.
🔹 Гибкость развертывания: разные среды через разные источники настроек.


🔗 Ссылка на подробную статью


💡 Вывод:

Swift Configuration - это серьезный шаг к стандартизации работы с настройками в Swift-экосистеме. Библиотека пока сыровата для продакшена, но идеи стоят внимания. Особенно ценна унификация доступа к разным источникам конфигов.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
18🔥12👍611
📱 Тестируем пуш-уведомления на iOS-симуляторе.

Здравствуйте, друзья! Сегодня мы разберем как тестировать пуш-уведомления на симуляторе без заморочек с сервером и реальными устройствами. Это особенно актуально когда нужно быстро проверить внешний вид или логику обработки уведомлений.


Подготовка: запрашиваем разрешения.

Первым делом нужно запросить разрешение на показ уведомлений. Без этого даже идеально настроенный пуш не сработает:


import UserNotifications

UNUserNotificationCenter.current().requestAuthorization(
options: [.alert, .sound, .badge]
) { granted, error in
print("Разрешение получено: \(granted)")
}



Два способа отправки пушей.


Способ 1: Drag & Drop (самый простой)

Создаем JSON-файл notification.apns с содержимым уведомления:


{
"aps": {
"alert": {
"title": "Новое сообщение",
"body": "Вам пришло новое сообщение в чате"
},
"badge": 1,
"sound": "default"
},
"Simulator Target Bundle": "com.yourapp.bundleid"
}


Просто перетаскиваем файл на симулятор, уведомление появится мгновенно!


Способ 2: Через терминал (для автоматизации)

Узнаем ID симулятора:


xcrun simctl list


Отправляем пуш:


xcrun simctl push booted com.yourapp.bundleid notification.apns


Ключевое слово booted автоматически определяет запущенный симулятор.


Что еще можно протестировать.

На симуляторе отлично работают:

🔹 Rich-уведомления с картинками.
🔹 Кастомные звуки.
🔹 Action-кнопки.
🔹 Deep links.
🔹 Badge-иконки.


Частые ошибки:

🔹 Не указан Simulator Target Bundle: симулятор не поймет, какому приложению предназначен пуш.
🔹 Нет разрешений: забыли вызвать requestAuthorization.
🔹 Неверный bundle identifier: проверьте точное написание в проекте.


🔗 Ссылка на подробную статью


💡 Вывод:

Тестировать пуш-уведомления на симуляторе стало проще простого. Не нужно настраивать серверную часть, достаточно JSON-файла и пары команд. Единственное ограничение - некоторые продвинутые функции вроде фоновых обновлений контента лучше проверять на реальном устройстве. Но для 90% повседневных задач симулятора более чем достаточно.

Стоит отметить, что на iOS 26 симуляторах иногда наблюдаются проблемы, при тестировании пуш-уведомлений. Если у вас возникли проблемы, попробуйте протестировать на предыдущих версиях iOS.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
2011🔥5🙏2👍11
Forwarded from Кот Денисова
This media is not supported in your browser
VIEW IN TELEGRAM
🆘 Возвращение легенды: Stack Overflow запускает свой ИИ.

Пока все обсуждают ChatGPT и Copilot, легендарный Stack Overflow тихо готовит ответный удар. И у них есть серьезное преимущество: гигантская база проверенных ответов, которые создавали мы с вами все эти годы.


Что происходит?

Stack Overflow анонсировал собственную ИИ-систему Overflow AI. И это не просто очередной чат-бот, а интеграция их огромной базы знаний в рабочие процессы разработчиков.


Ключевые фишки:

🔹 Умный поиск: можно задавать вопросы естественным языком.
🔹 Интеграция с VS Code: помощь прямо в редакторе кода.
🔹 Slack-бот: ответы на технические вопросы в рабочих чатах.
🔹 Корпоративная версия: поиск по внутренним базам знаний компаний.


Мое мнение:

Stack Overflow может стать антидотом от ИИ-багов. Особенно ценна корпоративная версия, представьте, ИИ ищет ответы не только в публичной базе, но и в вашем внутреннем Confluence, GitHub и документации.


💡 Вывод:

Игра только начинается. Stack Overflow может занять нишу правильного ИИ для разработчиков, где важна точность, а не креативность.


🔗 Кот Денисова
Please open Telegram to view this post
VIEW IN TELEGRAM
21🔥14👍9👏3👀11
🔢🏋️ Swift на Android: один код для двух платформ.

Друзья, привет! Случилось то, о чем многие давно мечтали, но мало кто верил это произойдет! После месяцев работы рабочей группы по поддержке Android, компания Apple выпустила первую версию Swift SDK для разработки под операционную систему Android.


Масштабы поддержки:

Уже сейчас 25% пакетов в Swift Package Index поддерживают сборку для Android. Среди них многие популярные библиотеки, которые мы используем в повседневной разработке.

Стоит отметить, что код компилируется на Java и Kotlin, так как Android пока еще нативно не поддерживает Swift.


Что нужно для старта:

🔹 Установите Swift 6.3: раннюю версию с поддержкой Android.
🔹 Загрузите Swift SDK для Android: отдельно или в составе установщика для Windows.
🔹 Добавьте Android NDK: для нативной компиляции.

Подробные инструкции уже доступны в официальной документации.


Почему это важно:

🔹 Больше не нужно учить Kotlin/Java для разработки под Android, если вы владеете Swift.
🔹 Единая бизнес-логика, кодовая база и архитектурные подходы на обеих платформах.
🔹 Снижение затрат, одна команда вместо двух раздельных под каждую из платформ.


Перспективы:

Рабочая группа уже готовит дорожную карту развития платформы. В планах: улучшение отладки, оптимизация производительности и расширение поддержки Android API.


Что важно понимать:

🔹 Это предварительная версия, некоторые функции ещё в разработке.
🔹 Требуется время на стабилизацию и полировку.
🔹 Не все iOS-библиотеки сразу будут работать на Android.


💡 Вывод:

Swift на Android - это не просто ещё одна кроссплатформенная технология, это возможность создать по-настоящему единую кодовую базу с нативной производительностью на языке программирования Swift.

Это может изменить расстановку сил на рынке мобильной разработки. KMM, Flutter и React Native получают мощного конкурента, а нативные разработчики новые возможности.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2515👍9🤔221
🔢 Observations: современный подход к отслеживанию изменений данных в Swift.

С выходом Swift 6.2 появился новый мощный инструмент для наблюдения за изменениями в @Observable моделях. Сейчас расскажу, как это работает и чем отличается от предыдущих подходов.


Что изменилось:

Раньше мы использовали withObservationTracking с его неудобным API и семантикой will set. Теперь появился объект Observations, который создает AsyncSequence для отслеживания изменений свойств.


Пример:

Допустим, у нас есть модель счетчика:


@Observable
class Counter {
var count = 0
var name = "Счетчик"
}


Старый подход:


class CounterObserver {
func observeOldWay(counter: Counter) {
withObservationTracking {
print("Текущее значение: \(counter.count)")
} onChange: {
self.observeOldWay(counter: counter) // Рекурсивный вызов
}
}
}


Новый подход:


class CounterObserver {
func observeNewWay(counter: Counter) {
Task { [weak self] in
let values = Observations { [weak self] in
guard let self else { return "" }
// Наблюдаем за count и name, но возвращаем форматированную строку
return "\(self.counter.name): \(self.counter.count)"
}

for await value in values {
print("Обновление: \(value)")
// Обновляем UI или выполняем другую логику
}
}
}
}


Еще один пример:


class UserProfileManager {
@Observable class UserProfile {
var username: String
var email: String
var isOnline: Bool
}

func startObservingProfile() {
Task { [weak self] in
let profileUpdates = Observations { [weak self] in
guard let self else { return false }
// Наблюдаем за несколькими свойствами
let status = self.userProfile.isOnline
let name = self.userProfile.username
return (status, name)
}

for await (isOnline, username) in profileUpdates {
await self?.updateUserInterface(isOnline: isOnline, username: username)
}
}
}
}



Преимущества нового подхода:

🔹 Более чистый код: никакой рекурсии.
🔹 AsyncSequence: интегрируется с современным асинхронным Swift.
🔹 Гибкость: можно возвращать любой тип данных.
🔹 Автоматическое отслеживание: наблюдаются все свойства, доступные в closure.


🔗 Ссылка на подробную статью


💡 Вывод:

Observations существенно упрощает отслеживание изменений данных по сравнению с предыдущими подходами. Теперь не нужно писать рекурсивные вызовы, достаточно создать асинхронную последовательность и обрабатывать обновления в цикле.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19159🔥2👀2🙏11
🔢 iOS 26.1: новый протокол для фоновой выгрузки ресурсов.

В iOS 26.1 компания Apple представила новый тип расширений для PhotoKit: Background Resource Upload. Это обновление, которое перекладывает управление фоновыми загрузками на саму операционную систему.


Что это такое?

PHBackgroundResourceUploadExtension - это новый протокол, который позволяет системе управлять загрузкой ресурсов от имени вашего приложения. Теперь iOS сама обрабатывает загрузки, даже когда пользователь переключился на другое приложение или заблокировал устройство.


Как это работает.

Система предоставляет два основных метода:


// Запрос на обработку фоновых загрузок
func process() -> PHBackgroundResourceUploadProcessingResult

// Уведомление о завершении работы
func notifyTermination()



Ключевые компоненты API:

🔹 PHBackgroundResourceUploadExtension: основной протокол для расширений фоновой загрузки.
🔹 PHBackgroundResourceUploadProcessingResult: enum с результатами обработки.
🔹 PHAssetResourceUploadJob: представляет запрос на загрузку ресурса PHAsset.
🔹 PHAssetResourceUploadJobChangeRequest: для управления записями загрузок.


Преимущества подхода:

🔹 Автоматическое управление сетью: система сама оптимизирует подключения.
🔹 Энергоэффективность: загрузки в оптимальное время для батареи.
🔹 Надежность: обработка даже при блокировке устройства.
🔹 Умные тайминги: система выбирает лучшее время для загрузок.


Для каких задач подходит.

Идеально для приложений, которые:

🔹 Выполняют бэкап фотографий в облако.
🔹 Синхронизируют медиаресурсы с серверами.
🔹 Загружают тяжелые видеофайлы.
🔹 Работают с большими коллекциями изображений.


Важные нюансы:

🔹 Пока доступно только в PhotoKit.
🔹 API находится в бета-версии.
🔹 Требуется iOS 26.1+
🔹 Документация может измениться.


🔗 Документация на сайте Apple


💡 Вывод:

Новый API Background Resource Upload - это серьезное упрощение для разработчиков, работающих с медиаресурсами. Система берет на себя всю сложность управления фоновыми задачами, позволяя сосредоточиться на бизнес-логике приложения.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍14🔥73👀11
🔢 Тестируем приватные свойства без нарушения инкапсуляции в Swift.

Всем привет! Сегодня поговорим о боли каждого iOS-разработчика: как тестировать приватные методы и свойства без нарушения принципов инкапсуляции. Оказывается, есть способ делать это элегантно!


Проблема, знакомая каждому.

Представьте ситуацию: у вас есть класс с приватным кэшем:


class PaymentProcessor {
private var cache: [String: Payment] = [:]

func processPayment(_ payment: Payment) {
// Сложная логика с использованием cache
}
}


Как протестировать, что кэш действительно работает? Раньше были только два неидеальных варианта:

🔹 Сделать cache internal: нарушаем инкапсуляцию.
🔹 Тестировать только через публичные методы: тесты становятся сложными и хрупкими.


Решение.

Swift предлагает атрибут @_private(sourceFile:), который позволяет получить доступ к приватным членам в тестах:


#if ENABLE_PRIVATE_TESTS
@_private(sourceFile: "PaymentProcessor.swift")
import MyApp
#endif

func testCacheBehavior() {
let processor = PaymentProcessor()

// Теперь можем напрямую работать с приватным cache!
XCTAssertTrue(processor.cache.isEmpty)
}



Настройка.

🔹 Шаг 1: Включаем приватные импорты в основном модуле. В Package.swift:


.target(
name: "MyApp",
swiftSettings: [
.unsafeFlags(["-Xfrontend", "-enable-private-imports"])
]
)


🔹 Шаг 2: Условная компиляция в тестах:


#if ENABLE_PRIVATE_TESTS
@_private(sourceFile: "PaymentProcessor.swift")
import MyApp
#endif


🔹 Шаг 3: Настраиваем переменную окружения. В схеме тестирования:


ENABLE_PRIVATE_TESTS=1



🔗 Ссылка на подробную статью


💡 Вывод:

@_private(sourceFile:) - инструмент для серьезных проектов, где важны качественные тесты. Используйте его осознанно, всегда оборачивайте в флаги компиляции и будьте готовы к тому, что в будущих версиях Swift он может перестать работать.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥13🤔6👀521🙏1🗿1
🔢 Новая навигация в UIKit 26: теперь с подзаголовком и гибким поиском.

Друзья, Apple продолжает сближать UIKit и SwiftUI! В iOS 26 обе технологии получают мощные обновления навигации, которые избавят нас от кастомных решений и костылей.


Что нового в UIKit.

Подзаголовки в UINavigationItem:


// Базовый подзаголовок
let navItem = navigationItem
navItem.title = "Профиль"
navItem.subtitle = "Премиум аккаунт"

// Стилизованная версия
let attributedSubtitle = AttributedString(
"Активен до 25.12.2026",
attributes: AttributeContainer([
.foregroundColor: UIColor.systemGreen,
.font: UIFont.systemFont(ofSize: 12, weight: .medium)
])
)
navItem.attributedSubtitle = attributedSubtitle


Гибкий поиск с новыми вариантами размещения:


// Разные варианты поиска
searchController.searchBarPlacement = .integrated // Встроенный
searchController.searchBarPlacement = .integratedButton // Как кнопка
searchController.searchBarPlacement = .integratedCentered // Центрированный



Что нового в SwiftUI.

Подзаголовки в NavigationStack:


struct ProfileView: View {
var body: some View {
NavigationStack {
Text("Контент профиля")
.navigationTitle("Профиль")
.navigationSubtitle("Премиум аккаунт") // Новое в iOS 26!
}
}
}


Liquid Glass для навигации:


.navigationBarTitleDisplayMode(.large)
.background(.ultraThinMaterial) // Эффект стекла



💡 Вывод:

iOS 26 делает навигацию единой для UIKit и SwiftUI. Больше не нужно выбирать между технологиями, можно создавать современные интерфейсы используя нативные API обеих платформ.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
19👍15🔥9621
🔢 Оптимальное создание миниатюр с помощью CGImageSource.

Создание миниатюр - одна из самых распространенных задач в мобильной разработке. Но не все методы одинаково эффективны. Рассмотрим, как разные подходы показывают себя на практике при работе с 12-мегапиксельным JPEG.

Классические методы показывают разную производительность:

🔹 NSImage на macOS: 710 мс.
🔹 UIGraphicsImageRenderer на iOS: 210 мс.
🔹 UIImage.prepareThumbnail() на iOS: 130 мс.

Специализированные методы демонстрируют лучшие результаты:

🔹 CGImageSource на macOS: 16-26 мс.
🔹 CGImageSource на iOS: 24-95 мс в зависимости от формата.


Пример использования CGImageSource:


let source = CGImageSourceCreateWithData(imageData as CFData, nil)!

let cgThumb = CGImageSourceCreateThumbnailAtIndex(source, 0, [
kCGImageSourceCreateThumbnailFromImageAlways: true,
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceThumbnailMaxPixelSize: max(size.width, size.height)
] as CFDictionary)!

let thumbnail = UIImage(cgImage: cgThumb) // или NSImage в macOS



Ключевые параметры:

🔹 kCGImageSourceCreateThumbnailFromImageAlways: гарантирует создание миниатюры.
🔹 kCGImageSourceCreateThumbnailWithTransform: учитывает ориентацию изображения.
🔹 kCGImageSourceThumbnailMaxPixelSize: задает максимальный размер.


Получение информации о размерах:


let source = CGImageSourceCreateWithData(data as CFData, nil)!
if let properties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [CFString: Any],
let width = properties[kCGImagePropertyPixelWidth] as? Int,
let height = properties[kCGImagePropertyPixelHeight] as? Int {
print("Ширина: \(width), высота: \(height)")
}



Преимущества CGImageSource:

🔹 Мгновенное получение размеров изображения (2-4 мс).
🔹 Работа с различными форматами (HEIC, JPEG, PNG).
🔹 Эффективное использование памяти.
🔹 Поддержка последовательной загрузки.


🔗 Ссылка на подробную статью


💡 Вывод:

CGImageSource показывает стабильно высокую производительность на обеих платформах, особенно заметно ускорение на macOS: до 40 раз по сравнению с классическими методами. Для задач, связанных с отображением галерей или списков изображений, этот подход становится оптимальным выбором.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍14🔥106🤝3👀21
Forwarded from Кот Денисова
👨‍💻 Реалии разработки: почему 50% времени уходит не на код.

Друзья, давайте честно: написание кода - это самая приятная, но далеко не самая большая часть нашей работы. Сегодня хочу поделиться типичным сценарием, который повторяется в проектах снова и снова.


Цикл разработки, который знаком каждому:


Неделя 1: начало разработки.

Вы получаете задачу, погружаетесь в контекст, продумываете архитектуру и бодро пишете код. Все идет по плану, фича почти готова. Вы чувствуете удовлетворение от хорошо сделанной работы и отправляете задачу на тестирование.


Неделя 2: ожидания тестирования.

Отдел тестирования перегружен, ваша задача висит в статусе «готова к тестированию». Вы переключаетесь на другие задачи и проекты, постепенно забывая детали реализации. Контекст стирается, а энтузиазм угасает.


Неделя 3: неожиданное возвращение.

Внезапно приходит сообщение: «Задача возвращена на доработку». Оказывается, требования изменились, нашли краевой случай или продукт-менеджер придумал улучшение. Теперь вам нужно заново вникать в задачу, которую вы уже считали завершенной.


Немного статистики:

🔹 Каждая третья фича возвращается на доработку минимум один раз.
🔹 15% задач требуют кардинальных изменений после тестирования.
🔹 Среднее время ожидания тестирования: от 2 дней до 7 дней.
🔹 Большинство разработчиков одновременно ведут несколько задач.


Почему так происходит:

Бизнес-требования постоянно эволюционируют: рынок не стоит на месте. То, что было актуально месяц назад, сегодня может устареть. Пользователи дают обратную связь, которая подсвечивает неочевидные проблемы. Тестирование выявляет ситуации, которые невозможно было предвидеть на этапе проектирования.


Как с этим работать:


Ментальные практики:

🔹 Не привязываться эмоционально к написанному коду.
🔹 Воспринимать изменения не как неудачу, а как возможность сделать продукт лучше.
🔹 Понимать, что выпиливание фичи - это не личное поражение, а забота о пользователе.


Построить рабочие процессы:

🔹 Организовать регулярные встречи с продукт-менеджерами для синхронизации.
🔹 Проводить промежуточные демо для стейкхолдеров до финального тестирования.
🔹 Выполнить детальные чек-листы перед сдачей задачи.
🔹 Назначить четкие критерии приемки для каждой фичи.


💡 Вывод:

Процесс разработки - это живой организм, который постоянно меняется. Умение адаптироваться, сохранять гибкость и не терять энтузиазм в цикле бесконечных доработок - вот что отличает профессионала.


🔗 Кот Денисова
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1914🙏10👀6🤝21
🔨 Важные изменения в Xcode 26.1 beta.

Привет, друзья! Сегодня поговорим о нововведения в Xcode 26.1 beta, которые повлияют на нашу повседневную работу:


SPM стал чуть умнее.

Локальное кэширование пакетов из реестра на час - это мелкое, но важное улучшение. Представьте: у вас в команде 10 человек, и все одновременно запускают pod install после обновления версии зависимости. Раньше каждый качал одно и то же, нагружая сеть. Теперь первый, кто скачал, становится локальным «источником» на час. Мелочь, а приятно, особенно для больших команд.


Instruments снова в строю.

На новых устройствах отказывал работать Processor Trace. Теперь это починили. Для тех, кто занимается глубокой оптимизацией и профилированием, это огромное облегчение. Теперь не нужно держать под рукой старый девайс, чтобы найти узкое место в производительности.


Coding Assistant перестал жрать память.

У кого были проекты с гигантскими git-репозиториями (например, с кучей субмодулей), тот знает, как Coding Assistant мог превратить MacBook в печку. Улучшение потребления памяти - это не про «удобства», это про возможность вообще работать с этим инструментом на реальных проектах.


Симулятор перестал чудить с JSON.

Команда simctl list devices --json снова работает корректно. Казалось бы, ерунда. Но это большая ерунда для всех, кто завязал на нее свои CI/CD-скрипты для автоматического тестирования на разных типах девайсов. Скрипты снова стали предсказуемыми.


Известные проблемы: будьте осторожны!

А вот здесь классика жанра. Apple выпускает бету, но перекладывает часть проблем на нас.

🔹 Симуляторы не запускаются. Первая сборка может упереться в то, что симулятор не загрузится.
Решение: Apple рекомендует вручную выполнить в терминале:


xcrun simctl runtime dyld_shared_cache update --all


🔹 Coding Assistant все еще подводит. Инструмент поиска по файлу может возвращать неверные номера строк. Представьте: вы хотите заменить все вхождения oldVariable на newVariable, а он из-за сбитого номера строки меняет не то, что нужно, и ломает вам логику. Пока что на этот инструмент лучше не полагаться в критичных операциях.


🔗 Xcode 26.1 beta Release Notes


💡 Вывод:

Xcode 26.1 beta - это типичный «качельный» апдейт. С одной стороны, мы видим долгожданные и очень точечные фиксы старых проблем (особенно в Instruments и SPM), которые реально облегчают жизнь. С другой получаем новые сюрпризы, которые могут остановить работу.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
16🔥13👍1032😁1👀1
🔢 Как Swift 6.2 сделал работу с зависимостями приятнее.

Вместе с выходом Swift 6.2 незаметно для многих произошли важные изменения в системе управления пакетами. Те, кто уже обновился, могли заметить, что сборки стали стабильнее, а некоторые процессы быстрее. Давайте разберемся, что именно изменилось и как это повлияет на вашу повседневную работу.


Безопасность памяти теперь под контролем.

Одно из ключевых нововведений: возможность включения строгой проверки безопасности памяти прямо в настройках пакета. На практике это означает, что потенциально опасные операции с памятью будут обнаруживаться на этапе компиляции, а не в рантайме.

Полезно для:

🔹 Серверных приложений.
🔹 Финансовых проектов.
🔹 Систем с повышенными требованиями к надежности.


Макросы перестали тормозить сборку.

Если вы используете макросы вроде @Observable или создаете собственные, теперь можете рассчитывать на ускорение сборки до 30%. Система научилась использовать предварительно собранные компоненты вместо постоянной перекомпиляции зависимостей.

Особенно заметно в CI/CD: в некоторых случаях экономия времени достигает нескольких минут на каждой сборке.


Умное кеширование экономит время.

Теперь бинарные зависимости кешируются более эффективно. При работе с несколькими проектами, использующими общие библиотеки, система не будет скачивать их повторно для каждого репозитория.

Когда полезно:

🔹 При работе в монорепозитории.
🔹 При частых пересборках.
🔹 При одновременной разработке нескольких связанных проектов.


Гибкие настройки диагностики.

Появилась возможность тонкой настройки предупреждений компилятора для разных компонентов проекта. Можно постепенно вводить строгие проверки в легаси-проектах, не ломая всю сборку сразу.


💡 Вывод:

Обновление принесло именно те улучшения, которых не хватало многим разработчикам. Сборки стали значительно быстрее, работа с зависимостями удобнее, а контроль качества кода гибче. Особенно заметны эти изменения в больших проектах, где каждая минута сборки буквально на счету.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1814🔥83👀21👏11
👨‍💻 Веб-версия App Store: как Apple упрощает поиск приложений.

Компания Apple запустила полноценную веб-версию App Store. Теперь можно искать и просматривать приложения со всех платформ Apple (iPhone, iPad, Mac, Apple Watch и Apple TV) прямо в браузере на любом устройстве.


Что изменилось?

Раньше ссылки на приложения вели на отдельные страницы с минимумом информации. Теперь это полнофункциональный магазин в браузере с:

🔹 Единым каталогом всех приложений.
🔹 Вкладкой Today с подборками и историями.
🔹 Разделами игр и Apple Arcade.
🔹 Полноценными страницами приложений со скриншотами, описаниями и видео.


Почему это важнее, чем кажется:

🔹 Кроссплатформенный поиск: теперь можно найти приложение, которое доступно одновременно на iPhone, iPad и Mac, и увидеть все варианты на одной странице. Больше не нужно переключаться между устройствами.

🔹 Обмен ссылками стал проще: отправляешь знакомому ссылку на полезное приложение и он может сразу посмотреть его описание и скриншоты, даже если у него под рукой только Android-телефон или ПК.

🔹 Маркетинг для разработчиков: теперь можно делиться ссылками на приложения в соцсетях, мессенджерах, на сайтах и пользователи увидят полноценную презентацию, а не урезанную карточку.


🔗 Ссылка на веб-версию App Store


💡 Вывод:

Этот шаг Apple не просто техническое обновление, а стратегический ход навстречу пользователям за пределами их экосистемы. Компания наконец-то признала реальность: миллионы людей используют смешанные устройства, например Windows с iPhone, и должны иметь возможность комфортно знакомиться с приложениями Apple.

Особенно важно, что веб-версия кардинально меняет процесс принятия решения о покупке. Теперь не нужно использовать iPhone или Mac, чтобы просто посмотреть, как выглядит приложение, достаточно открыть браузер на любом устройстве.

Для разработчиков это открывает новые возможности продвижения. Теперь можно эффективно работать с SEO и контент-маркетингом, направляя трафик напрямую в App Store из браузера. Пиар приложений выходит на новый уровень.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍1211😁5🤯22👏1
🔢 OptionSet: эффективная работа с флагами и настройками в Swift.

Привет! Сегодня хочу разобрать один из самых недооцененных инструментов в Swift: OptionSet. Это не просто протокол, а элегантное решение для задач, с которыми мы сталкиваемся почти в каждом проекте.


Для чего нужен OptionSet?

Представьте, что вы создаете компонент списка задач. В разных местах приложения вам нужно показывать разные возможности: где-то поиск и фильтр, где-то только сортировку, а в третьем месте вообще все элементы управления сразу.

Чаще всего, когда в коде нужно описать какие-то варианты выбора, разработчики сразу вспоминают про enum. Это действительно правильный подход для ситуаций, где может быть выбран только один вариан, например при статусах заказа: «в обработке», «доставляется» или «выполнен».

Но вот в чем проблема: когда нам нужно выбрать сразу несколько вариантов одновременно (например, показать и поиск, и фильтр, и сортировку), обычное перечисление не подходит. Пришлось бы создавать отдельные варианты для всех возможных комбинаций: «поиск_и_фильтр», «поиск_и_сортировка» и так далее. Это очень неудобно и громоздко.

OptionSet решает эту задачу гораздо элегантнее. Он работает как набор независимых переключателей, представьте себе чекбоксы на сайте. Вы можете включать и выключать их в любой комбинации и для этого не нужно заранее прописывать все возможные сочетания.


Пример.

Допустим, мы делаем тот самый список задач. Вот как может выглядеть наша конфигурация:


struct TasksListOptions: OptionSet {
let rawValue: Int

static let showFilter = TasksListOptions(rawValue: 1 << 0) // 0001
static let showSearch = TasksListOptions(rawValue: 1 << 1) // 0010
static let showSort = TasksListOptions(rawValue: 1 << 2) // 0100
static let showLayoutSelector = TasksListOptions(rawValue: 1 << 3) // 1000
}


Вся мощь OptionSet раскрывается, когда мы начинаем его использовать. Допустим, у нас есть экран «Сегодня» и экран «Все задачи». Для каждого из них мы можем легко задать нужный набор опций прямо при создании:


let todayOptions: TasksListOptions = [.showFilter, .showSearch]

let allTasksOptions: TasksListOptions = [.showFilter, .showSearch, .showSort, .showLayoutSelector]

// Для архива ничего не нужно
let archiveOptions: TasksListOptions = []


Теперь в коде это выглядит чисто и понятно. Когда мы создаем ViewModel для каждого экрана, мы просто передаем соответствующий набор опций:


let todayViewModel = TasksListViewModel(options: todayOptions)
let allTasksViewModel = TasksListViewModel(options: allTasksOptions)
let archiveViewModel = TasksListViewModel(options: archiveOptions)


Самое удобное, что мы можем легко проверять, какие опции активны в любой момент:


class TasksListViewModel {
let options: TasksListOptions

var shouldShowSearch: Bool {
return options.contains(.showSearch)
}

var shouldShowSort: Bool {
return options.contains(.showSort)
}
}


Технически, можно было бы использовать Set<Enum>, но зачем?


Приемущества OptionSet:

🔹 Производительность: работа на уровне битовых операций - это максимально быстро.
🔹 Минимальное потребление памяти: все флаги хранятся в одном числе.
🔹 Готовый API: contains, insert, remove, union и другие операции из коробки.


🔗 Ссылка на подробную статью


💡 Вывод:

OptionSet - это один из тех инструментов, который кажется сложным только до первого использования. На практике он очень упрощает код, делает его безопаснее и выразительнее.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
19👍15105🙏2🤯1
😊 RuStore для iOS: верим, что это только начало большого успеха.

В сети обнаружили любопытную функцию в тестовой версии RuStore для Android: возможность установки приложений на iPhone. Технология получила название RuStore Bridge, но ее реализация вызвала больше вопросов, чем восторгов.


Как это работает сейчас:

🔹 Нужен Android-смартфон с модифицированной версией RuStore.
🔹 iPhone подключается к Android-устройству по проводу.
🔹 Требуется использовать «Временный Apple ID» от разработчиков RuStore.
🔹 В каталоге пока только одно приложение: Промсвязьбанк, на котором можно опробовать работу данной технологии.


Ограничения:

🔹 Нужно удалить основную версию RuStore.
🔹 Кабели USB-C на USB-C не подходят, нужен кабель USB-A с переходником.
🔹 Авторизация только по SMS (аккаунты Яндекса и VK не поддерживаются).


🔗 Источник


💡 Мое мнение:

Это важный, первый шаг, который показывает, что команда RuStore активно ищет решения для пользователей iOS. Да, текущая реализация выглядит сложной, но помните: все великие проекты начинались с прототипов.

Технология RuStore Bridge - это доказательство того, что российские разработчики не сдаются и продолжают инновации даже в сложных условиях. Тот факт, что они нашли способ обойти ограничения, уже заслуживает уважения.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍18🔥13👀8😁53🤯21
👨‍💻 App Store Connect: важные изменения для разработчиков.

Всем привет! Apple выпустила набор обновлений для App Store Connect, которые на первый взгляд кажутся минорными, но могут серьезно повлиять на наши рабочие процессы. Это не громкие анонсы, а скорее точечные улучшения, которые стоит иметь в виду.


Изменения в процессе ревью.

Теперь можно отправлять отдельные компоненты приложения на проверку, не дожидаясь завершения основного ревью. Например:

🔹 In-App Events, пока основная версия приложения еще на проверке.
🔹 Критический фикс, не связанный с текущими кастомными страницами.
🔹 Компоненты Game Center (достижения, таблицы лидеров) отдельно от основной сборки.

Это действительно упрощает жизнь, особенно когда нужно срочно пофиксить баг или запустить событие к определенной дате. Раньше такие ситуации превращались в долгое ожидание полноценной проверки.


Кастомные продуктовые страницы.

Лимит кастомных продуктовых страниц увеличен с 35 до 70. Но главное: теперь можно назначать ключевые слова для каждой страницы.

Например, если у вас приложение для редактирования фото, можно создать отдельные страницы для редактирования портретов (ключевые слова: «портрет», «ретушь»), обработки пейзажей (ключевые слова: «пейзаж», «природа»), создания коллажей (ключевые слова: «коллаж», «фоторедактор»).


Промо-коды для всех типов покупок.

Теперь промо-коды работают для всех типов In-App Purchases:

🔹 Consumable (потребляемые товары).
🔹 Non-consumable (непотребляемые покупки).
🔹 Non-renewing subscriptions (подписки без авто-продления).


🔗 Подробнее в посте Apple Developer


💡 Вывод:

Эти изменения показывают, что Apple постепенно делает экосистему более гибкой. Не революция, но эволюция в правильном направлении. Особенно радует расширение промо-кодов - это реально полезный инструмент для монетизации.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥15942🙏1🤝1
🔢 Combine: важный инструмент для iOS-разработчика.

Всем привет! В мире Swift-разработки сегодня доминирует Swift Concurrency, но есть другой фреймворк, который заслуживает внимания: Combine. Этот инструмент способен кардинально изменить подход к работе с асинхронными операциями, предлагая совершенно иной взгляд на потоки данных.


Что такое Combine на самом деле:

Если просто - это декларативный способ работать с потоками данных. Вместо того чтобы вручную управлять очередями, колбэками и состоянием, вы описываете как данные должны преобразовываться и куда поступать.


Из чего состоит Combine:

🔹 Publisher: источник данных.
🔹 Subscriber: получатель данных.
🔹 Operator: фильтруют, модифицируют или комбинируют значения между Publisher и Subscriber.


Пример:

Представьте, что вы делаете поиск по товарам. Без Combine это обычно выглядело так:

🔹 Отслеживаем ввод в форму поиска.
🔹 Делаем небольшую задержку, чтобы не слать запросы на каждый символ.
🔹 Проверяем, что текст поиска не пустой.
🔹 Отправляем запрос.
🔹 Обновляем интерфейс в главной очереди.

Целая простыня кода с разрозненными таймерами и колбэками. С Combine это превращается в элегантную цепочку:


searchTextField
.publisher(for: \.text)
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.removeNil()
.filter { !$0.isEmpty }
.flatMapLatest { query in
apiService.searchProducts(query: query)
.catch { _ in Just([]) }
}
.receive(on: DispatchQueue.main)
.sink { [weak self] products in
self?.updateUI(with: products)
}
.store(in: &cancellables)



Почему Combine все еще актуален.

Да, async/await проще для линейных операций. Но Combine незаменим, когда нужно:

🔹 Реагировать на непрерывные изменения (текст в поиске, положение слайдера).
🔹 Комбинировать несколько потоков данных.
🔹 Создавать сложные цепочки преобразований.

Главный плюс, который часто упускают: Combine учит думать о данных как о потоках. Это ментальная модель, которая пригождается даже при работе с Swift Concurrency.


🔗 Ссылка на подробную статью


💡 Вывод:

Combine - это не просто фреймворк, а философия. Да, его изучение требует времени, но однажды изучив, вы начинаете видеть асинхронные операции в совершенно новом свете. Владение реактивным программированием - это важный навык для опытного iOS-разработчика, учитывая насколько широко оно применяется в крупных проектах и является стандартом во многих компаниях.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍136🔥2🙏11
Forwarded from Кот Денисова
👨‍💻 Говори на языке бизнеса: как доносить технические идеи менеджеру.

Друзья, сегодня поговорим о боли, знакомой каждому разработчику. Вы придумали гениальное техническое решение, но менеджер вас не понимает. В чем проблема? Мы говорим на разных языках!


Почему нас не слышат?

Бизнесу абсолютно не интересны:

🔹Красивая архитектура.
🔹Модные технологии.
🔹Чистый код как самоцель.


Что действительно волнует бизнес.

Бизнес живет тремя ключевыми метриками:

🔹Финансы: расходы и потенциальный доход.
🔹Скорость и эффективность: насколько быстро мы можем реагировать на рынок.
🔹Устойчивость: сокращение потерь и сбоев.


Трансформируем технические аргументы в бизнес-выгоды:

Вместо: «Нужно переписать этот legacy-код, он ужасен».
Говорим: «Текущая архитектура платежного модуля приводит к 20 часам простоя в месяц. После рефакторинга мы сэкономим X и снизим риск финансовых потерь».

Вместо: «Давайте использовать новую библиотеку, она крутая».
Говорим: «Новая библиотека ускорит разработку новых фич на 40% и снизит количество багов на 60%».


Практический инструмент: формула презентации идеи.

🔹Проблема: «Я вижу риск...».
🔹Решение: «Предлагаю три варианта...».
🔹Выгода: «Это сэкономит/ускорит/снизит...».
🔹Стоимость: «Потребуется X времени/ресурсов».


Красные флаги в коммуникации.

Если в ответ на ваши обоснованные предложения вы слышите:

🔹«Не выдумывай, просто работай».
🔹«Это твои проблемы, ты и решай».
🔹«Сейчас не время, потом» (и «потом» никогда не наступает).

Это признаки токсичной среды, где вас воспринимают как исполнителя, а не партнера.


Что может помочь:

🔹Готовить расчеты: не просто слова, а конкретные цифры экономии/ускорения/оптимизации.
🔹Предлагать варианты: показывать разные сценарии с плюсами/минусами.
🔹Говорить на их языке: использовать термины «риски», «окупаемость», «экономия».
🔹Быть готовым к компромиссам: делить большую задачу на этапы.


Результат таких изменений:

🔹Ваши идеи начинают слушать.
🔹Вы становитесь стратегическим партнером, а не просто «кодером».
🔹Растет доверие и влияние в команде.
🔹Появляется возможность влиять на технические решения.


💡 Вывод:

Умение говорить на языке бизнеса - это не предательство технических принципов, а мост между двумя мирами. Когда вы показываете, как технические улучшения влияют на прибыль и риски, ваши идеи начинают слышать.


➡️ Кот Денисова
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1694🤔2🔥1
Хочу порекомендовать канал @prettygeeknotes Анна Жарковой. Много полезного контента, посвященного мобильной разработке, полезные гайды, статьи, новости, а также анонсы важных IT-мероприятий. Кстати, Анна автор книги "Kotlin Multiplatform на практике"

Советую подписаться 👍
🔥14👍6🗿6😁5311
🔨 Проблема с симулятором в Xcode 26.1 и как ее обойти.

Обнаружилась серьезная проблема в Xcode 26.1: симулятор iOS 26.1 может дико тормозить и грузить процессор на 100%. Если у вас тоже бешено крутятся кулеры и симулятор работает как в слайд-шоу, вы не одиноки.


В чем проблема:

Процесс MercuryPosterExtension постоянно крашится, что заставляет систему запускать ReportCrash снова и снова. Это создает бесконечный цикл падений и отчетов об ошибках, который съедает все ресурсы процессора.


Откуда растут ноги:

Судя по логам, проблема в работе с обоями (PosterKit) в симуляторе. Когда система пытается отобразить стандартные обои происходит сбой.


Рабочие решения:

🔹 Перейти на симулятор iOS 26.0, он работает стабильно.
🔹 Сменить обои в симуляторе: зайти в настройки, выбрать другие обои и удалить стандартные, черные.


💡 Вывод:

Это классический пример того, как мелкий баг в одном компоненте может парализовать всю работу. Особенно обидно, когда срочно нужно тестировать на последней версии iOS, а симулятор превращается в слайд-шоу.

Что удивительно: проблема сохраняется и в Xcode 26.2 beta. Похоже, Apple еще не успела пофиксить эту проблему.

Ждем фикс от Apple.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍128🙏5🤯3🔥1👀1