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

С выходом Xcode 26 появился удобный инструмент для быстрого тестирования кода прямо в проекте — макрос #Playground. Теперь не нужно создавать отдельные .playground файлы, чтобы проверить идею.

🤔 Как это работает?

♣️ Добавляем макрос в любой Swift-файл:
import Playgrounds  

#Playground {
let person = Person(name: "Артем")
print(person.name.uppercased())
}

После чего смотрим результат в Canvas (как с SwiftUI превью, пример на изображении).

Плюсы:
🔹 Экономия времени — не нужно переключаться между файлами.
🔹 Тестирование на реальных данных — используете структуры из проекта.
🔹 Несколько превью в одном файле — можно подписать каждое:

#Playground("Проверка имени") {  
print(Person(name: "Анна").name.count)
}


⚠️ Ограничения:
🔸 Требует Xcode 26+ и iOS 18/macOS 15.
🔸 Пока нет поддержки интерактивного редактирования (как в обычных Playgrounds).

💡 Вывод:
#Playground — это лайт-версия Playgrounds прямо в рабочих файлах. Не заменяет полноценные .playground файлы для сложных экспериментов, но идеален для повседневных задач.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25🔥126👀1
🔢 WebKit для SwiftUI: новые API для работы с веб-контентом.

На WWDC25 компания Apple представила новые компоненты WebView и WebPage, которые значительно упрощают интеграцию веб-контента в SwiftUI приложения, которые доступны с iOS 18.4.

Что нового?

1️⃣ WebPage: удобная загрузка и управление.
Отслеживание состояния:
@State private var isLoading: Bool = false
@State private var progress: Double = 0.0

WebPage(url: URL(string: "https://t.me/hardworkerIT"))
.onLoadingChanged { loading in
isLoading = loading
}
.onProgressChanged { progress in
self.progress = progress
}


Обработка событий навигации (currentNavigationEvent), таких как ошибки, перенаправления, завершение загрузки.

2️⃣ Сохранение контента.
Теперь есть возможность сохранения веб-контента в следующих форматах:
🔹 Снимки экрана (PNG/JPEG).
🔹 PDF.
🔹 Веб-архивы (полное сохранение страницы).
WebPage(url: someURL)
.saveSnapshot(as: .pdf) { result in
switch result {
case .success(let data):
// Сохраняем PDF
case .failure(let error):
print("Ошибка: \(error)")
}
}


3️⃣ WebArchiveView — просмотр сохранённых веб-страниц.
Есть возможность отображения сохраненных страниц:
WebArchiveView(data: archivedData)


4️⃣ Дополнительные возможности:
🔹 Скролл к определённому элементу на странице.
🔹 Расширенное взаимодействие с JavaScript.
🔹 Кастомные обработчики для ссылок и форм.

🤔 Зачем это нужно?
🔸 Проще, чем WKWebView — не нужно писать обёртки для SwiftUI.
🔸 Нативные состояния загрузки — больше никаких кастомных индикаторов.
🔸 Готовые решения для экспорта и архивирования.

⚠️ Ограничения:
🔹 Требуется iOS 18.4+ / macOS 15.4+.
🔹 Для сложных сценариев (например, кастомные схемы URL) всё ещё может потребоваться WKWebView.

Больше информации доступно в официальной документации.

💡 Вывод:
Новые API делают работу с веб-контентом в SwiftUI такой же простой, как и с любыми другими вью. Теперь встраивать браузеры, документацию или веб-интерфейсы стало ещё удобнее!

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2311👍6👀2
🔨 Xcode 26: как ИИ помощник изменит разработку под Apple.

На WWDC25 компания Apple представила Xcode 26 с революционным ИИ ассистентом, который переосмысливает процесс создания приложений. Вот что ждет разработчиков.


ИИ помощник: код как диалог.

1️⃣ Умное автодополнение:
🔹 Анализирует стиль кода и предлагает персонализированные варианты.
🔹 Генерирует шаблонный код (делегаты, сетевые запросы).

2️⃣ Предсказание ошибок:
🔹 Находит синтаксические и логические баги до запуска.
🔹 Подсказывает оптимизации для Swift / Objective-C.

3️⃣ Контекстные советы:

// Вы начинаете печатать:
@State private var isLoading = false

// ИИ сразу предлагает:
.onChange(of: isLoading) { newValue in
print("Loading state changed: \(newValue)")
}


Тесная интеграция с экосистемой Apple.
🔹 Swift Playgrounds: ИИ помогает экспериментировать с кодом в реальном времени.
🔹 TestFlight: автоматически анализирует краши и предлагает фиксы.
🔹 Core ML: упрощает внедрение ML-моделей (подсказывает код для обработки данных).


Мультиязыковая поддержка.

ИИ работает с:
🔹 Swift (приоритет).
🔹 Objective-C.
🔹 C++.
🔹 SwiftUI / UIKit.


Отладка нового уровня.

1️⃣ ИИ анализ крашей:
🔹 Определяет корневую причину падений.
🔹 Предлагает готовые решения.

2️⃣ Визуализация данных:
🔹 Показывает графики потребления CPU / памяти.
🔹 Выявляет утечки без Instruments.


🤔 Как это изменит разработку?
🔸 Скорость: на 30-50% меньше рутинных задач.
🔸 Качество: меньше багов в продакшене.
🔸 Доступность: новым разработчикам проще входить в экосистему.


⚠️ Требования:
🔸 Mac на Apple Silicon (M1+).
🔸 Xcode 26 (минимум).


💡 Вывод:
Xcode 26 — это не просто обновление, а смена парадигмы. Теперь ИИ берет на себя шаблонные задачи, оставляя вам творческую часть — архитектуру и инновации.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥24👍117👏1
🔢 SwiftUI: отступы для секций в List для iOS 26+.

В SwiftUI появился долгожданный инструмент для точного контроля отступов в секциях List — модификатор listSectionMargins(). Теперь можно гибко настраивать отступы для отдельных секций, не прибегая к костылям.

🤔 Как это работает?
Модификатор принимает:
🔸 edges — стороны для отступов (по умолчанию .all).
🔸 length — величина отступа в точках.

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

List {
Section("Новости") {
Text("Свежие обновления")
}
.listSectionMargins(.horizontal, 20) // Отступы по бокам

Section("Профиль") {
Text("Настройки")
}
.listSectionMargins(.top, 10) // Отступ сверху
}


Ключевые особенности:
🔹 Переопределяет стандартные отступы: заменяет дефолтные отступы, заданные стилем списка.
🔹 Работает с заголовками/подвалами: отступы применяются вокруг header и footer секции.
🔹 Гибкость: можно задавать для конкретных сторон (.horizontal, .vertical, .top и т.д.) или для всех сторон сразу (.all).
🔹 Не влияет на отступы между ячейками (для этого по-прежнему используем listRowSpacing).

⚠️ До iOS 26 приходилось использовать:
🔸 Неочевидные комбинации padding() + listRowInsets().
🔸 Кастомные разделители.
🔸 Костыли с GeometryReader.

Теперь всё решается одним модификатором!

listSectionMargins() — это отличное дополнение для тонкой настройки списков!

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥25👍96👀2
🔢 Class vs Actor в Swift: ключевые отличия.

В Swift и классы, и actor используются для создания ссылочных типов, но с разными целями. Главное отличие — в потокобезопасности. Actor появились в Swift 5.5 как часть Concurrency.

1️⃣ Классы (class):
🔹 Не потокобезопасны: доступ к свойствам и методам из разных потоков может привести к гонкам данных.
🔹 Поддерживают наследование: можно создавать подклассы.
🔹 Используются для общего состояния: подходят для объектов, которые не требуют синхронизации.

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

class Counter {
var value = 0

func increment() {
value += 1 // Опасность при вызове из разных потоков
}
}


2️⃣ Actor:
🔹 Потокобезопасны: Swift автоматически сериализует доступ к свойствам и методам (очередь задач).
🔹 Нет наследования: нельзя наследовать от actor.
🔹 Для изолированного состояния: идеальны для данных, которые изменяются из разных потоков.

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

actor SafeCounter {
private var value = 0

func increment() {
value += 1 // Безопасно (автоматическая синхронизация)
}

func currentValue() -> Int {
return value
}
}


♣️ Пример работы с Actor:

let counter = SafeCounter()

Task {
await counter.increment()
let value = await counter.currentValue()
print(value) // 1
}


⚠️ Важно:
🔸 Для вызова методов actor нужен await.
🔸 Свойства actor по умолчанию private.

💡 Вывод:
🔹 Классы — для простых объектов без многопоточности.
🔹 Actor — для данных, изменяемых из разных потоков (счетчики, кеши, состояния).

Если нужно потокобезопасное решение — выбирайте actor. Если важна гибкость и наследование — class.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25🔥107🫡1
👨‍💻 Чем на самом деле отличается джун от сеньора?
И почему стаж ≠ опыт.

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


1️⃣ Видение контекста.

Джун:
🔹 Фокусируется на своей задаче.
🔹 Пишет код по ТЗ, не всегда понимая, как он влияет на систему.

Сеньор:
🔹 Видит связи между компонентами.
🔹 Спрашивает: как это повлияет на поддержку, бизнес или пользователей?
🔹 Выбирает простые, но надежные решения, даже если они менее модные.


2️⃣ Ответственность за результат.

Джун:
🔹 Исправляет баги, если их явно указали.
🔹 Может переложить проблему: «Это не мой модуль».

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


3️⃣ Работа в команде.

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

Сеньор:
🔹 Находит слабые места в команде и помогает их закрыть.
🔹 Дает тактичные замечания при code review, объясняет почему следует внести исправления с аргументами, а не только указывает на проблемный код.
🔹 Говорит: давай разберем твой подход вместе, вместо ты неправ.


4️⃣ Выбор технологий.

Джун:
🔹 Хочет использовать новейший стек, потому что так круто.
🔹 Пишет на SwiftUI, когда нужен UIKit (и наоборот).

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


5️⃣ Умение НЕ писать код.

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

Сеньор:
🔹 Избегает изучение лишней информации, которая никогда не пригодится.
🔹 Говорит: этот легаси работает — не трогаем или автоматизируем в следующем квартале.


6️⃣ Работа с неопределенностью.

Джун:
🔹 Ждет четких ТЗ.
🔹 Паникует, если требования меняются.

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


⚠️ Главное отличие.

Сеньор — это не про количество строк кода, а про:
Глубину понимания последствий своих решений.
Ответственность за продукт, а не за таски.
Мягкие навыки (коммуникация, менторство и т.д).

Как говорил один мудрый тимлид: джун думает, как написать. мидл — что написать. сеньор — стоит ли писать.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2812🫡7👀1
🍏 🏋️ Мое приложение для отказа от вредных привычек.

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

💚 Счетчик дней: вредные привычки.
Конечно, счетчик дней без вредных привычек — не новинка. Но я добавил уникальный функционал, которого не было у конкурентов:

Возможность отслеживать не только вредные, но и полезные привычки.
Поддержка iOS, watchOS, macOS и Android версии приложения.
Удобные виджеты для iOS и macOS.
Синхронизация данных между всеми устройствами пользователя.
Система рейтинга – пользователи могут соревноваться в отказе от курения и алкоголя.
Возможность выбора счетчиков привычек, которые следует отображать на главном экране приложения, на виджетах и на часах Apple Watch.
Отображение мотивирующих цитат по отказу от вредных привычек на главном экране приложения.

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

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


👨‍💻 Разработка:
🔹 Приложение «Счетчик дней: вредные привычки» для iOS, watchOS и macOS разработано на SwiftUI.
🔹 Версия для Android разработана на Flutter.
🔹 Серверную часть для приложения разрабатывал самостоятельно на PHP.

📊 На данный момент приложение имеет более 80 тысяч скачиваний в магазинах приложений.

📱 📱 Приложение доступно в магазинах приложений


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2018🔥10👏1
🔢 Расширенные текстовые возможности в SwiftUI с AttributedString.

На WWDC25 Apple представила новые API для работы с AttributedString в SwiftUI, позволяющие создавать мощные текстовые редакторы с гибким форматированием.

⚠️ Что нового?

Готовые стили:
🔹 Поддержка жирного текста, курсива, подчеркивания, зачеркивания.
🔹 Изменение размера шрифта и цвета текста.

Кастомные атрибуты:
🔹 Можно добавлять собственные правила форматирования.

Безопасное редактирование:
🔹 AttributedTextValueConstraint ограничивает допустимые атрибуты.
🔹 TextEditor автоматически применяет заданные правила.

Динамическое обновление:
🔹 SwiftUI корректно обрабатывает изменения текста и выделения.

🔗 Подробнее на сайте Apple

💡 Где это пригодится?
🔸 Редакторы статей/рецептов (как в демо WWDC).
🔸 Приложения для заметок с расширенным форматированием.
🔸 Чат-боты с поддержкой стилизованного текста.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23🔥9🙏7👀1
👨‍💻 ИТ-рынок сжался. Как теперь искать работу?

Ещё недавно компании боролись за разработчиков, а сегодня на одну вакансию — сотни резюме.

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

⚠️ Как пробиться даже в кризис?

1️⃣ Резюме — ваш пропуск на собеседование.
🔹 Важно иметь минимум 3 года коммерческого опыта (фриланс и пет-проекты считаются, но котируются меньше).
🔹 Цифры и факты вместо общих фраз. Не «оптимизировал приложение», а «снизил потребление памяти на 25%».
🔹 Если есть пробелы в опыте работы, лучше их закрыть фрилансом или пет проектами.
🔹 Проверьте резюме через ChatGPT или hh-аналитику — даже мелкие ошибки могут отсеять вас.
🔹 Приложите портфолио к резюме. Примеры ваших работ позволят оценить ваш опыт.

2️⃣ Собеседования — учимся играть по новым правилам.
🔹 Будьте готовы к лайвкодингу. Без умения решать задачи на глазах у интервьюера шансы равны нулю.
🔹 Тренируйте алгоритмы (LeetCode должен решаться на автомате).
🔹 Перед собеседованием обязательно ищите слитые разборы вопросов по компании (телеграм чаты, форумы, статьи в интернете).

3️⃣ Выделяться или проиграть.
Жирные офферы получают специалисты, умеющие продать себя. Разработчиков много, поэтому берут тех, кого видно. Вот несколько советов, как стать заметнее:
🔹 Ведите технический блог (даже 1 статья в месяц — уже очень хорошо).
🔹 Участвуйте в опенсорс-проектах (это новый must-have для middle+).
🔹 Делайте разборы кейсов в LinkedIn (работодатели это проверяют).
🔹 Выступайте публично, на ИТ мероприятиях или онлайн конференциях.

Медийность = доверие. Если о вас знают, шанс получить оффер гораздо выше.

4️⃣ Принять новые правила игры.
🔹 Рынок работодателя: вакансий меньше, чем кандидатов.
🔹 Жалобы не помогут: либо адаптируешься, либо останешься без оффера.
🔹 Компании ищут готовых специалистов: доучиваться за их счет не больше не выйдет.
🔹 Удалёнка для джунов почти умерла: готовьтесь к гибридному формату.
🔹 Зарплаты стабилизировались: зп 400к для мидлов осталась в 2023 году.
🔹 Слабые отсеиваются: но те, кто вкатывает, продолжают брать топовые предложения.

💡 Вывод:
Да, рынок уже не тот, но офферы всё ещё есть — их просто получают те, кто готовится лучше других и вкладывается в свою экспертность.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
30🙏13👍8👀1
🔢 NavigationStack в SwiftUI: современная навигация.

NavigationStack — это новый (с iOS 16+) и более мощный способ организации навигации в SwiftUI. В отличие от NavigationView, он дает полный контроль над стеком экранов и поддерживает сложные сценарии.

Основные возможности:
🔹 Программное управление стеком экранов (пуш, поп, переход к корню).
🔹 Глубокая навигация по ссылкам (например, app://products/123).
🔹 Кастомные переходы между экранами.
🔹 Поддержка NavigationPath для хетерогенных данных в стеке.

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

struct ContentView: View {
@State private var path = NavigationPath()

var body: some View {
NavigationStack(path: $path) {
List {
NavigationLink("Экран 1", value: 1)
NavigationLink("Экран 2", value: "Текст")
}
.navigationDestination(for: Int.self) { value in
Text("Число: \(value)")
}
.navigationDestination(for: String.self) { value in
Text(value)
}
}
}
}


1️⃣ NavigationPath.

Тип-обертка для управления стеком. Может содержать разные типы данных:

path.append(1)
path.append("ABC")
path.removeLast()


2️⃣ navigationDestination(for:).

Определяет, какой экран показывать для каждого типа данных:

.navigationDestination(for: Product.self) { product in
ProductView(product: product)
}


3️⃣ Программная навигация.


Button("Перейти к экрану 3") {
path.append(3)
}

Button("Назад") {
path.removeLast()
}

Button("В корень") {
path.removeLast(path.count)
}


⚠️ Глубокая навигация.

Можно привязать навигацию к URL:

NavigationStack(path: $path) {
}
.onOpenURL { url in
if url.path == "/products/123" {
path.append(Product(id: 123))
}
}


💡 Рекомендации:
🔸 Для iOS 15 и ниже используйте NavigationView.
🔸 Для модальных окон — sheet или fullScreenCover.
🔸 Не смешивайте NavigationStack и NavigationView.

NavigationStack — это эволюция навигации в SwiftUI. Он идеален для приложений со сложной навигацией, программного управления историей экранов и лубоких ссылок.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28🔥12🤝61🫡11
This media is not supported in your browser
VIEW IN TELEGRAM
🔨 Xcode 26: ИИ может документировать фрагмент кода!

Установите бета-версию macOS Tahoe и Xcode 26, если хотите попробовать эту функцию.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2912👍8🤯11
🔗 Поддержка Universal Links на iOS.

Universal Links — это удобный способ открывать контент вашего приложения прямо из веб-ссылок. Они обеспечивают более плавный пользовательский опыт и упрощают обмен контентом.


🤔 Что нужно для настройки?


1️⃣ Серверная часть:

🔹 На вашем сервере должен быть доступен файл apple-app-site-association в формате JSON.
🔹 В нём указываются appID вашего приложения и разрешённые пути (paths).

♣️ Пример файла apple-app-site-association:

{
"applinks": {
"details": [
{
"appID": "TEAMID.hardworker.it",
"paths": [
"/shop",
"/card",
"/profile"
]
}
]
}
}


Где appID указывается в формате teamId.bundleId. paths содержит пользовательские пути, которые должны обрабатываться в приложении.


2️⃣ Настройка проекта Xcode:

🔹 Добавьте Associated Domains в Capabilities.
🔹 Укажите ваш домен с префиксом applinks:, например:

applinks:your-domain.com



3️⃣ Тестирование:

🔹 Откройте ссылки на реальном устройстве (в Notes, Safari, через сообщения или Telegram).
🔹 Иногда требуется переустановка приложения или перезагрузка устройства, чтобы изменения вступили в силу.

Ожидается обработка следующих ссылок:

https://your-domain.com/shop
https://your-domain.com/card
https://your-domain.com/profile



💡 Вывод:

Universal Links делают навигацию удобнее, а ваш сервис — доступнее.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍279🔥52🙏1
👨‍💻 Почему в 2025 году сопроводительное письмо, тестовые задания и проекты на GitHub важны для устройства на работу.

Недавно Дэвид Ханссон (создатель Ruby on Rails) в интервью Лексу Фридману раскрыл два ключевых критерия при найме:
🔹 Качество кода в тестовом задании.
🔹 Мотивационное письмо.

Казалось бы — ничего нового. Но давайте разберём, почему именно эти пункты стали критически важными в 2025 году.


1️⃣ Тестовое задание: как перестать быть «подозрительным» кандидатом.
С появлением ИИ ассистентов вроде GitHub Copilot и ChatGPT работодатели стали скептически относиться к идеально написанным, но безликим решениям.

⚠️ Что проверяют:
🔹 Стиль кода (если он похож на шаблонный код от ИИ — это красный флаг).
🔹 Неочевидные решения (вас обязательно спросят: «Почему выбрали именно это решение?»).
🔹 Коммиты (история изменений показывает ход ваших мыслей).


2️⃣ Сопроводительное письмо: ваш секретный инструмент.
В 2025 году резюме без сопроводительного письма — как код без комментариев: вроде бы всё понятно, но чего-то не хватает. HR-ы и тимлиды признаются: «Письмо решает, кого пригласить, когда 100+ кандидатов с одинаковым опытом».

🤔 Почему письмо важнее, чем кажется?
🔸 Показывает вашу человечность: ИИ пишет резюме, но не может искренне объяснить, почему вы мечтаете работать в этой компании.
🔸 Раскрывает soft skills: Удалённая работа требует чёткой письменной коммуникации.
🔸 Компенсирует недостатки резюме: Нет коммерческого опыта или пробелы в резюме? Расскажите о причинах и пет проектах.

⚠️ Структура сопроводительного письма:
🔹 Персонализация: общие письма для всех компаний не работаю, нужна привязка к конкретной компании, куда вы откликаетесь.
🔹 Почему вы? Привяжите свой опыт к конкретной боли компании, которую необходимо решить.
🔹 Почему они? Докажите что вы реально заинтересованы в работе в данной компании, знакомы с ее историей, пользуетесь их продуктами и знакомы с технологиям, которые в ней используются.

💡 Вывод:
Хорошее письмо — это ваш голос в тишине. В 2025 году его отсутствие равноценно фразе «Мне всё равно, куда устраиваться».


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
20👍16🔥9👀11
🔢 Работа с JSON в Swift: Codable, Encodable и Decodable.

Swift предлагает удобные протоколы для преобразования объектов в JSON и обратно. Разберём, как это работает.


1️⃣ Основные протоколы.

🔹 Decodable: только декодирование (JSON → объект).
🔹 Encodable: только кодирование (объект → JSON).
🔹 Codable: и то, и другое (typealias для Decodable & Encodable).


struct User: Codable {
var name: String
var age: Int
}



2️⃣ Декодирование (JSON → объект).

Используем JSONDecoder:

let json = """
{
"name": "Иван",
"age": 30
}
"""

guard let jsonData = json.data(using: .utf8) else { return }

do {
let user = try JSONDecoder().decode(User.self, from: jsonData)
print(user.name) // "Иван"
} catch {
print("Ошибка: \(error)")
}


⚠️ Особенности:

🔸 Имена свойств должны совпадать с ключами JSON (или использовать CodingKeys).
🔸 Типы данных должны соответствовать.


3️⃣ Кодирование (объект → JSON).

Используем JSONEncoder:

let user = User(name: "Мария", age: 25)

do {
let jsonData = try JSONEncoder().encode(user)
let jsonString = String(data: jsonData, encoding: .utf8)
print(jsonString ?? "")
// {"name":"Мария","age":25}
} catch {
print("Ошибка: \(error)")
}


⚠️ Настройки:


let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted // Красивый вывод
encoder.dateEncodingStrategy = .iso8601 // Формат даты



4️⃣ Кастомные ключи (CodingKeys).

Если имена в JSON не совпадают со свойствами:

struct Product: Codable {
var productName: String
var price: Double

enum CodingKeys: String, CodingKey {
case productName = "product_name_title"
case price
}
}



5️⃣ Вложенные структуры.

JSON:

{
"user": {
"name": "Анна",
"age": 28
}
}


Swift:

struct Response: Codable {
var user: User
}

struct User: Codable {
var name: String
var age: Int
}



7️⃣ Обработка опциональных значений.


struct Profile: Codable {
var name: String
var bio: String? // Опциональное поле
}


Если поля нет в JSON, свойство получит значение nil.


8️⃣ Игнорирование полей.

Пропускаем ненужные свойства:

struct Settings: Codable {
var theme: String
var fontSize: Int

// Не включаем в Codable
var temporaryFlag: Bool = false
}



9️⃣ Ручная реализация.

Для сложных случаев можно реализовать методы вручную:

struct Custom: Codable {
var id: UUID
var tags: [String]

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
tags = try container.decode([String].self, forKey: .tags)
}

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(tags, forKey: .tags)
}
}



💡 Вывод:

🔸 Используйте Codable для большинства задач.
🔸 Настраивайте сложные случаи через CodingKeys.
🔸 Для нестандартных форматов реализуйте методы вручную.

Теперь вы легко сможете работать с любым JSON в Swift!

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
26🙏19👍511
🔨 Apple представила Retention Messaging API позволяющий удержать подписчиков.

Компания Apple анонсировала новый Retention Messaging API, который поможет разработчикам снизить отток подписчиков. Теперь можно гибко настраивать сообщения для пользователей, которые хотят отменить подписку.


⚠️ Что это дает?

С помощью данного API можно показывать 4 типа сообщений:

🔹 Текстовое: напоминание о преимуществах подписки.
🔹 Текст + изображение: визуальное убеждение.
🔹 Смена тарифа: предложение перейти на другой тарифный план.
🔹 Промо-оффер: скидка или спецусловия.

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


🤔 Как это работает?

🔸 Пользователь нажимает «Отменить подписку».
🔸 Система запрашивает у вашего сервера подходящее сообщение (или использует стандартное).
🔸 Пользователь видит предложение: оставить подписку, перейти на другой тариф или воспользоваться скидкой.


👨‍💻 Как подключить?

🔹 Загрузите тексты и изображения в App Store Connect.
🔹 Настройте дефолтные сообщения (текст, либо текст + картинка).
🔹 Реализуйте серверный endpoint для динамического выбора сообщений.


🔗 Официальная документация на сайте Apple


💡 Вывод:

Retention Messaging API — это не просто новая фича, а стратегический инструмент для монетизации. Вместо пассивного наблюдения за оттоком подписчиков вы получаете:

🔸 Контроль над последним touchpoint перед отменой.
🔸 Данные для анализа поведения пользователей.
🔸 Рычаг влияния на ключевое бизнес-метрики.

Теперь ваша реакция на отток — не постфактум, а в момент принятия пользователем решения.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
26🔥19👍83
Очень интересный канал про IOS разработку 👉 @error_nil, в основном все в формате видеоуроков, много полезного материала, интересные обсуждения, XCode проекты и тд, советую подписаться 👍
👍104😁3🔥1🤔1
🔢 XCTest уходит в прошлое? Разбираем плюсы и минусы Swift Testing.

С выходом Swift Testing многие задумались о миграции с XCTest. Но так ли всё гладко, как обещает Apple? Давайте разберём реальные подводные камни и лайфхаки для перехода.


🤔 Чем Swift Testing отличается от XCTest?

1️⃣ Обнаружение тестов.
🔹 XCTest: использует XCTestCase + Objective-C runtime.
🔹 Swift Testing: макросы @Test + Swift ориентированный подход.

2️⃣ Выполнение тестов.
🔹 XCTest: выполняется последовательно (один за другим).
🔹 Swift Testing: выполняется параллельно (каждый тест в отдельной Task).

3️⃣ Синтаксис.
Разница в коде:

// XCTest  
func testLogin() { XCTAssertEqual(result, expected) }

// Swift Testing
@Test func login() { #expect(result == expected) }



⚠️ Главные проблемы миграции.

1️⃣ Ассерты вне контекста Task.
Swift Testing требует, чтобы проверки (#expect) выполнялись только внутри Task.

// Старая схема (XCTest)
func testAsync() {
DispatchQueue.main.async {
XCTAssertEqual(result, 42)
}
}

// Неправильная миграция (упадёт в Swift Testing)
@Test func asyncTest() {
DispatchQueue.main.async {
#expect(result == 42) // Ошибка: вне контекста Task
}
}

// Правильная миграция
@Test func asyncTest() async { // 1. Объявляем async тест
let result = await withCheckedContinuation { continuation in
DispatchQueue.main.async {
continuation.resume(returning: 42) // 2. Возвращаем результат в контекст Task
}
}

#expect(result == 42) // 3. Проверяем УЖЕ внутри Task-контекста
}


Ключевые моменты:
🔸 Тест должен быть async — это автоматически создаёт контекст Task.
🔸 Все асинхронные операции, которые не поддерживают async/await оборачиваются в withCheckedContinuation.
🔸 #expect вызывается после получения результата, но внутри области теста.

2️⃣ Проблемы с общим состоянием.
Параллельное выполнение тестов могут вызвать гонки данных.

♣️ Пример:

actor Counter {
var count = 0

func increment() {
count += 1
}
}

@Test func testA() async {
await Counter.shared.increment()
#expect(await Counter.shared.count == 1) // Может упасть, если testB запустится раньше!
}

@Test func testB() async {
await Counter.shared.increment()
}


Решение:
Использование @Suite(.serialized) для последовательного выполнения:

@Suite(.serialized)
struct CriticalTests {
@Test func testA() {
}

@Test func testB() {
}
}



3️⃣ Наследование тестов не работает.
В XCTest можно было наследовать XCTestCase и автоматически получать все тесты родителя. В Swift Testing так не работает — тесты нужно дублировать.

Что делать:
🔸 Для простых сценариев использовать параметризованные тесты.
🔸 Для сложных, пока оставьте XCTest и мигрируйте постепенно.


💡 Вывод:
На Swift Testing стоит переходить если у вас современный проект, который использует Swift Concurrency и вам необходимо параллельное выполнение тестов.

Мой совет: Начинайте с гибридного подхода — подключайте Swift Testing для новых модулей, а старые тесты оставляйте в XCTest.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
26👍193🔥2
👨‍💻 Пять фатальных ошибок в карьере разработчика.

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


1️⃣ Думать вместо делать.
«Сначала изучу весь SwiftUI, потом начну писать код» — знакомо?

Вспоминаю, как сам начинал: вместо того чтобы бесконечно изучать теорию, я просто пробовал писать код. Да, он был кривой, да, с ошибками, но это работало! Сейчас многие застревают на этапе «сначала выучу всё идеально, потом начну». Так не бывает. Лучший способ научиться: делать, ошибаться и исправлять.


2️⃣ Слушать не тех людей.
«Мой друг-джун сказал, что VIPER — это мусор».

Когда я только начинал, один «опытный» знакомый уверял меня, что Swift — это модно только для мажоров, а за Java будущее и он будет использоваться везде вечно. Хорошо, что я не поверил. Часто советы дают те, кто сам ещё мало что понимает. Ищите советов среди тех, кто реально добился результатов в вашей сфере.


3️⃣ Бояться критики.
«Мой код идеален, это тимлид ничего не понимает!»

Да, неприятно, когда говорят, что твой код плох. Но именно так и растёшь! Я научился воспринимать замечания не как личное оскорбление, а как бесплатный урок. Заводил даже отдельный блокнот, куда записывал все конструктивные замечания — очень помогает не наступать на те же грабли.


4️⃣ Лениться и откладывать на потом.
«Сегодня устал, завтра начну».

Сколько раз вы откладывали изучение новой технологии, потому что «еще есть время»? Или обещали себе дописать пет проект, но в итоге смотрели сериалы? Я сам через это проходил. Правда в том, что идеального момента не будет никогда. Каждый отложенный месяц — это упущенные возможности, проекты и даже зарплата. Технологии меняются быстрее, чем мы собираемся их изучить.


5️⃣ Бояться перемен.
«Лучше синица в руках, чем журавль в небе. Останусь там, где хоть что-то платят».

🔹 Страх сменить проект: «а если новый окажется хуже».
🔹 Боязнь попросить повышение: «а вдруг откажут».
🔹 Страх откликнуться на интересную вакансию: «там же нужно будет учить новое!».

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

Эти страхи кажутся разумными только в нашей голове. Со стороны они выглядят именно тем, чем и являются — отговорками, которые мешают нам расти.

В IT безопаснее прыгнуть в неизвестность, чем оставаться в зоне комфорта. Каждый раз, когда вы говорите «еще не готов», кто-то другой говорит «да» и получает ваши потенциальные бенефиты.


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


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
26👍16👀2🔥1🗿11
🎨 Вышли официальные наборы компонентов дизайна iOS 26 и iPadOS 26.

Все обновленные компоненты и гайды доступны на сайте Apple.


🤔 Что внутри?

🔹 UI Kit (Figma, Sketch).
🔹 App Icon Template (Sketch, Photoshop, Illustrator, Figma).


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍3👀1🗿11
🔢 Современные механизмы блокировок в Swift: Mutex и Synchronization Framework.

В Swift существует несколько способов защиты данных от гонки (data races): NSLock, DispatchSemaphore, последовательные очереди (DispatchQueue). Но на WWDC24 компания Apple представила новый Synchronization Framework, включающий современный Mutex – стандартизированную блокировку взаимного исключения.


🤔 В чем разница между Lock и Mutex?
🔸 Lock: общее название механизмов синхронизации (например, NSLock, os_unfair_lock).
🔸 Mutex: частный случай блокировки, гарантирующий, что только один поток может владеть ресурсом в данный момент.


Ключевая особенность Mutex:
🔹 Строгое владение – разблокировать может только тот поток, который заблокировал.
🔹 Поддержка Sendable, что делает его удобным для Swift Concurrency.


♣️ Пример использования.
Пример защиты счетчика:


final class Counter {
private let count = Mutex<Int>(0) // Обернули значение в Mutex

var currentCount: Int {
count.withLock { $0 } // Безопасное чтение
}

func increment() {
count.withLock { $0 += 1 } // Атомарная операция
}

func decrement() throws {
try count.withLock {
guard $0 > 0 else { throw Error.reachedZero }
$0 -= 1
}
}
}



🆚 Mutex vs Actor.
🔸 Actor: идеален для асинхронного доступа, но требует await.
🔸 Mutex: синхронный, подходит для legacy кода или когда нельзя использовать async/await.


⚠️ Когда выбирать Mutex?
🔸 Нужна мгновенная синхронная блокировка.
🔸 Работа с не Sendable типами (например NSBezierPath).
🔸 Интеграция с кодом, не поддерживающим Concurrency.


💡 Важно:
🔹 Доступен с iOS 18 и macOS 15.
🔹 Не заменяет Actor, а дополняет инструментарий для работы с многопоточностью.

Mutex из Synchronization Framework – это современный, безопасный и эффективный способ защиты данных в Swift.


➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥1141🗿11