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

В Swift современный подход к многопоточности: Structured Concurrency — позволяет легко управлять асинхронными операциями, сохраняя читаемость кода. Рассмотрим два ключевых сценария: последовательное и параллельное выполнение.

1️⃣ Последовательное выполнение.
Когда задачи зависят друг от друга или должны выполняться по очереди:

func fetchData() async {
// Сначала загружаем аккаунты, затем задачи
let accounts = await fetchAccounts()
let tasks = await fetchTasks(accounts: accounts)

print("Аккаунты: \(accounts)")
print("Задачи: \(tasks)")
}


⚠️ Особенности:
🔸 Выполняется пошагово: fetchAccounts()fetchTasks()
🔸 Подходит, если второй запрос требует данных из первого.
🔸 Простота отладки (очевидный порядок выполнения).

2️⃣ Параллельное выполнение.
Когда задачи независимы и можно сэкономить время, выполняя их одновременно:

func fetchData() async {
// Параллельный запуск
async let accountsRequest = await fetchAccounts()
async let tasksRequest = await fetchTasks()

// Ожидаем результаты
let (accounts, tasks) = await (accountsRequest, tasksRequest)

print("Аккаунты: \(accounts)")
print("Задачи: \(tasks)")
}


⚠️ Особенности:
🔸 Обе функции запускаются одновременно.
🔸 Общее время выполнения ≈ времени самой долгой задачи.
🔸 async let создает параллельное подзадачи.
🔸 Результаты доступны только после await.

Ключевые принципы Structured Concurrency:

Иерархия задач:
🔹 Родительская задача ждет завершения дочерних (async let).
🔹 Отмена родительской отменяет и дочерние.

Безопасность:
🔹 Компилятор контролирует await, предотвращая deadlock.
🔹 Ошибки распространяются корректно.

Эффективность:
🔹 Система сама решает, сколько потоков использовать.
🔹 Нет ручного управления (DispatchQueue не нужен).

💡 Вывод:
🔸 await — для последовательного кода.
🔸 async let — для параллельных операций.
🔸 Structured Concurrency делает асинхронный код предсказуемым

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

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
26👍13👀1
🇷🇺 🍏 Россия требует от Apple открыть iPhone для RuStore.

Владимир Путин сегодня подписал закон, который обязывает Apple разрешить установку российского магазина приложений RuStore на iPhone.

Теперь производителям запрещено блокировать его загрузку на устройства, продаваемые в России. Если RuStore установлен (даже если вы скачали его сами), Apple не может замедлять его работу, мешать обновлять приложения, ограничивать платежи или ухудшать работу смартфона из-за российского магазина приложений.

Несоблюдение этих правил будет считаться нарушением прав потребителей — это грозит серьезными штрафами.
Закон вступает в силу 1 сентября 2025 года.

📱 Но главное: согласится ли Apple?
Компания всегда строго охраняла свою экосистему, и неизвестно, как она отреагирует на требование открыть iPhone для стороннего магазина.

👨‍💻 Что я думаю?
Лично мне кажется, что Apple всё же разрешит RuStore. Россия — важный рынок, и компания вряд ли захочет рисковать штрафами или уходом с него. Да, их система всегда была закрытой, но ради бизнеса они могут пойти на уступки — как уже делали в других странах.

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

NavigationView — это основной компонент для организации навигации в SwiftUI приложениях. Он позволяет создавать иерархические переходы между экранами, похожие на стандартные UINavigationController в UIKit.

Основные возможности:
🔹 Стековая навигация (push/pop).
🔹 Автоматическая кнопка "Назад".
🔹 Поддержка заголовков и панелей инструментов.

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

struct MenuView: View {
var body: some View {
NavigationView {
List {
NavigationLink("Первый экран", destination: FirstScreen())
NavigationLink("Второй экран", destination: SecondScreen())
}
.navigationTitle("Главное меню")
}
}
}


⚠️ Ключевые модификаторы:
🔸 navigationTitle - задает заголовок экрана.
🔸 navigationBarItems - добавляет кнопки в панель навигации.
🔸 navigationBarHidden- скрывает панель навигации.

NavigationLink - основной способ перехода между экранами:

NavigationLink(destination: FirstScreen()) {
Text("Первый экран")
}


💡 Советы по использованию:
🔹 Не вкладывайте несколько NavigationView друг в друга.
🔹 Для сложной навигации используйте NavigationStack.
🔹 Помните, что стиль навигации может отличаться на разных платформах (iOS, macOS).

NavigationView значительно упрощает реализацию навигации по сравнению с UIKit, сохраняя при этом привычный пользователям iOS интерфейс.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1911🤝4
🔢 Автоматическое отслеживание изменений с помощью @Observable: магия SwiftUI теперь доступна в UIKit.

С iOS 18 и macOS 15 UIKit получил скрытую фичу, которая меняет правила игры — автоматическое отслеживание изменений данных через @Observable. Больше не нужны ручные вызовы setNeedsLayout() — интерфейс теперь обновляется сам!

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

Помечаем модель макросом @Observable:

import Observation

@Observable
class User {
var name = "Иван"
var unreadMessages = 0
}


Читаем данные в стандартных методах ViewController:

class ProfileVC: UIViewController {
let user = User()

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()

// UIKit автоматически отследит эти изменения
nameLabel.text = user.name
messagesCountLabel.text = "\(user.unreadMessages)"
}
}


Изменяем данные — интерфейс обновится автоматически:

@objc func buttonDidTap() {
// Значение messagesCountLabel обновится автоматически
user.unreadMessages += 1
}


Включаем отслеживание @Observable в Info.plist:

<key>UIObservationTrackingEnabled</key>
<true/>


В iOS 26 это работает из коробки без настройки.

⚠️ Важные нюансы:
🔸 Автоматическое отслеживание изменений работает в viewWillLayoutSubviews(), layoutSubviews() и новом методе updateProperties(), который вызывается перед layoutSubviews для оптимизации.
🔸 Обновление интерфейса после обновления данных возможно только в main thread.
🔸 Важно не забывать про retain cycles, при работе с @Observable.
🔸 Рекомендуется избегать обновление данных без необходимости, так как частое обновление интерфейса может сказаться на производительности приложения.

💡 Вывод:
Теперь UIKit умеет так же удобно обновлять интерфейс, как SwiftUI. Главное — правильно использовать @Observable и не забывать про потокобезопасность.

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍229🔥3
✌️ Продажу iPhone могут запретить в России, если Apple не пропустит RuStore.

Буквально недавно обсуждали, что никаких запретов в сторону Apple не ожидается, а вот вам и здравствуйте. В Госдуме сообщили, что в случае отказа Apple содействовать работе российского магазина приложений RuStore на своих устройствах, в отношении компании могут ввести санкции, вплоть до полного запрета продаж iPhone на территории России.

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

Переобулись уж очень быстро 😅

➡️ Подписаться на канал
Мобильный трудоголик
Please open Telegram to view this post
VIEW IN TELEGRAM
🗿28🤯12🫡3
🔨 Новый макрос #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